diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-01-25 12:57:36 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-01-25 12:57:36 +0000 |
| commit | 2b91c3d0af33099f7b260a41efac252655104c50 (patch) | |
| tree | 4636152e118d90381a584f2636da34efbe8dd568 /root/articles | |
| parent | correction in portfolio (diff) | |
| parent | update README.md (diff) | |
| download | mmm-2b91c3d0af33099f7b260a41efac252655104c50.tar.gz mmm-2b91c3d0af33099f7b260a41efac252655104c50.zip | |
Merge branch 'ba'
Diffstat (limited to 'root/articles')
139 files changed, 2474 insertions, 273 deletions
diff --git a/root/articles/$order b/root/articles/$order new file mode 100644 index 0000000..66aad40 --- /dev/null +++ b/root/articles/$order @@ -0,0 +1,3 @@ +mmmfs +xy-workshop +realities diff --git a/root/articles/mmmfs/$order b/root/articles/mmmfs/$order new file mode 100644 index 0000000..d58d878 --- /dev/null +++ b/root/articles/mmmfs/$order @@ -0,0 +1,14 @@ +title +abstract +table-of-contents +introduction +motivation +historical-approaches +framework +mmmfs +examples +evaluation +conclusion +references +ba_log +statement-of-originality diff --git a/root/articles/mmmfs/abstract/text$markdown+sidenotes.md b/root/articles/mmmfs/abstract/text$markdown+sidenotes.md new file mode 100644 index 0000000..c7d6c9c --- /dev/null +++ b/root/articles/mmmfs/abstract/text$markdown+sidenotes.md @@ -0,0 +1,14 @@ +abstract +======== + +Current end-user operating systems are based on a set of design principles and computing paradigms that make them +simple to use in some circumstances but are very inflexible for user customization and adaptation. In this thesis, these +limitations and design principles will be discussed and contrasted by an analysis of historic systems that solved these +issues by following different design goals. Based on this analysis, as well as further literature, an evaluation +framework for end-user computing systems is established. +The design and implementation of a new end-user computing system, which focuses on a file system with rich file types +and a type coercion system as its central paradigm, is discussed. Following this, the capabilities of the system are +demonstrated using multiple example use-cases. An evaluation of these examples as well as the system itself according +to the framework established earlier shows that the proposed system is indeed very flexible and useful for a wide +variety of uses involving multimedia content from various sources, although the system has many flaws that would hinder +widespread adoption. diff --git a/root/articles/mmmfs/ba_log/$order b/root/articles/mmmfs/ba_log/$order new file mode 100644 index 0000000..a77277a --- /dev/null +++ b/root/articles/mmmfs/ba_log/$order @@ -0,0 +1,15 @@ +start +2019-10-07 +2019-10-08 +2019-10-09 +2019-10-10 +2019-10-11 +2019-10-14 +2019-10-15 +2019-10-24 +2019-10-26 +2019-10-27 +2019-10-29 +2019-11-01 +2019-11-25 +2019-12-20 diff --git a/root/articles/mmmfs/ba_log/2019-10-07/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-07/text$markdown.md new file mode 100644 index 0000000..46c6892 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-07/text$markdown.md @@ -0,0 +1,40 @@ +Today I started working on the HTTP server that finds, converts and serves content stored in the (SQL) backend just-in-time (later the server could also cache content). + +The server can handle these types of requests: + +## Fileder Index Requests +A request like `GET /path/to/fileder/` (note the trailing slash) is used to query the contents of a fileder. +It solicits a JSON-encoded response that contains the full paths to all children of this fileder, as well as all facets currently stored, e.g: + + { + "children": [ + "/projects/vcv_mods", + "/projects/HowDoIOS", + "/projects/iii-telefoni", + "/projects/btrktrl", + "/projects/demoloops", + "/projects/VJmidiKit", + "/projects/gayngine", + "/projects/themer", + "/projects/chimpanzee_bukkaque" + ], + "facets": [ + ["", "text/moonscript -> fn -> mmm/dom"], + ["name", "alpha"], + ["title", "text/plain"] + ] + } + +## Facet Requests +A request like `GET /path/to/fileder/facet_name` is used to query a facet. +To differentiate a request for the 'unnamed' facet from an index request, unnamed facets are represented as a `:` character instead. +The type to ask for can be specified in a `MMM-Accept` header separately, it defaults to `text/html`. + +The server either sends back the (possibly converted) facet with a `200 OK` status, +or a `406 Not Acceptable` error if no conversion was possible. + +I also restructured the code a bit and moved some of the HTML-rendering code into the main mmmfs code. +Then I renamed the `text/html` type to `text/html+frag`, since it refers to only a fragment of HTML code, not a whole document, +and added a new *convert* from `text/html+frag` to `text/html` that wraps the fragment in the HTML template and style. + +the full code change is in commits [81e143f](https://git.s-ol.nu/mmm/commit/81e143fa8181a6adb58d7fba632bd31a13164410/) and [ad26c7c](https://git.s-ol.nu/mmm/commit/ad26c7c4e374f66a978f9946bbb083377f2224a6/) diff --git a/root/articles/mmmfs/ba_log/2019-10-08/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-08/text$markdown.md new file mode 100644 index 0000000..c10b75f --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-08/text$markdown.md @@ -0,0 +1,58 @@ +Today I mostly fixed the output/rendering of the 'live' server I implemented yesterday. + +I changed the URL scheme, it no longer uses headers, which made it hard to link to resources through `<link>` and `<script>` tags. +Instead the path, facet-name and type are now all part of the URI: + +| URI | fileder path | facet name | type | +| ---------------------------------------------- | ------------------ | --------------- | ------------------------------ | +| `/fileder/facet: type/subtype -> wrapped/type` | `/path/to/fileder` | `facet` | `type/subtype -> wrapped/type` | +| `/fileder/: some/type` | `/fileder` | (default facet) | `some/type` | +| `/fileder/alternate:` | `/fileder` | `alternate` | `text/html` (default type) | +| `/path` | `/path` | (default facet) | `text/html` (default type) | +| `/` | `/` | (default facet) | `text/html` (default type) | + +The fileder-index metadata was moved to a `?index` 'pseudofacet' (e.g. `/fileder/?index`). + +**EDIT 2019-10-09:** +> I will take this chance to show and hopefully explain the point of this all again: +> With the system running it is now possible to demonstrate the type-coercion that powers the system. +> +> In the system, every piece of data (the *facet*s) is stored together with it's *type*. +> When requesting data, it can of course be loaded with that *type*, yielding the data unmodified, +> but it is also possible to demand a different *type* that may be more useful to the receiving application. +> +> as an example we can take for example this article about one of the internal libraries for writing HTML documents: +> [`/meta/mmm.dom/`](/meta/mmm.dom/). +> +> The path `/meta/mmm.dom/` corresponds, according to the table above, to the default facet of the `/meta/mmm.dom` fileder, +> and since no type was specified, it is assumed that the browser wants a `text/html` document. +> The follwing path gives the same result, but makes this explicit: +> [`/meta/mmm.dom/:text/html`](/meta/mmm.dom/:text/html) +> +> now, instead of asking for the rendered HTML document, we can also ask for the source, which is of the type +> `text/moonscript -> mmm/dom` (a Moonscript file that evaluates to a website-fragment): +> [`meta/mmm.dom/:text/moonscript -> mmm/dom`](/meta/mmm.dom/:text/moonscript%20-%3E%20mmm/dom) +> +> the source code was written in MoonScript, which compiles to Lua before it is executed. +> We can also ask the server to do that for us: +> `text/lua -> mmm/dom` (a Lua file that evaluates to a website-fragment): +> [`meta/mmm.dom/:text/lua -> mmm/dom`](/meta/mmm.dom/:text/lua%20-%3E%20mmm/dom) +> +> or, we could ask for the generated html fragment, but without the full HTML layout around it - +> that would be the type `text/html+frag`, as mentioned in the last post: +> [`meta/mmm.dom/:text/html+frag`](/meta/mmm.dom/:text/html+frag) +> +> lastly, we could also ask the system to generate a link to this content, in the `text/html` format (`URL -> text/html`): +> [`meta/mmm.dom/:URL -> text/html`](/meta/mmm.dom/:URL%20-%3E%20text/html) +> this might seem somewhat redundant, since we need a link to access this link, +> but it can be useful when a component cannot work with binary data directly, e.g. when mentioning or embedding an image +> or a video file. + +I also added support to the server for serving static assets (e.g. the CSS stylesheet) from the `static` directory. +These files are accessible through the `/.static/` route (e.g. `/.static/main.css`), where they shouldn't interfere +with the mmmfs contents. +With the layout adjsuted to use these new paths, the live server now looks properly styled again too! + +Finally I worked on the Dockerfile and my deployment a bit, +so that my updates to the code will now be automatically applied to my test site, +which is available at [ba.s-ol.nu](//ba.s-ol.nu) (which might be where you are reading this right now!). diff --git a/root/articles/mmmfs/ba_log/2019-10-09/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-09/text$markdown.md new file mode 100644 index 0000000..702620d --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-09/text$markdown.md @@ -0,0 +1,9 @@ +I added another driver/store that loads files straight from disk \[[`86bbe80`][86bbe80]\], +and made the server load the fileder tree when it receives a request for content, rather than loading the whole tree up front. +This means that I can work on the content again and see changes in the browser without restarting the server every time \[[`97bc4a0`][97bc4a0]\], +This feature should be made unnecessary by the in-page editing feature, but until then it's important for my workflow. + +I also started cleaning up the mmmfs article a bit, and integrating this project log in a way that will make it available online soon. + +[86bbe80]: https://git.s-ol.nu/mmm/commit/86bbe805a7ec49a8b891412713ea43d6e46d0d73/ +[97bc4a0]: https://git.s-ol.nu/mmm/commit/97bc4a0d8d866026905eac6f0ba08b75f166219a/ diff --git a/root/articles/mmmfs/ba_log/2019-10-10/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-10/text$markdown.md new file mode 100644 index 0000000..010f861 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-10/text$markdown.md @@ -0,0 +1,46 @@ +Today I moved the static resources needed by the web-frontend into the content of the mmmfs itself: +The server doesn't make an exception for static files anymore (as described in [a previous update][2019-10-08]), +but rather the files are just in a fileder called `static` now, and properly typed, here: + +- [/static/style/](/static/style/:%20text/html+interactive) +- [/static/mmm/](/static/mmm/:%20text/html+interactive) + +This removed a big exception and left the server implementation much cleaner and shorter, as can be seen in the corresponding commit [`005cc9b`][005cc9b]. + +I also changed the route syntax introduced in [`2019-10-08`][2019-10-08] for getting the fileder index, +now instead of being hard-coded to return a JSON value at `?index` \[[`b36a1a6`][b36a1a6]\]. +`?index` is treated as a pseudo-facet that can be requested in different types, just like real facets. +I also added a second pseudo-facet `?tree`, which works like `?index`, except that it recurses and includes +all content below the current fileder, rather than just including the child-fileders. + +Here are some example links for viewing these: + +- [`/?index: text/html`](/?index:%20text/html) +- [`/articles/mmmfs/ba_log/?index: text/html`](/articles/mmmfs/ba_log/?index:%20text/html) + +Finally I added a third pseudo-facet called `?interactive` that renders the Inspector that the old page ran on, +allowing to inspect raw facets, and bringing back the navbar \[[`9ab2f0f`][9ab2f0f]\]. + +Now that there was a way to serve the Browser to the client again, I got to work on fixing it there. +This involved a bigger changes in the shared mmm internals: + +Up to this point, for each request to render a fileder, the server would load that fileder, +with all its facets and their values, as well as all children and their facets and children recursively. +That means that when the root fileder is rendered, currently 120MB of data have to be loaded from disk (or a database). +Now that the client can render content within the web browser again, that would be even worse due to the network delay. + +To solve this, the Fileder implementation now lazy-loads \[[`9632233`][9632233]\]. +When a Fileder is created, it initially knows only its path, but doesn't know which facets or children it contains. +As soon as that data is attempted to be accessed, the fileder loads in the list of its children and facets from the datastore. +The facet contents are loaded only when they are actually needed to fulfill a data request or conversion. + +With this need for optimization taken care of, I added a new datastore (`web`) \[[`91546d1`][91546d1]\], that can run on the client. +Instead of directly accessing a database or physical file system, like the `sql` and `fs` stores, the `web` store delegates all +requests to the server APIs I have been building, such as the new `?index` pseudo-facet. + +[2019-10-08]: /articles/mmmfs/ba_log/2019-10-08/ +[005cc9b]: https://git.s-ol.nu/mmm/commit/005cc9b3914128267017620984aee921999e173f/ +[b36a1a6]: https://git.s-ol.nu/mmm/commit/b36a1a6c61a6e8bff156ce4e2dc66fe8ed8cd95e/ +[9ab2f0f]: https://git.s-ol.nu/mmm/commit/9ab2f0fe3a1a043300536a057bafe5058d987d7f/ +[9632233]: https://git.s-ol.nu/mmm/commit/9632233c16a26f017c648faf36a6b26833e62f2e/ +[91546d1]: https://git.s-ol.nu/mmm/commit/91546d12919736b08567d7174bf1063cab0838f0/ diff --git a/root/articles/mmmfs/ba_log/2019-10-11/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-11/text$markdown.md new file mode 100644 index 0000000..0b58c75 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-11/text$markdown.md @@ -0,0 +1,30 @@ +Yesterday I got client-side access to the whole mmmfs tree to work via the new `web` datastore, +but the requests were still extremely inefficient. +This was because the organisation of the interface between the `Fileder` implementation and the datastore, +which required the Fileder to make two separate requests to `?index` to fetch its children and facets, +and also couldn't take advantage of the `?tree` pseudo-facet to bundle together multiple indexes in a single request. + +To fix this I added a new datastore method called `get_index` that returns both facet and child information \[[`e2a4257`][e2a4257]\] +The Fileder implementation now uses this method instead of asking individually for the two pieces of information +when lazy-loading fileder contents. +The `get_index` method can also be instructed to recursively load to a fixed depth. +A Fileder can also be instantiated using such a nested index, +which causes it to immediately preload up to the same depth without the need for fetching more data. +This allows some more optimizations, like having the client preload 3-levels deep when it launches, +which seems like a decent heuristic of the data actually required for most pages and minimizes load time. + +I also added some tests for the `Key` class that I use in many different places to represent facet names and types \[[`782d072`][782d072]\]]. + +The `?interactive` pseudo-facet from yesterday was changed to the `text/html+interactive` type instead \[[`8cdf5d4`][8cdf5d4]\]. +This was a bit of a tough decision, because it is a bit un-idiomatic: rendering the browser page still requires an exception in the browser. +In the end the motivation for the change was that it should be possible, +for user ergonomics, to link to the interactive view of a given facet of a given fileder. +With `?interactive` being a facet, it wasn't possible to specify the facet without jumping out of the adressing system. +With these updates on the other hand it is possible to link fo example: + +- to the main content of the root fileder, as an interactive view: [`/: text/html+interactive`](/:%20text/html+interactive) +- to the page title of the root fileder, as an interactive view: [`/title: text/html+interactive`](/title:%20text/html+interactive) + +[e2a4257]: https://git.s-ol.nu/mmm/commit/e2a4257fc05d37822df2b7bbe0f587645375edf2/ +[782d072]: https://git.s-ol.nu/mmm/commit/782d0725f3f29eaa7d4a12213fb00c6643795348/ +[8cdf5d4]: https://git.s-ol.nu/mmm/commit/8cdf5d4a363ba99a6356e7e1dfe0dfb39e6fb13e/ diff --git a/root/articles/mmmfs/ba_log/2019-10-14/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-14/text$markdown.md new file mode 100644 index 0000000..e42f8be --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-14/text$markdown.md @@ -0,0 +1,101 @@ +I finally added a better type-conversion-path-finding algorithm \[[`deb21aa`][deb21aa]\]. +The old algorithm only took into consideration how many steps it took to get from type A (stored on disk) to type B (requested). +This could lead to problems, for example in this situation: + +On Disk: `text/moonscript -> fn -> mmm/dom` (a moonscript file that contains a function that returns a bit of UI) +Requested: `mmm/dom` +Known Conversions: +1. `text/moonscript` to `mmm/dom` (displays the source code with highlighting) +2. `text/moonscript -> ???` to `???` (evaluates the moonscript file) +3. `fn -> ???` to `???` (calls the function, providing access to children and other facets) + +Since conversion 1 only takes a single step, it would have been preferred by the old algorithm (although there were workarounds for this). +The new algorithm adds the concept of conversion-cost, that has to be specified for each conversion. +The conversions 2 and 3 now have a cost of `1`, while conversion 1 has a cost of `5`. +The conversions are simply added up and the path with the lowest cost is chosen. +Like in other pathfinding applications like digital games, the cost metric is also used by the algorithm to enhance the search itself, +it prioritises searching further on the path with the least current cost. + +To implement this optimization I implemented a priority queue: + + -- a priority queue with an index + -- only one element with a given key may exist at a time + -- when an element with an existing key is added, + -- the element with lower priority survives. + class Queue + new: => + @values = {} + @index = {} + + -- add a value with a given priority to the queue + -- if no key is specified, assume the element is uniq + add: (value, priority, key) => + entry = { :value, :key, :priority } + + if key + if old_entry = @index[key] + -- already have an entry for this key + -- if it is lower priority, we leave it there and do nothing + if old_entry.priority < priority + return + + -- otherwise we remove the old one and continue as normal + -- find the index of the old entry + local i + for ii, entry in ipairs @values + if entry == old_entry + i = ii + break + + -- remove it + table.remove @values, i + + -- store this entry in the index + @index[key] = entry + + -- store lowest priority last + for i, v in ipairs @values + if v.priority < priority + -- i is the first key that is lower, + -- we want to insert right before it + table.insert @values, i, entry + return + + -- couldn't find a key with a lower priority, + -- so insert at the end + table.insert @values, entry + + peek: => + entry = @values[#@values] + if entry + { :value, :priority, :key } = entry + @index[key] = nil if key + value, priority + + pop: => + entry = table.remove @values + if entry + { :value, :priority, :key } = entry + @index[key] = nil if key + value, priority + + -- iterator, yields (value, priority), low priority first + poll: => @.pop, @ + + { + :Queue + } + +This priority queue behaves mostly as expected, but I added an extra feature to make sure that only the +best conversion path to a specific type is considered for further searching: +When adding a new element to the Queue, an extra `key` can be passed. +If a key is passed, the Queue makes sure that there is only ever one element with that key in the queue. +When a second element would be introduced, the queue discards whichever element has a higher priority value. + +This way I can use the type that a conversion path leads to as the key, +and the queue will automatically discard a worse solution if a better one is found that leads to the same type result. + +To make sure the Queue implementation was solid, I also added unit tests for it: [`spec/queue_spec.moon`][spec] + +[deb21aa]: https://git.s-ol.nu/mmm/commit/deb21aa43fe8bf11eb276803973b272913b7e716/ +[spec]: https://git.s-ol.nu/mmm/blob/deb21aa43fe8bf11eb276803973b272913b7e716/spec/queue_spec.moon diff --git a/root/articles/mmmfs/ba_log/2019-10-15/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-15/text$markdown.md new file mode 100644 index 0000000..d4e4121 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-15/text$markdown.md @@ -0,0 +1,70 @@ +I'm giving a workshop next weekend, and I had to create the slides for that. +Since one of the aspirations of `mmmfs` is to be easily adaptable to any kind of data organization and -presentation task, +that was a good opportunity to try and implement a simple slideshow system. + +I started by creating a new fileder to hold the slideshow, [`/articles/xy-workshop`](/articles/xy-workshop/). +In the main facet, I created a MoonScript file. +Since the facet needs to access its children (the individual slides), I also used the `fn ->` type, +that injects the current fileder into the script. + +`text/moonscript -> fn -> mmm/dom` + + import ReactiveVar, tohtml, fromhtml, text, elements from require 'mmm.component' + import article, button, div, span from elements + + => + index = ReactiveVar 1 + slide = index\map (index) -> @children[index] + + local view + view = div { + style: ... -- styling ommited here + + div { + style: ... -- styling omitted here + + slide\map => @get 'mmm/dom' + } + } + + local left, right + if MODE == 'CLIENT' + left = (_, e) -> + e\preventDefault! + index\transform (a) -> math.max 1, a - 1 + + right = (_, e) -> + e\preventDefault! + index\transform (a) -> math.min #@children, a + 1 + + tohtml with article! + \append div { + button '<', onclick: left + ' ' + span index\map (t) -> text t + ' ' + button '>', onclick: right + } + \append view + +I used the `mmm.component` library that lets me create reactive UIs. +First I declare the reactive variable `index`, the current slide number. +Then I derive the `slide` reactive variable, that is defined to be the child with index `index` - +since these are `ReactiveVar`s, whenever `index` changes, `slide` will automatically load the current slide fileder. + +Then I create the main slide view, which consists mainly of two containers and some styling. +Inside, I derive another reactivevar from `slide`: whenever a new `slide` is selected, +this piece of code will request the main content in `mmm/dom` format and replace the current view content with that. + +Lastly I construct a little navigation UI, consisting of the left and right buttons. +When one of them is clicked, it modifies the `index` variable, making sure to stay in the range of existing slides. +The rest of the UI then reactively updates accordingly. + +Lastly I added keyboard controls for cycling through the slides, as well as a button to enter fullscreen mode. +You can find the extended code for that in the commit [`ca24ef1`][ca24ef1], +but it is not a lot either: with the additions the file is 70 lines long. + +With this done, it is just a matter of creating children-fileders and placing whichever content I want in them, +they behave just like any other page of the system now. + +[ca24ef1]: https://git.s-ol.nu/mmm/blob/ca24ef108dbb11860e719711e4e7fbd6323aee0e/root/articles/xy-workshop/text%24moonscript%20-%3E%20fn%20-%3E%20mmm%24dom.moon diff --git a/root/articles/mmmfs/ba_log/2019-10-24/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-24/text$markdown.md new file mode 100644 index 0000000..dbb838a --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-24/text$markdown.md @@ -0,0 +1,32 @@ +While writing some of the main section of the thesis today, +I felt the need to illustrate some subject matter with a diagram depicting a folder structure. +Knowing of some similar tools that generate SVG diagrams from textual descriptions, +some quick research turned up [mermaid JS][mermaid]. + +I tried it in their online live editor first to verify that it would indeed do what I needed it to, +and then added it to the set of supported types in mmm (on the clientside only) \[[`2ff6f90`][2ff6f90]\]. +This was pretty easy in the end, all it took was adding mermaid.js to the interactive version's resources (in `build/server.moon`) +and then definig the `convert` (and thereby implicitly defining the corresponding type, `text/mermaid-graph`): + + { + inp: 'text/mermaid-graph' + out: 'mmm/dom' + cost: 1 + transform: (source) => + with container = document\createElement 'div' + cb = (svg, two) => + .innerHTML = svg + window.mermaid\render "mermaid-#{id_counter}", source, cb + } + +The code is quite short, since all it needs to do is create a container element, +then tell mermaid.js to render the textual definition. +Once mermaid.js is done, the rendered content is added in the container element. + +Here is one of the two diagrams that I implemented the feature for, +you can also follow the link through to the source and view the textual representation using the 'inspect' button. + +<mmm-embed path="/articles/mmmfs/mmmfs/tree_mainstream"></mmm-embed> + +[mermaid]: https://mermaidjs.github.io/mermaid-live-editor/ +[2ff6f90]: https://git.s-ol.nu/mmm/commit/2ff6f906c498c1b742dd8437a09c97ebe29a652a/ diff --git a/root/articles/mmmfs/ba_log/2019-10-26/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-26/text$markdown.md new file mode 100644 index 0000000..d5cd9bd --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-26/text$markdown.md @@ -0,0 +1,62 @@ +Besides some smaller fixes with the styling of the page, and in particular the diagrams introduced in [`2019-10-24`][2019-10-24], +I finally (re-)implemented children-ordering in the `fs`-store of mmmmfs +(the `sql` store is still missing it, but I am not currently using it either) \[[`a62f63b`][a62f63b]\]: +Files on the regular filesystem don't have a particular order, but in mmmfs the order of children is is guaranteed, +so that arranging children in a particular order becomes a meaningful tool. + +To store the ordering data, a 'magic' file called `$order` is (optionally) stored in each directory in the filesystem. +The file lists all child fileders by name in the given order. +When the children of a fileder are requested (in `list_fileders_in` or `get_index`, which relies on the former), +all children that are mentioned in `$order` are returned in that order, +while all remaining children are sorted alphabetically and appended at the end of the list. +This way the order is guaranteed to be stable even if no `$order` file is specified, +or when the `$order` file has not been updated after adding new children. + +Here is the commented implementation in MoonScript: + + list_fileders_in: (path='') => + -- create a mapping of all child-fileders + -- in 'entries' (name -> path) + entries = {} + for entry_name in lfs.dir @root .. path + continue if '.' == entry_name\sub 1, 1 + entry_path = @root .. "#{path}/#{entry_name}" + if 'directory' ~= lfs.attributes entry_path, 'mode' + continue + + entries[entry_name] = "#{path}/#{entry_name}" + + -- where we will store our sorted list of children + sorted = {} + + -- check for existance of the order file + order_file = @root .. "#{path}/$order" + if 'file' == lfs.attributes order_file, 'mode' + for line in io.lines order_file + path = assert entries[line], "entry in $order but not on disk: #{line}" + + -- add all $order-entries to the sorted output in the same order they appear. + -- also flag these entries as already added + table.insert sorted, path + sorted[line] = true + + -- find the he remaining (non-flagged) entries, sort them alphabetically + -- and then append them to the sorted output list + entries = [path for entry, path in pairs entries when not sorted[entry]] + table.sort entries + for path in *entries + table.insert sorted, path + + -- return an iterator over the sorted output + coroutine.wrap -> + for path in *sorted + coroutine.yield path + +The interface for reordering fileders is still missing in the code, +and just while writing this I realized that the current implementation is in fact buggy: +when a fileder that is mentioned in `$order` is deleted via the `stores.fs` API, +it is not removed from `$order`, causing an error the next time the fileder is listed. +I will probably get around to fixing both of these problems when I build the corresponding UI. + +[2019-10-24]: /articles/mmmfs/ba_log/2019-10-24/ +[a62f63b]: https://git.s-ol.nu/mmm/commit/a62f63bc00cd63a98b349a2574e3e9e14c95a441/ diff --git a/root/articles/mmmfs/ba_log/2019-10-27/$order b/root/articles/mmmfs/ba_log/2019-10-27/$order new file mode 100644 index 0000000..2b68b52 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-27/$order @@ -0,0 +1 @@ +video diff --git a/root/articles/mmmfs/ba_log/2019-10-27/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-27/text$markdown.md new file mode 100644 index 0000000..3e9f886 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-27/text$markdown.md @@ -0,0 +1,77 @@ +Today I finally reached the ability of editing content inside of mmmfs directly! + +<mmm-embed path="video" nolink></mmm-embed> + +Content is currently not saved anywhere, but the basis of the feature is there. +For the moment this is implemented as yeat another *convert* that simply converts +from `text/.*` (any textual code) to `mmm/dom` (web UI) \[[`28653c9`][28653c9]\]. +However this *convert* is only applied in the inspector view (more on that below). +First, here is the convert itself: + + { + inp: 'text/([^ ]*).*' + out: 'mmm/dom' + cost: 0 + transform: (value, fileder, key) => + mode = @from\match @convert.inp + Editor value, mode, fileder, key + } + +and the main part of the code, the `Editor` widget: + +```moonscript +class Editor + new: (value, mode, @fileder, @key) => + @node = div class: 'editor' + -- 'o' is a little helper for converting a Lua table to a JS object + @cm = window\CodeMirror @node, o { + :value + :mode + lineNumber: true + lineWrapping: true + autoRefresh: true + theme: 'hybrid' + } + + @cm\on 'changes', (_, mirr) -> + window\clearTimeout @timeout if @timeout + @timeout = window\setTimeout (-> @change!), 300 + + change: => + @timeout = nil + doc = @cm\getDoc! + if @lastState and doc\isClean @lastState + -- no changes since last event + return + + @lastState = doc\changeGeneration true + value = doc\getValue! + + @fileder.facets[@key] = value + BROWSER\refresh! +``` + +I chose the [CodeMirror][codemirror] library as the basis for the editor, +because it seemed like one of the leanest ones I could find +(and yet it is quite heavy at 100kb plus styling and language support addons). +The code for the editor is also quite minimale it really just creates a wrapper for the editor +and tells CodeMirror to set itself up inside. +Whenever changes are detected, a timeout of 300ms is started, +after which the preview is refreshed to preview the changes. +If more changes are made within the 300ms, the timer is reset to 300ms, +so that the preview update doesn't interrupt the typing flow. + +I also spent some time refactoring the global list of converts out into multiple smaller plugins +(although a lot of global converts remain at the moment) \[[`abefbf8`][abefbf8]\]. +A plugin can export a list of converts as well as a list of 'editors', which are essentially no different, +except that they are taken into consideration only when converting content for the inspector. + +Breaking the converts up into little packages like that makes it a lot easier to edit, +and allows enabling and disabling individual features very easily. +I am also considering moving the converts into the mmmfs data itself, +to make extending the system and working inside the system more congruent, +and this is a good way of testing my idea of how the modularization of the system should work. + +[codemirror]: https://codemirror.net/ +[28653c9]: https://git.s-ol.nu/mmm/commit/28653c9ae46b2b3e42c2c75879589138c731f37b/ +[abefbf8]: https://git.s-ol.nu/mmm/commit/abefbf82531021f5ca4149675932a7fe2ff37dde/ diff --git a/root/articles/mmmfs/ba_log/2019-10-27/video/video$webm.webm b/root/articles/mmmfs/ba_log/2019-10-27/video/video$webm.webm Binary files differnew file mode 100644 index 0000000..020e352 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-27/video/video$webm.webm diff --git a/root/articles/mmmfs/ba_log/2019-10-29/$order b/root/articles/mmmfs/ba_log/2019-10-29/$order new file mode 100644 index 0000000..2b68b52 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-29/$order @@ -0,0 +1 @@ +video diff --git a/root/articles/mmmfs/ba_log/2019-10-29/text$markdown.md b/root/articles/mmmfs/ba_log/2019-10-29/text$markdown.md new file mode 100644 index 0000000..4119d21 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-29/text$markdown.md @@ -0,0 +1,38 @@ +Today I implemented updating/saving content in the server, and bridged the feature to the client. +In the inspector there is now a `save changes` button that (attempts to) save the content on +the server's filesystem \[[`4b8d9be`][4b8d9be]\]. + +<mmm-embed path="video" nolink>demonstration of editing and persistantly saving facet</mmm-embed> + +Originally I wanted to create a `sandbox` fileder that was to be edited by any one online \[[`d9eafa2`][d9eafa2]\]. +I restricted editing to only fileders underneath `/sandbox`, but then upon publishing quickly realized +that this left open a major security vulnerability, since content can be evaluated on server or client: +if a client were to create a facet `exploit: text/lua -> text/plain` with the following content in the root: + +```lua +pass = io.open('/etc/passwd', 'r') +return pass:read("*all") +``` + +...and then request that facet as converted to `text/plain` (`GET /exploit: text/plain`), +then that Lua code would be executed on the server, and return the confidential `passwd` file on the server. +This basically meant handing anyone online full unconditionaly access to my server +(or at least the VM running the website, and potentially options to escalate from there). + +As a result I had to choose to either disable public editing, or disable server-side code execution. +Because server-side execution is a major feature of mmmfs, I settled for the following compromise \[[`1e3b0a1`][1e3b0a1]\]: + +- when developing and running locally, editing and code execution are both enabled in 'unsafe mode' +- on https://ba.s-ol.nu, editing is disabled but code execution is possible +- on https://sandbox.s-ol.nu, editing is enabled but code server-side code execution is disabled + +The Sandbox can now be found at the following address, at least until the thesis project is concluded: + +# [`sandbox.s-ol.nu`](https://sandbox.s-ol.nu) + +Currently it is only possible to edit existing facets, +but creation and deletion of facets and fileders should be implemented soon. + +[4b8d9be]: https://git.s-ol.nu/mmm/commit/4b8d9be10e4517114c0c216fa24aaaa310503d4a/ +[d9eafa2]: https://git.s-ol.nu/mmm/commit/d9eafa21ad1d6ad340b5744d69e9fc68ce2083cb/ +[1e3b0a1]: https://git.s-ol.nu/mmm/commit/1e3b0a12060dce916b686921c94520202c4cb130/ diff --git a/root/articles/mmmfs/ba_log/2019-10-29/video/video$mp4.mp4 b/root/articles/mmmfs/ba_log/2019-10-29/video/video$mp4.mp4 Binary files differnew file mode 100644 index 0000000..162d0fc --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-10-29/video/video$mp4.mp4 diff --git a/root/articles/mmmfs/ba_log/2019-11-01/$order b/root/articles/mmmfs/ba_log/2019-11-01/$order new file mode 100644 index 0000000..1549b67 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-11-01/$order @@ -0,0 +1 @@ +demo diff --git a/root/articles/mmmfs/ba_log/2019-11-01/demo/video$webm.webm b/root/articles/mmmfs/ba_log/2019-11-01/demo/video$webm.webm Binary files differnew file mode 100644 index 0000000..1463897 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-11-01/demo/video$webm.webm diff --git a/root/articles/mmmfs/ba_log/2019-11-01/text$markdown.md b/root/articles/mmmfs/ba_log/2019-11-01/text$markdown.md new file mode 100644 index 0000000..afcaf0a --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-11-01/text$markdown.md @@ -0,0 +1,18 @@ +In the last two days I implemented the remaining features for full editing support in the browser: + +- support for adding, removing facets in the inspector \[[`dc08e26`][dc08e26]\] +- support for adding, removing fileders in the inspector \[[`ff9ee8e`][ff9ee8e]\] +- implemented the API for reordering fileders as mentioned in [`2019-10-26`][2019-10-26] \[[`053e607`][053e607]\] +- support for reordering fileders in the inspector \[[`16232a2`][16232a2]\] + +Here is a short demo video of these features: + +<mmm-embed nolink path="demo"></mmm-embed> + +As usual, this can be tried out immediately at [`sandbox.s-ol.nu`](//sandbox.s-ol.nu) + +[2019-10-26]: /articles/mmmfs/ba_log/2019-10-26/ +[dc08e26]: https://git.s-ol.nu/mmm/commit/dc08e262cd53a48480a88235aa58500f0638ad79/ +[ff9ee8e]: https://git.s-ol.nu/mmm/commit/ff9ee8e99cd5f5c420ba0501c335ac18f1b10769/ +[053e607]: https://git.s-ol.nu/mmm/commit/053e607a49989b2d4491c20ff14c839b7161d713/ +[16232a2]: https://git.s-ol.nu/mmm/commit/16232a2509a87a900b69b2d0f826a2e3edec3f96/ diff --git a/root/articles/mmmfs/ba_log/2019-11-25/$order b/root/articles/mmmfs/ba_log/2019-11-25/$order new file mode 100644 index 0000000..1549b67 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-11-25/$order @@ -0,0 +1 @@ +demo diff --git a/root/articles/mmmfs/ba_log/2019-11-25/demo/video$webm.webm b/root/articles/mmmfs/ba_log/2019-11-25/demo/video$webm.webm Binary files differnew file mode 100644 index 0000000..bdf9d9c --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-11-25/demo/video$webm.webm diff --git a/root/articles/mmmfs/ba_log/2019-11-25/text$markdown.md b/root/articles/mmmfs/ba_log/2019-11-25/text$markdown.md new file mode 100644 index 0000000..48a0bb4 --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-11-25/text$markdown.md @@ -0,0 +1,89 @@ +There was a longer break in development of the projects as I have been focusing on the thesis, +where progress is not represented accurately in the repository. + +There was also some progress on featurse that haven't been tidied up and committed yet, +such as drag'n'drop / direct file upload. Those features will probably get their own post sometime soon. + +Today I spent some time to implement one of the example use-cases that will be part of the theoretical text as well, +[the 'pinwall' demo][pinwall] \[[`5ec1fe2`][5ec1fe2]\]. + +The Pinwall example renders all its children as resizeable and movable boxes that can be freely positioned on a canvas: + +<mmm-embed nolink path="demo"></mmm-embed> + +Any changes to the box positions and sizes are saved persistently as a `pinwall_info` facet on each child. +For example the size and coordinates of the image can be found at [`image/pinwall_info: text/json`][info]. + +Rendering the children themselves is pretty easy: + +```moon +import article, div from require 'mmm.dom' +import convert from require 'mmm.mmmfs.conversion' + +update_info = (fileder, x, y, w, h) -> + info = (fileder\get 'pinwall_info: table') or x: 100, y: 100, w: 300, h: 300 + info.x = x if x + info.y = y if y + info.w = w if w + info.h = h if h + + json = convert 'table', 'text/json', info, fileder, 'pinwall_info' + fileder\set 'pinwall_info: text/json', json + +=> + observe = ... -- (ommited - calls `update_info` when child is resized) + + children = for child in *@children + info = (child\get 'pinwall_info: table') or x: 100, y: 100, w: 300, h: 300 + wrapper = div { + style: + position: 'absolute' + -- (more styling omitted here) + + left: "#{info.x}px" + top: "#{info.y}px" + width: "#{info.w}px" + height: "#{info.h}px" + + -- handle for moving the child + div { + style: + -- (styling omitted here) + + onmousedown: ... -- (omitted) + } + + -- child content + div { + style: + width: '100%' + height: '100%' + background: 'var(--white)' + + (child\gett 'mmm/dom') + } + } + + observe wrapper, child + + wrapper + + children.style = { + width: '1000px' + height: '500px' + } + + children.onmouseup = ... -- (omitted) + children.onmousemove = ... -- (omitted) + children.onmouseleave = ... -- (omitted) + + article children +``` + +[The rest of the code][source] is just about catching the events when the mouse is clicked/release/moved and when a child is resized, +and then calling `update_info` as appropriate. + +[info]: /articles/mmmfs/examples/pinwall/image/pinwall_info:%20text/html+interactive +[pinwall]: /articles/mmmfs/examples/pinwall/ +[source]: https://git.s-ol.nu/mmm/blob/5ec1fe2fc943ad4123fac138de70d4152e8b341d/root/articles/mmmfs/examples/pinwall/text%24moonscript%20-%3E%20fn%20-%3E%20mmm%24dom.moon +[5ec1fe2]: https://git.s-ol.nu/mmm/blob/5ec1fe2fc943ad4123fac138de70d4152e8b341d/ diff --git a/root/articles/mmmfs/ba_log/2019-12-20/text$markdown+sidenotes.md b/root/articles/mmmfs/ba_log/2019-12-20/text$markdown+sidenotes.md new file mode 100644 index 0000000..3de1a9c --- /dev/null +++ b/root/articles/mmmfs/ba_log/2019-12-20/text$markdown+sidenotes.md @@ -0,0 +1,39 @@ +In the last three days I have been working extensively on support for sidenotes and academic referencing, +inspired by Edward Tufte's style of publishing (as seen in *Beatiful Evidence* and documented in [tufte-css][tufte-css]. + +To this end margin-notes have been implemented in the CSS styling of the page using two classes, `sidenote` and +`sidenote-container`, which are to be applied to individual sidenotes and the containing document respectively. +Sidenotes are then pulled out of their surrounding context using `position: absolute` and placed in a margin that is +left free by `sidenote-container`. + +Inside of markdown files, sidenotes can then be added simply using basic HTML, like so: + +```md +<div class="sidenote">additional information to be found on the margin</div> +An example paragraph of text, describing something. +``` + +Which will render like this: + +> <div class="sidenote">additional information to be found on the margin</div> +> An example paragraph of text, describing something. + +Additionally, conversions from `text/bibtex`, a reference specification format, to `mmm/dom` have been added, that +create citations using the metadata available in the BibTeX file. + +For example the following BibTeX is rendered like this: + +<mmm-embed nolink path="../../references/inkandswitch" facet="markdown"></mmm-embed> + +> <mmm-embed wrap="raw" path="../../references/inkandswitch"></mmm-embed> + +I also added a special override that links to +BibTeX files by placing the citation in a sidenote, and adding a footnote indicator in-text. + +There is also a handy convert that turns ACM Digital Library links into URLs that directly return the BibTeX file, +which allows me to cite the links directly without manually adding the BibTeX information to my document. + +All of this is implemented in the `cites` plug-in: [`cites.moon`][cites.moon]. + +[cites.moon]: https://git.s-ol.nu/mmm/blob/ba/mmm/mmmfs/plugins/cites.moon +[tufte-css]: https://edwardtufte.github.io/tufte-css/ diff --git a/root/articles/mmmfs/ba_log/intro: text$markdown.md b/root/articles/mmmfs/ba_log/intro: text$markdown.md new file mode 100644 index 0000000..37366cf --- /dev/null +++ b/root/articles/mmmfs/ba_log/intro: text$markdown.md @@ -0,0 +1,4 @@ +The following pages document the development of the `mmmfs` system described above in the form of a project log. +Please note that the log has been written primarily for viewing using a web browser, and as such makes extensive use of +hyperlinking, and also includes some videos that cannot be reproduced in print. It is therefore recommended to view the +live version of the log online at the following address: [s-ol.nu/ba/log](https://s-ol.nu/ba/log). diff --git a/root/articles/mmmfs/ba_log/print: text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/ba_log/print: text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..97ebd4c --- /dev/null +++ b/root/articles/mmmfs/ba_log/print: text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,19 @@ +import div, section, h1, h2, hr from require 'mmm.dom' +import link_to from (require 'mmm.mmmfs.util') require 'mmm.dom' +import ropairs from require 'mmm.ordered' + +=> + div { + class: 'print-ownpage' + + h1 (link_to @, "appendix: project log"), id: 'ba-log' + @gett 'intro: mmm/dom' + table.unpack for post in *@children + continue if post\get 'hidden: bool' + + section { + hr! + h2 link_to post, post\gett 'name: mmm/dom' + (post\gett 'mmm/dom') + } + } diff --git a/root/articles/mmmfs/ba_log/start/text$markdown.md b/root/articles/mmmfs/ba_log/start/text$markdown.md new file mode 100644 index 0000000..d56130b --- /dev/null +++ b/root/articles/mmmfs/ba_log/start/text$markdown.md @@ -0,0 +1,25 @@ +The system described in the thesis and subject to the following blog posts was partially pre-existing to the work +done as part of the thesis and thesis project. The `mmmfs` system was originally developed as the software for my +personal website, with development beginning around May 2018. In this phase of development the website and system +changed shape drastically multiple times. In the following paragraphs I will describe the state of the project at +the last revision prior to the beginning of the thesis project, as it existed before the 7th of October 2019. +All developments since this revision have been tracked in the following project log entries, and are to be considered +the practical contributions to the thesis project. + +In this revision, the system existed as a tool to produce a static website representing the contents of the `mmmfs` +system in browsable HTML format. The tool had to be run manually after changes, or using a build tool like [`tup`][tup]. +A primitive *Inspector* tab was present in the HTML output and allowed viewing the raw `mmmfs` contents, but all editing +of content had to be done with external tools and in the external file-system. To see changes in the browser, a +compilation phase had to be triggered and completed, and consecutively the page reloaded in the browser. There was no +server-side component that could convert content or store changes for clients. The tool could only accept content from +the filesystem, not from zip archives or SQLite databases. The conversion algorithm used was more naive and was not +able to track cost values, which meant that some more advanced conversions couldn't be implemented. + +There was already an example implementation of a simple slideshow present, but due to the lack of editing capabilities +there was no pinwall examle. There was also no support for side- or marginnotes, or academic referencing and citations. +There also was no support for [`mermaid`][mermaid] diagrams or JSON-encoded data, and there was no plugin interface. +The HTML template, CSS styling and JS runtime were all built and tracked outside of the `mmmfs` system itself. +There was no unit tests for any of the project. + +[tup]: http://gittup.org/tup/ +[mermaid]: https://mermaidjs.github.io/ diff --git a/root/articles/mmmfs/ba_log/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/ba_log/text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..b6b0756 --- /dev/null +++ b/root/articles/mmmfs/ba_log/text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,15 @@ +import div, h1, ul, li from require 'mmm.dom' +import link_to from (require 'mmm.mmmfs.util') require 'mmm.dom' +import ropairs from require 'mmm.ordered' + +=> + div { + h1 (link_to @, "appendix: project log"), id: 'ba-log' + @gett 'intro: mmm/dom' + ul do + posts = for post in *@children + continue if post\get 'hidden: bool' + li link_to post, post\gett 'name: mmm/dom' + + posts + } diff --git a/root/articles/mmmfs/conclusion/text$markdown+sidenotes.md b/root/articles/mmmfs/conclusion/text$markdown+sidenotes.md new file mode 100644 index 0000000..92230a0 --- /dev/null +++ b/root/articles/mmmfs/conclusion/text$markdown+sidenotes.md @@ -0,0 +1,11 @@ +# 8 conclusion + +The historical analysis and the evaluation of the proposed system show that many of the limitations of current +mainstream operating systems can be worked around effectively. The flaws can also be attributed in part to some +concrete design paradigms, which future system designers may seek to avoid. To this end, the framework provided for +evaluation may also be useful. + +The system proposed and developed in the project corresponding to this thesis has been shown to successfully implement +many of the properties were hoped to be achieved, such as a modular and consistent architecture and strong support for +mixed-content transclusions. On the other hand, some limitations in the design are apparent. Many of these limitations +constitute candidate topics for further research, and most can be attributed to trade-offs made in the development process. diff --git a/root/articles/mmmfs/empty/title: text$plain b/root/articles/mmmfs/empty/title: text$plain deleted file mode 100644 index 911f98b..0000000 --- a/root/articles/mmmfs/empty/title: text$plain +++ /dev/null @@ -1 +0,0 @@ -Hey I'm an almost empty Fileder. diff --git a/root/articles/mmmfs/evaluation/text$markdown+sidenotes.md b/root/articles/mmmfs/evaluation/text$markdown+sidenotes.md new file mode 100644 index 0000000..65024d4 --- /dev/null +++ b/root/articles/mmmfs/evaluation/text$markdown+sidenotes.md @@ -0,0 +1,173 @@ +# 7 evaluation +In this section, I will first take a look at the implementations of the examples for the use cases outlined above, +and evaluate them with regard to the framework derived in the corresponding section above. After that, some general +concerns and insights that have become apparent while developing the system and working with it will be reviewed. + +## 7.1 examples +### 7.1.1 publishing and blogging +Since mmmfs has grown out of the need for a versatile content management system for a personal website and blog, it is +not surprising to see that it is still up to that job. Nevertheless, it is worth taking a look at its strengths and +weaknesses in this context: + +The system has proven itself perfect for publishing small- and medium-size articles and blog posts, especially for its +ability to flexibly transclude content from any source. This includes diagrams (such as in this thesis), +videos (as in the documentation in the appendix), but also less conventional media such as +interactive diagrams<mmm-embed path="../references/aspect-ratios" wrap="sidenote"></mmm-embed> or twitter postings. + +On the other hand, the development of the technical framework for this thesis has posed greater challenges. +While the reference and sidenote systems integrated well with the rest of the system, some features like automated +table-of-contents and section numbering were less obvious to tackle and finally completed manually. +This is mostly due to the approach of splitting up the thesis into a multitude of fileders, and the current lack of +mechanisms to re-capture information spread throughout the resulting hierarchy effectively. + +### 7.1.2 pinwall +The pinwall example shows some strengths of the mmmfs system pretty convincingly. +The type coercion layer completely abstracts away the complexities of transcluding different types of content, +and only positioning and sizing the content, as well as enabling interaction, remain to handle in the pinwall fileder. + +A great benefit of the use of mmmfs versus other technology for realizing this example is that the example can +seamlessly embed not only plain text, markdown, images, videos, and interactive widgets, but also follow links to all +of these types of content, and display them meaningfully. Accomplishing this with traditional frameworks would take +great effort, where mmmfs benefits from the reuse of these conversions across the whole system. + +In addition, the script for the pinwall folder is 120 lines long, of which 30 lines are styling, while almost 60 lines +take care of capturing and handling JS events. The bulk of complexity is therefore shifted towards interacting with the +UI layer (in this case the browser), which could feasibly be simplified through a custom abstraction layer or the use of +output means other than the web. + +### 7.1.3 slideshow +A simplified image slideshow example consists of only 20 lines of code and demonstrates how the reactive component +framework simplifies the generation of ad-hoc UI dramatically: + +```moon +import ReactiveVar, text, elements from require 'mmm.component' +import div, a, img from elements + +=> + index = ReactiveVar 1 + + prev = (i) -> math.max 1, i - 1 + next = (i) -> math.min #@children, i + 1 + + div { + div { + a 'prev', href: '#', onclick: -> index\transform prev + index\map (i) -> text " image ##{i} " + a 'next', href: '#', onclick: -> index\transform next + }, + index\map (i) -> + child = assert @children[i], "image not found!" + img src: @children[i]\gett 'URL -> image/png' + } +``` + +The presentation framework is a bit longer, but the added complexity is again required to deal with browser quirks, +such as the fullscreen API and sizing content proportionally to the viewport size. +The parts of the code dealing with the content are essentially identical, except that content is transcluded via the +more general `mmm/dom` type-interface, allowing for a greater variety of types of content to be used as slides. + +## 7.2 general concerns +While the system has proven pretty successful and moldable to the different use-cases that it has been tested in, +there are also limitations in the proposed system that have become obvious in developing and working with the system. +In this section, these limitations will be discussed individually, and directions for further research and solutions will +be given where apparent. + +### 7.2.1 global set of converts +In the current system, there is only a single, global set of *converts* that can be potentially applied to facets +anywhere in the system. +Therefore it is necessary to encode behavior directly (as code) in facets wherever exceptional behavior is required. +For example, if a fileder containing multiple images wants to provide custom UI for each image when viewed independently, +this code has to either be attached to every image individually (and redundantly), or added as a global convert. +To make sure this convert does not interfere with images elsewhere in the system, it would be necessary to introduce +a new type and change the images to use it, which may present even more problems, and works against the principle of +compatibility that the system has been constructed for. + +A potential direction of research in the future is to allow specifying *converts* as part of the fileder tree. +Application of *converts* could then be scoped to their fileders' subtrees, such that for any facet only the *converts* +stored in the chain of its parents upwards are considered. +This way, *converts* can be added locally if they only make sense within a given context. +Additionally, it could be made possible to use this mechanism to locally override *converts* inherited from +further up in the tree, for example, to specialize types based on their context in the system. + +<mmm-embed wrap="marginnote" path="../references/alternatives-to-trees">See also </mmm-embed> +The biggest downside to this approach would be that it presents another pressure factor for, while also reinforcing, +the hierarchical organization of data, thereby exacerbating the limits of hierarchical structures. + +### 7.2.2 code outside of the system +At the moment, a large part of the mmmfs codebase is still separate from the content and developed outside of mmmfs +itself. This is a result of the development process of mmmfs and was necessary to start the project as the filesystem +itself matured, but has now become a limitation of the user experience: potential users of mmmfs would generally start +by becoming familiar with the operation of mmmfs from within the system, as this is the expected (and designated) +experience developed for them. All of the code that lives outside of the mmmfs tree is therefore invisible and opaque +to them, actively limiting their understanding, and thereby the customizability, of the system. + +This weakness represents a failure to (fully) implement the quality of a "Living System" as proposed by +*Ink and Switch*<mmm-embed path="../references/inkandswitch" wrap="sidenote"></mmm-embed>. + +In general, however, some portion of code may always have to be left outside of the system. +This also wouldn't necessarily represent a problem, but in this case it is particularly relevant +for the global set of *converts* (see above), as well as the layout used to render the web view. +Both of these are expected to undergo changes as users adapt the system to their own content types and +domains of interest, as well as their visual identity, respectively. + +### 7.2.3 type system +The currently used type system based on strings and pattern matching has been largely satisfactory +but has proven problematic for some anticipated use cases. +It should be considered to switch to a more intricate, +structural type system that allows encoding more concrete meta-data alongside the type, +and to match *converts* based on a more flexible scheme of pattern matching. +For example, it is envisaged to store the resolution of an image file in its type. +Many *converts* might choose to ignore this additional information, +but others could use this information to generate lower-resolution 'thumbnails' of images automatically. +Using these mechanisms for example images could be requested with a maximum-resolution constraint to save on bandwidth +when embedded in other documents. + +<div style="break-before: page;"></div> + +### 7.2.4 type-coercion +By giving the system more information about the data it is dealing with, +and then relying on the system to automatically transform between data-types, +it is easy to lose track of which format data is concretely stored in. +In much the same way that the application-centric paradigm alienates users from an understanding +and feeling of ownership of their data by overemphasizing the tools in between, +the automagical coercion of data types introduces distance between the user and +an understanding of the data in the system. +This poses a threat to the transparency of the system, and potentially a lack of the "Embodiment" quality (see above). + +Potential solutions could be to communicate the conversion path clearly and explicitly together with the content, +as well as making this display interactive to encourage experimentation with custom conversion queries. +Emphasizing the conversion process more strongly in this way might be a way to turn this feature from an opaque +hindrance into a transparent tool. This should represent a challenge mostly in terms of UX and UI design. + +### 7.2.5 in-system editing +Because many *converts* are not necessarily reversible, it is very hard to implement generic ways of editing stored data +in the same format it is viewed. For example, the system trivially converts markdown-formatted text sources into +viewable HTML markup, but it is hardly possible to propagate changes to the viewable HTML back to the markdown source. +This particular instance of the problem might be solvable using a Rich-Text editor, but the general problem worsens when +the conversion path becomes more complex: If the markdown source was fetched via HTTP from a remote URL (e.g. if the +facet's type was `URL -> text/markdown`), it is not possible to edit the content at all, since the only data owned by +the system is the URL string itself, which is not part of the viewable representation. Similarly, when viewing output +that is generated by code (e.g. `text/moonscript -> mmm/dom`), the code itself is not visible to the user, and if the +user wishes to change parts of the representation, the system is unable to relate these changes to elements of the code +or assist the user in doing so. + +However, even where plain text is used and edited, a shortcoming of the current approach to editing is evident: +The content editor is wholly separate from the visible representation, and only facets of the currently viewed fileder +can be edited. This means that content cannot be edited in its context, which is exacerbated by the extreme +fragmentation of content that mmmfs encourages. + +As a result, interacting with the system at large is still a very different experience from editing content (and +thereby extending the system) in it. This is expected to represent a major hurdle for users getting started with the +system and is a major shortcoming in enabling end-user programming, as set as a goal for this project. +A future iteration should carefully reconsider how editing could be integrated more holistically with the other core +concepts of the design. + +<div style="break-before: page;"></div> + +### 7.2.6 end-user adoption +As mentioned above, a conscious choice was made to exclude the implementation of a dedicated end-user programming +facility in the system, and instead conventional programming languages and mechanisms were relied upon as the central +way of customizing the system and experience. While this was a crucial choice to make in order to proceed with the +project as a whole, it means that the system currently can not be adopted and used to its full extent by +end-users. This also means that a full evaluation of the system with regard to end-user empowerment has to be left open +until this can be changed by further work. diff --git a/root/articles/mmmfs/examples/$order b/root/articles/mmmfs/examples/$order new file mode 100644 index 0000000..4ee3140 --- /dev/null +++ b/root/articles/mmmfs/examples/$order @@ -0,0 +1,5 @@ +language_support +image +markdown +gallery +pinwall diff --git a/root/articles/mmmfs/examples/gallery/$order b/root/articles/mmmfs/examples/gallery/$order new file mode 100644 index 0000000..9d438bd --- /dev/null +++ b/root/articles/mmmfs/examples/gallery/$order @@ -0,0 +1,2 @@ +link_to_image +actual_image diff --git a/root/articles/mmmfs/gallery/actual_image/image$png.png b/root/articles/mmmfs/examples/gallery/actual_image/image$png.png Binary files differindex b499413..b499413 100644 --- a/root/articles/mmmfs/gallery/actual_image/image$png.png +++ b/root/articles/mmmfs/examples/gallery/actual_image/image$png.png diff --git a/root/articles/mmmfs/gallery/actual_image/preview: image$png.png b/root/articles/mmmfs/examples/gallery/actual_image/preview: image$png.png Binary files differindex f9dbfad..f9dbfad 100644 --- a/root/articles/mmmfs/gallery/actual_image/preview: image$png.png +++ b/root/articles/mmmfs/examples/gallery/actual_image/preview: image$png.png diff --git a/root/articles/mmmfs/gallery/link_to_image/URL -> image$png b/root/articles/mmmfs/examples/gallery/link_to_image/URL -> image$png index 7cf76ff..7cf76ff 100644 --- a/root/articles/mmmfs/gallery/link_to_image/URL -> image$png +++ b/root/articles/mmmfs/examples/gallery/link_to_image/URL -> image$png diff --git a/root/articles/mmmfs/gallery/link_to_image/preview: URL -> image$png b/root/articles/mmmfs/examples/gallery/link_to_image/preview: URL -> image$png index 2b2233b..2b2233b 100644 --- a/root/articles/mmmfs/gallery/link_to_image/preview: URL -> image$png +++ b/root/articles/mmmfs/examples/gallery/link_to_image/preview: URL -> image$png diff --git a/root/articles/mmmfs/gallery/slideshow: text$moonscript -> fn -> mmm$component.moon b/root/articles/mmmfs/examples/gallery/slideshow: text$moonscript -> fn -> mmm$component.moon index 0178ac2..0178ac2 100644 --- a/root/articles/mmmfs/gallery/slideshow: text$moonscript -> fn -> mmm$component.moon +++ b/root/articles/mmmfs/examples/gallery/slideshow: text$moonscript -> fn -> mmm$component.moon diff --git a/root/articles/mmmfs/gallery/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/examples/gallery/text$moonscript -> fn -> mmm$dom.moon index 9bdac54..9bdac54 100644 --- a/root/articles/mmmfs/gallery/text$moonscript -> fn -> mmm$dom.moon +++ b/root/articles/mmmfs/examples/gallery/text$moonscript -> fn -> mmm$dom.moon diff --git a/root/articles/mmmfs/examples/gallery/title: text$plain b/root/articles/mmmfs/examples/gallery/title: text$plain new file mode 100644 index 0000000..2e9ef34 --- /dev/null +++ b/root/articles/mmmfs/examples/gallery/title: text$plain @@ -0,0 +1 @@ +a gallery of images diff --git a/root/articles/mmmfs/image/URL -> image$png b/root/articles/mmmfs/examples/image/URL -> image$png index c586722..c586722 100644 --- a/root/articles/mmmfs/image/URL -> image$png +++ b/root/articles/mmmfs/examples/image/URL -> image$png diff --git a/root/articles/mmmfs/examples/image/title: text$plain b/root/articles/mmmfs/examples/image/title: text$plain new file mode 100644 index 0000000..dca924f --- /dev/null +++ b/root/articles/mmmfs/examples/image/title: text$plain @@ -0,0 +1 @@ +link to a remote image diff --git a/root/articles/mmmfs/examples/implementation: text$markdown+sidenotes.md b/root/articles/mmmfs/examples/implementation: text$markdown+sidenotes.md new file mode 100644 index 0000000..8a6a185 --- /dev/null +++ b/root/articles/mmmfs/examples/implementation: text$markdown+sidenotes.md @@ -0,0 +1,88 @@ +## 6.1 publishing and blogging +### 6.1.1 blogging +Blogging is pretty straightforward since it generally just involves publishing lightly-formatted text, +interspersed with media such as images and videos or perhaps social media posts. +Markdown is a great tool for this job, and has been integrated into the system to much success: +There are two different types registered with *converts*: `text/markdown` and `text/markdown+span`. +They both render to HTML (and DOM nodes), so they are immediately viewable as part of the system. +The only difference for `text/markdown+span` is that it is limited to a single line, +and doesn't render as a paragraph but rather just a line of text. +This makes it suitable for denoting formatted-text titles and other small strings of text. + +The problem of embedding other content together with text comfortably is also solved easily +because Markdown allows embedding arbitrary HTML in the document. +This made it possible to define a set of pseudo-HTML elements in the Markdown-convert, +`<mmm-embed>` and `<mmm-link>`, which respectively embed and link to other content native to mmmfs. + +### 6.1.2 academic publishing +<div class="sidenote" style="margin-top: 1.25rem"> +One of the 'standard' solutions, <a href="https://www.latex-project.org/">LaTeX</a>, +is arguably at least as complex as the mmm system proposed here, but has a much narrower scope, +since it does not support interaction. +</div> + +Academic publishing is notoriously complex, involving not only the transclusion of diagrams +and other media but generally requiring precise and consistent control over formatting and layout. +Some of these complexities are tedious to manage but present good opportunities for programmatic +systems and media to do work for the writer. + +One such topic is the topic of references. +References appear in various formats at multiple positions in an academic document; +usually, they are referenced via a reduced visual form within the text of the document +and then shown again with full details at the end of the document. + +For the sake of this thesis, referencing has been implemented using a subset of the popular +BibTeX format for describing citations. Converts have been implemented for the `text/bibtex` +type to convert to a full reference format (to `mmm/dom`) and to an inline side-note reference +(`mmm/dom+link`) that can be transcluded using the `<mmm-link>` pseudo-tag. + +For convenience, a convert from the `URL -> cite/acm` type has been provided to `URL -> text/bibtex`, +which generates links to the ACM Digital Library<mmm-embed path="../references/acm-dl" wrap="sidenote"></mmm-embed> +API for accessing BibTeX citations for documents in the library. This means that it is enough to store the link to the +ACM DL entry in mmmfs, and the reference will automatically be fetched, and therefore stay up to date with potential +remote corrections. + +## 6.2 pinwall +In many situations, and particularly for creative work, it is often useful to compile resources of +different types for reference or inspiration and arrange them spatially so that they can be viewed +at a glance or organized into different contexts, etc. +Such a pinwall could serve for example to organize references to articles, +to collect visual inspiration for a mood board, etc. + +As a collection, the Pinwall is primarily mapped to a Fileder in the system. +Any content that is placed within can then be rendered by the Pinwall, +which can constrain every piece of content to a rectangular piece on its canvas. +This is possible through a simple script, e.g. of the type `text/moonscript -> fn -> mmm/dom`, +which enumerates the list of children, wraps each in such a rectangular container +and outputs the list of containers as DOM elements. + +The position and size of each panel are stored in an ad-hoc facet, encoded in the JSON data format: +`pinwall_info: text/json`. Such a facet is set on each child and read whenever the script is called +to render the children, plugging the values within the facet into the visual styling of the document. + +The script can also set event handlers that react to user input while the document is loaded, +and allow the user to reposition and resize the individual pinwall items by clicking and dragging +on the upper border or lower right-hand corner respectively. +Whenever a change is made the event handler can then update the value in the `pinwall_info` facet, +so that the updated position and size are stored for the next time the pinwall is opened. + +## 6.3 slideshow +Another common use of digital documents is as aids in a verbal presentation. +These often take the form of slideshows, for the creation of which a number of established applications exist. +In simple terms, a slideshow is simply a linear series of screen-sized documents, that can be +advanced (and rewound) one by one using keypresses. + +The implementation of this is rather straightforward as well. +The slideshow as a whole becomes a fileder with a script that generates a designated viewport rectangle, +as well as a control interface with keys for advancing the active slide. +It also allows putting the browser into fullscreen mode to maximize screen space and remove visual elements +of the website that may distract from the presentation, and register an event handler for keyboard accelerators +for moving through the presentation. + +Finally, the script simply embeds the first of its child-fileders into the viewport rectangle. +Once the current slide is changed, the next embedded child is simply chosen. + +<!-- +## code documentation +/meta/mmm.dom/:%20text/html+interactive +--> diff --git a/root/articles/mmmfs/examples/intro: text$markdown+sidenotes.md b/root/articles/mmmfs/examples/intro: text$markdown+sidenotes.md new file mode 100644 index 0000000..126f407 --- /dev/null +++ b/root/articles/mmmfs/examples/intro: text$markdown+sidenotes.md @@ -0,0 +1,10 @@ +# 6 example use-cases +To illustrate the capabilities of the proposed system, and to compare the results with the framework introduced above, +a number of example use cases have been chosen and implemented from the perspective of a user. +In the following section I will introduce these use cases and briefly summarize the implementation +approach in terms of the capabilities of the proposed system. + +<div style="break-before: page;"></div> + +<span class="sidenote">The online version is available at [s-ol.nu/ba](https://s-ol.nu/ba).</span> +The following examples can be viewed and inspected in the interactive version online: diff --git a/root/articles/mmmfs/examples/language_support/$order b/root/articles/mmmfs/examples/language_support/$order new file mode 100644 index 0000000..3cc0e47 --- /dev/null +++ b/root/articles/mmmfs/examples/language_support/$order @@ -0,0 +1,3 @@ +javascript +moonscript +lua diff --git a/root/articles/mmmfs/language_support/javascript/text$javascript -> mmm$dom.js b/root/articles/mmmfs/examples/language_support/javascript/text$javascript -> mmm$dom.js index de56531..de56531 100644 --- a/root/articles/mmmfs/language_support/javascript/text$javascript -> mmm$dom.js +++ b/root/articles/mmmfs/examples/language_support/javascript/text$javascript -> mmm$dom.js diff --git a/root/articles/mmmfs/language_support/javascript/title: text$plain b/root/articles/mmmfs/examples/language_support/javascript/title: text$plain index 581fbc7..581fbc7 100644 --- a/root/articles/mmmfs/language_support/javascript/title: text$plain +++ b/root/articles/mmmfs/examples/language_support/javascript/title: text$plain diff --git a/root/articles/mmmfs/language_support/lua/text$lua -> mmm$dom.lua b/root/articles/mmmfs/examples/language_support/lua/text$lua -> mmm$dom.lua index 62e79f1..62e79f1 100644 --- a/root/articles/mmmfs/language_support/lua/text$lua -> mmm$dom.lua +++ b/root/articles/mmmfs/examples/language_support/lua/text$lua -> mmm$dom.lua diff --git a/root/articles/mmmfs/language_support/lua/title: text$plain b/root/articles/mmmfs/examples/language_support/lua/title: text$plain index 0f9d550..0f9d550 100644 --- a/root/articles/mmmfs/language_support/lua/title: text$plain +++ b/root/articles/mmmfs/examples/language_support/lua/title: text$plain diff --git a/root/articles/mmmfs/language_support/moonscript/text$moonscript -> mmm$dom.moon b/root/articles/mmmfs/examples/language_support/moonscript/text$moonscript -> mmm$dom.moon index 5cc50e6..5cc50e6 100644 --- a/root/articles/mmmfs/language_support/moonscript/text$moonscript -> mmm$dom.moon +++ b/root/articles/mmmfs/examples/language_support/moonscript/text$moonscript -> mmm$dom.moon diff --git a/root/articles/mmmfs/language_support/moonscript/title: text$plain b/root/articles/mmmfs/examples/language_support/moonscript/title: text$plain index f8871ac..f8871ac 100644 --- a/root/articles/mmmfs/language_support/moonscript/title: text$plain +++ b/root/articles/mmmfs/examples/language_support/moonscript/title: text$plain diff --git a/root/articles/mmmfs/language_support/preview: text$markdown b/root/articles/mmmfs/examples/language_support/preview: text$markdown index d6c2845..d6c2845 100644 --- a/root/articles/mmmfs/language_support/preview: text$markdown +++ b/root/articles/mmmfs/examples/language_support/preview: text$markdown diff --git a/root/articles/mmmfs/language_support/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/examples/language_support/text$moonscript -> fn -> mmm$dom.moon index 4ae0679..4ae0679 100644 --- a/root/articles/mmmfs/language_support/text$moonscript -> fn -> mmm$dom.moon +++ b/root/articles/mmmfs/examples/language_support/text$moonscript -> fn -> mmm$dom.moon diff --git a/root/articles/mmmfs/language_support/title: text$plain b/root/articles/mmmfs/examples/language_support/title: text$plain index ae06474..ae06474 100644 --- a/root/articles/mmmfs/language_support/title: text$plain +++ b/root/articles/mmmfs/examples/language_support/title: text$plain diff --git a/root/articles/mmmfs/examples/markdown/text$markdown.md b/root/articles/mmmfs/examples/markdown/text$markdown.md new file mode 100644 index 0000000..880eedb --- /dev/null +++ b/root/articles/mmmfs/examples/markdown/text$markdown.md @@ -0,0 +1,20 @@ +This is a markdown document rendered using [marked][marked] on the client, and [discount][discount] on the server. +All Markdown features are supported, for example there is support for lists... + +- a list of things +- (two things) + +...and syntax-highlighted code tags: + +``` +print "Hello World" +``` + +Since Markdown supports inline HTML, mmmfs shorthands can also be used to embed and reference content from elsewhere in +the system. For example, the title of this fileder can be embedded using +`<mmm-embed facet="title"></mmm-embed>`: + +<mmm-embed facet="title"></mmm-embed> + +[marked]: https://marked.js.org/ +[discount]: https://luarocks.org/modules/craigb/discount diff --git a/root/articles/mmmfs/examples/markdown/title: text$plain b/root/articles/mmmfs/examples/markdown/title: text$plain new file mode 100644 index 0000000..7915148 --- /dev/null +++ b/root/articles/mmmfs/examples/markdown/title: text$plain @@ -0,0 +1 @@ +markdown content diff --git a/root/articles/mmmfs/examples/pinwall/$order b/root/articles/mmmfs/examples/pinwall/$order new file mode 100644 index 0000000..b8b054a --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/$order @@ -0,0 +1,3 @@ +image +text +video diff --git a/root/articles/mmmfs/examples/pinwall/image/image$png.png b/root/articles/mmmfs/examples/pinwall/image/image$png.png Binary files differnew file mode 100644 index 0000000..1628d99 --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/image/image$png.png diff --git a/root/articles/mmmfs/examples/pinwall/image/pinwall_info: text$json b/root/articles/mmmfs/examples/pinwall/image/pinwall_info: text$json new file mode 100644 index 0000000..e5893ac --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/image/pinwall_info: text$json @@ -0,0 +1 @@ +{"x": 94.0, "y": 265.0, "w": 205.0, "h": 155.0}
\ No newline at end of file diff --git a/root/articles/mmmfs/examples/pinwall/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/examples/pinwall/text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..e611579 --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,120 @@ +import article, div from require 'mmm.dom' +import convert from require 'mmm.mmmfs.conversion' + +update_info = (fileder, x, y, w, h) -> + info = (fileder\get 'pinwall_info: table') or x: 100, y: 100, w: 300, h: 300 + info.x = x if x + info.y = y if y + info.w = w if w + info.h = h if h + + json = convert 'table', 'text/json', info, fileder, 'pinwall_info' + fileder\set 'pinwall_info: text/json', json + +CLIENT = MODE == 'CLIENT' + +=> + + pending = {} + observe = if CLIENT + map = {} + observer = js.new js.global.ResizeObserver, (_, entries) -> + for entry in js.of entries + if child = map[entry.target] + rect = entry.contentRect + pending[child] = -> update_info child, nil, nil, rect.width, rect.height + + (node, child) -> + map[node] = child + observer\observe node + + drag = nil + + children = for child in *@children + info = (child\get 'pinwall_info: table') or x: 100, y: 100, w: 300, h: 300 + wrapper = div { + style: + position: 'absolute' + padding: '10px' + resize: 'both' + overflow: 'hidden' + background: 'var(--gray-dark)' + border: '1px solid var(--gray-bright)' + + left: "#{info.x}px" + top: "#{info.y}px" + width: "#{info.w}px" + height: "#{info.h}px" + + -- handle for moving the child + div { + style: + top: '0' + left: '0' + right: '0' + height: '10px' + cursor: 'pointer' + position: 'absolute' + + onmousedown: CLIENT and (_, e) -> + node = e.target.parentElement + drag = { + :child + :node + + startX: tonumber node.style.left\match '(%d+)px' + startY: tonumber node.style.top\match '(%d+)px' + startMouseX: e.clientX + startMouseY: e.clientY + } + } + + -- child content + div { + style: + width: '100%' + height: '100%' + background: 'var(--white)' + + (child\gett 'mmm/dom') + } + } + + -- listen for resize events + observe wrapper, child if CLIENT + wrapper + + children.style = { + width: '1000px' + height: '500px' + } + + if CLIENT + children.onmousemove = (_, e) -> + return unless drag + + x = drag.startX + (e.clientX - drag.startMouseX) + y = drag.startY + (e.clientY - drag.startMouseY) + drag.node.style.left = "#{x}px" + drag.node.style.top = "#{y}px" + + children.onmouseup = (_, e) -> + for k, func in pairs pending + func! + pending = {} + + return unless drag + + x = drag.startX + (e.clientX - drag.startMouseX) + y = drag.startY + (e.clientY - drag.startMouseY) + update_info drag.child, x, y + drag = nil + + children.onmouseleave = (_, e) -> + return unless drag + + drag.node.style.left = "#{drag.startX}px" + drag.node.style.top = "#{drag.startY}px" + drag = nil + + article children diff --git a/root/articles/mmmfs/examples/pinwall/text/pinwall_info: text$json b/root/articles/mmmfs/examples/pinwall/text/pinwall_info: text$json new file mode 100644 index 0000000..39bdb45 --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/text/pinwall_info: text$json @@ -0,0 +1 @@ +{"x": 53.0, "y": 64.0, "w": 396.0, "h": 74.0}
\ No newline at end of file diff --git a/root/articles/mmmfs/examples/pinwall/text/text$plain.txt b/root/articles/mmmfs/examples/pinwall/text/text$plain.txt new file mode 100644 index 0000000..8838e5a --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/text/text$plain.txt @@ -0,0 +1,4 @@ +This is a pinwall example. +Every box is a separate fileder. +The boxes can be rearranged and resized freely. +If the server is in read-write mode, the changes are saved persistently in real time. diff --git a/root/articles/mmmfs/examples/pinwall/title: text$plain b/root/articles/mmmfs/examples/pinwall/title: text$plain new file mode 100644 index 0000000..c629992 --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/title: text$plain @@ -0,0 +1 @@ +a pinwall diff --git a/root/articles/mmmfs/examples/pinwall/video/URL -> video$mp4 b/root/articles/mmmfs/examples/pinwall/video/URL -> video$mp4 new file mode 100644 index 0000000..6364771 --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/video/URL -> video$mp4 @@ -0,0 +1 @@ +https://file-examples.com/wp-content/uploads/2017/04/file_example_MP4_480_1_5MG.mp4 diff --git a/root/articles/mmmfs/examples/pinwall/video/pinwall_info: text$json b/root/articles/mmmfs/examples/pinwall/video/pinwall_info: text$json new file mode 100644 index 0000000..7be8702 --- /dev/null +++ b/root/articles/mmmfs/examples/pinwall/video/pinwall_info: text$json @@ -0,0 +1 @@ +{"x": 534.0, "y": 136.0, "w": 387.0, "h": 218.0}
\ No newline at end of file diff --git a/root/articles/mmmfs/examples/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/examples/text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..2988f29 --- /dev/null +++ b/root/articles/mmmfs/examples/text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,44 @@ +-- main content +-- doesn't have a name prefix (e.g. preview: fn -> mmm/dom) +-- uses the 'fn ->' conversion to execute the lua function on @get +-- resolves to a value of type mmm/dom +=> + html = require 'mmm.dom' + import h4, div, a, span, ul, li from html + import link_to from (require 'mmm.mmmfs.util') html + + -- render a preview block + preview = (child) -> + -- get 'title' as 'text/plain' (error if no value or conversion possible) + title = child\gett 'title', 'text/plain' + + -- get 'preview' as a DOM description (nil if no value or conversion possible) + -- content = child\get 'preview', 'mmm/dom' + + -- div { + -- h4 title, style: { margin: 0, cursor: 'pointer' }, onclick: -> BROWSER\navigate child.path + -- content or span '(no renderable content)', style: { color: 'red' }, + -- style: { + -- display: 'inline-block', + -- width: '300px', + -- height: '200px', + -- padding: '4px', + -- margin: '8px', + -- border: '4px solid #eeeeee', + -- overflow: 'hidden', + -- }, + -- } + + li link_to child + + examples = ul for child in *@children + preview child + + div { + style: + 'break-after': 'page' + + (@gett 'intro: mmm/dom') + examples + (@gett 'implementation: mmm/dom') + } diff --git a/root/articles/mmmfs/framework/text$markdown+sidenotes.md b/root/articles/mmmfs/framework/text$markdown+sidenotes.md new file mode 100644 index 0000000..e5f3c7e --- /dev/null +++ b/root/articles/mmmfs/framework/text$markdown+sidenotes.md @@ -0,0 +1,96 @@ +# 4 evaluation framework + +In this section, I will collect approaches and reviews of different end-user software systems from current literature, +as well as derive and present my own requirements and guiding principles for the development of a new system. + +Firstly, I will take a look at a framework for evaluating end-user computing systems from literature, before presenting +three concrete design principles and components for a new system. + +4.1 qualities of successful end-user computing +--------------------------------------------------- + +*Ink and Switch* suggest three qualities for tools striving to support <span style="display: inline-block;"> +end-user programming<mmm-embed path="../references/inkandswitch" wrap="sidenote"></mmm-embed>:</span> + +- *Embodiment*, i.e. reifying central concepts of the programming model as more concrete, tangible objects + in the digital space (for example, through visual representation), + in order to reduce cognitive load on the user. +- *Living System*, by which they seem to describe the malleability of a system or environment, + and in particular the ability to make changes at different levels of depth in the system with + very short feedback loops and a feeling of direct experience. +- *In-place toolchain*, denoting the availability of tools to customize and author the experience, + as well as a certain accessibility of these tools, granted by a conceptual affinity between the + use of the tools and general 'passive' use of containing system at large. + +These serve as guiding principles for the design and evaluation of computer systems for end-users but are by nature +very abstract. The following properties are therefore derived as more concrete proposals based on more specific +constraints: namely the construction of a system for end-users to keep, structure and display personal information and +thoughts. + +<div style="break-after: page;"></div> + +4.2 modularity +------------------- + +The *UNIX Philosophy*<mmm-embed path="../references/unix" wrap="sidenote"></mmm-embed> describes the software design +paradigm pioneered in the creation of the Unix operating system at the AT&T Bell Labs research center in the 1960s. The +concepts are considered quite influential and are still notably applied in the Linux community. Many attempts at +summaries exist, but the following includes the pieces that are especially relevant even today: + +<mmm-embed path="../references/unix" wrap="marginnote"></mmm-embed> +> Even though the UNIX system introduces a number of innovative programs and techniques, no single program or idea makes +> it work well. Instead, what makes it effective is the approach to programming, a philosophy of using the computer. +> Although that philosophy can't be written down in a single sentence, at its heart is the idea that the power of a +> system comes more from the relationships among programs than from the programs themselves. Many UNIX programs do quite +> trivial things in isolation, but, combined with other programs, become general and useful tools. + +This approach has multiple benefits with regard to end-user programmability: Assembling the system out of simple, +modular pieces means that for any given task a user may want to implement, it is very likely that preexisting parts +of the system can help the user realize a solution. Wherever such a preexisting part exists, it pays off designing it +in such a way that it is easy to integrate for the user later. Assembling the system as a collection of modular, +interacting pieces also enables future growth and customization, since pieces may be swapped out with customized or +alternate software at any time. + +Settling on a specific modular design model, and reifying other components of a system in terms of it, also corresponds +directly to the concept of *Embodiment* described by Ink & Switch. + +4.3 content transclusion +----------------------------- + +The strengths of modular architectures should similarly extend also into the way the system will be used by users. +If users are to store their information and customized behavior in such an architecture, then powerful tools need to be +present in order to assemble more complex solutions out of such parts. Therefore static content should be able to be +linked to (as envisioned for the *Memex*, see above), but also to be <mmm-embed wrap="marginnote" +path="../references/transclusion">The term <i>transclusion</i> refers to the concept of including content from a +separate document, possibly stored remotely, by reference rather than by duplication. See also +</mmm-embed>*transcluded*, +to facilitate the creation of flexible data formats and interactions, such that e.g. a slideshow slide can include +content in a variety other formats (such as images and text) from anywhere else in the system. Behaviors also should be +able to be transcluded and reused to facilitate the creation of ad-hoc systems and applets based on user needs. For +example, a user-created todo list should be able to take advantage of a sketching tool the user already has access to. + +By forming the immediately user-visible layer of the system out of the same abstractions that the deeper levels of the +system are made of, the sense of a *Living System* is also improved: skills that are learned at one (lower) level of the +system carry on into further interaction with the system on deeper levels, as does progress in understanding the +system's mechanisms. + +While there are drawbacks to cloud-storage of data (as outlined above), the utility of distributed systems is +acknowledged, and the system should therefore be able to include content and behaviors via the network. +This ability should be integrated deeply into the system, so that data can be treated independently of its origin and +storage conditions, with as little caveats as possible. In particular, the interactions of remote data access and +content transclusion should be paid attention to and taken into consideration for a system's design. + +4.4 end-user programming +----------------------------- + +In order to provide users full access to their information as well as the computational infrastructure, +users need to be able to finely customize and reorganize the smallest pieces to suit their own purposes, +in other words: be able to program. + +While there is an ongoing area of research focusing on the development of new programming paradigms, +methodologies, and tools that are more accessible and cater to the wide +range of end-users<mmm-embed path="../references/subtext" wrap="sidenote"></mmm-embed>, +in order to keep the scope of this work appropriate, +conventional programming languages are used for the time being. +Confidence is placed in the fact that eventually more user-friendly languages will be available and, +given the goal of modularity, should be implementable in a straightforward fashion. diff --git a/root/articles/mmmfs/gallery/preview: text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/gallery/preview: text$moonscript -> fn -> mmm$dom.moon deleted file mode 100644 index 5285629..0000000 --- a/root/articles/mmmfs/gallery/preview: text$moonscript -> fn -> mmm$dom.moon +++ /dev/null @@ -1,7 +0,0 @@ -import div, img, br from require 'mmm.dom' - -=> div { - 'the first pic as a little taste:', - br!, - img src: @children[1]\get 'preview', 'URL -> image/png' -} diff --git a/root/articles/mmmfs/gallery/title: text$plain b/root/articles/mmmfs/gallery/title: text$plain deleted file mode 100644 index ad74eec..0000000 --- a/root/articles/mmmfs/gallery/title: text$plain +++ /dev/null @@ -1 +0,0 @@ -A Gallery of 25 random pictures, come on in! diff --git a/root/articles/mmmfs/historical-approaches/$order b/root/articles/mmmfs/historical-approaches/$order new file mode 100644 index 0000000..b98a91b --- /dev/null +++ b/root/articles/mmmfs/historical-approaches/$order @@ -0,0 +1 @@ +star-graph diff --git a/root/articles/mmmfs/historical-approaches/star-graph/image$png.png b/root/articles/mmmfs/historical-approaches/star-graph/image$png.png Binary files differnew file mode 100644 index 0000000..ed4003c --- /dev/null +++ b/root/articles/mmmfs/historical-approaches/star-graph/image$png.png diff --git a/root/articles/mmmfs/historical-approaches/star-graph/note: text$markdown.md b/root/articles/mmmfs/historical-approaches/star-graph/note: text$markdown.md new file mode 100644 index 0000000..eb115dd --- /dev/null +++ b/root/articles/mmmfs/historical-approaches/star-graph/note: text$markdown.md @@ -0,0 +1,4 @@ +<p><i>How systems influenced later systems. This graph summarizes how various systems related to Star have influenced +one another over the years. Time progresses downwards. Double arrows indicate direct successors (i.e., +follow-on versions). [...]</i></p> +<mmm-embed wrap="raw" path="../../references/xerox-star"></mmm-embed> diff --git a/root/articles/mmmfs/historical-approaches/text$markdown+sidenotes.md b/root/articles/mmmfs/historical-approaches/text$markdown+sidenotes.md new file mode 100644 index 0000000..dfe9390 --- /dev/null +++ b/root/articles/mmmfs/historical-approaches/text$markdown+sidenotes.md @@ -0,0 +1,73 @@ +<div style="break-before: page;"></div> + +# 3 historical approaches + +Two of the earliest holistic computing systems, the Xerox Alto and Xerox Star, both developed at Xerox PARC and +introduced in the 70s and early 80s pioneered not only graphical user-interfaces but also the "Desktop Metaphor". +The desktop metaphor presents information as stored in "Documents" that can be organized in folders and on the +"Desktop". It invokes a strong analogy to physical tools. One of the differences between the Xerox Star system and +other systems at the time, as well as the systems we use currently, is that the type of data a file represents is +directly known to the system. + +In a retrospective analysis of the Xerox Star's impact on the computer industry, the desktop metaphor is described as +follows: + +<mmm-embed path="../references/xerox-star" wrap="marginnote"></mmm-embed> +> In a Desktop metaphor system, users deal mainly with data files, oblivious to the existence of programs. +> They do not "invoke a text editor", they "open a document". +> The system knows the type of each file and notifies the relevant application program when one is opened. +> +> The disadvantage of assigning data files to applications is that users sometimes want to operate on a file with a +> program other than its "assigned" application. \[...\] +> Star's designers feel that, for its audience, the advantages of allowing users to forget about programs outweighs +> this disadvantage. + +Other systems at the time lacked any knowledge of the type of files, and while mainstream operating systems of today +have retro-fit the ability to associate and memorize the preferred applications to use for a given file based on its +name suffix, the intention of making applications a secondary, technical detail of working with the computer has +surely been lost. + +Another design detail of the Star system is the concept of "properties" that are stored for "objects" throughout the +system (the objects being anything from files to characters or paragraphs). These typed pieces of information are +labeled with a name and persistently stored, providing a mechanism to store metadata such as user preference for +ordering or the default view mode of a folder for example. + +The earliest indirect influence for the Xerox Alto and many other systems of its time was the *Memex*. +The *Memex* is a hypothetical device and system for knowledge management. Proposed by Vannevar Bush in 1945<mmm-embed +path="../references/memex" wrap="sidenote"></mmm-embed>, the concept predates much of the technology that later was used +to implement many parts of the vision. + +<mmm-embed path="star-graph" facet="note" wrap="marginnote" style="margin-top: 1rem;"></mmm-embed> +<mmm-embed path="star-graph" nolink></mmm-embed> + +<!-- +While the article extrapolates from existing technology at the time, describing at times +very concrete machinery based on microfilm and mechanical contraptions, many of the conceptual predictions became +true or inspired .... +--> + +One of the most innovative elements of Bush's predictions is the idea of technologically cross-referenced and +connected information, which would later be known and created as *hypertext*. While hypertext powers the majority of +today's internet, many of the advantages that Bush imagined have not carried over into the personal use of computers. +There are very few tools for creating personal, highly-interconnected knowledge bases, even though it is technologically +feasible and a proven concept (exemplified for example by the massively successful online encyclopedia +*Wikipedia*<mmm-embed path="../references/wikipedia" wrap="sidenote"></mmm-embed>). + +While there are few such tools available today, one of the systems that could be said to have come closest to a +practical implementation of a Memex-inspired system for personal use might be Apple's *HyperCard*. + +In a live demonstration<mmm-embed path="../references/hypercard" wrap="sidenote"></mmm-embed>, the creators of the +software showcase a system of stacks of cards that together implement, amongst others, a calendar (with yearly and +weekly views), a list of digital business cards for storing phone numbers and addresses, and a todo list. However these +stacks of cards are not just usable by themselves, it is also demonstrated how stacks can link to each other in +meaningful ways, such as jumping to the card corresponding to a specific day from the yearly calendar view or +automatically looking up the card corresponding to a person's first name from a mention of the name in the text on a +different card. + +Alongside Spreadsheets, *HyperCard* remains one of the most successful implementations of end-user programming, even +today. While its technical abilities have been long matched and surpassed by other software (such as the ubiquitous +*Hypertext Markup Language* HTML, and the associated programming language *JavaScript*), these technical successors have +failed the legacy of *HyperCard* as an end-user tool: While it is easier than ever to publish content on the web +(through various social media and microblogging services), the benefits of hypermedia as a customizable medium for +personal management have nearly vanished. End-users do not create hypertext anymore. + diff --git a/root/articles/mmmfs/image/preview: text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/image/preview: text$moonscript -> fn -> mmm$dom.moon deleted file mode 100644 index 6c431d0..0000000 --- a/root/articles/mmmfs/image/preview: text$moonscript -> fn -> mmm$dom.moon +++ /dev/null @@ -1,5 +0,0 @@ -import img from require 'mmm.dom' - --- look for main content with 'URL to png' type --- and wrap in an mmm/dom image tag -=> img src: @gett 'URL -> image/png' diff --git a/root/articles/mmmfs/image/title: text$plain b/root/articles/mmmfs/image/title: text$plain deleted file mode 100644 index 60a556f..0000000 --- a/root/articles/mmmfs/image/title: text$plain +++ /dev/null @@ -1 +0,0 @@ -Hey I'm like a link to a picture or smth diff --git a/root/articles/mmmfs/introduction/text$markdown.md b/root/articles/mmmfs/introduction/text$markdown.md new file mode 100644 index 0000000..b8550fe --- /dev/null +++ b/root/articles/mmmfs/introduction/text$markdown.md @@ -0,0 +1,18 @@ +1 introduction +==================== + +As of December 2019, there are only four major operating systems available to end-users for desktop and mobile +devices<mmm-embed path="../references/market-share" wrap="sidenote"></mmm-embed>. All of these systems are comparatively inflexible and +can only be customized by users where the system or application developers have anticipated a need with corresponding +options. Only a small minority of professional or hobby developers have the knowledge and tools at their disposal to +create their own digital experiences, and even for them, the process is often too complex and inefficient to do so +effectively. +However, historically, empowered ownership of the computing experience was not meant to be restricted only to +end-users. Many computing systems designed during the computer revolution were designed specifically with the goal of +complete customizability by users, but little of this approach remains in the systems we use today. + +In the first section of this thesis, I will discuss some of the limitations of mainstream operating systems and +potential causes in detail. Next, I will highlight some of the contrasting approaches found in historic computing +systems, and then derive a framework for the evaluation of end-user computing systems with regard to user empowerment. +I will then discuss a new computing system, demonstrate it in some example use cases, and evaluate it using the +framework. diff --git a/root/articles/mmmfs/markdown/preview: text$markdown.md b/root/articles/mmmfs/markdown/preview: text$markdown.md deleted file mode 100644 index 4b38ef2..0000000 --- a/root/articles/mmmfs/markdown/preview: text$markdown.md +++ /dev/null @@ -1,6 +0,0 @@ -See I have like - -- a list of things -- (two things) - -and some bold **text** and `code tags` with me. diff --git a/root/articles/mmmfs/markdown/title: text$plain b/root/articles/mmmfs/markdown/title: text$plain deleted file mode 100644 index 319068d..0000000 --- a/root/articles/mmmfs/markdown/title: text$plain +++ /dev/null @@ -1 +0,0 @@ - I'm not even five lines of markdown but i render myself! diff --git a/root/articles/mmmfs/mmmfs/$order b/root/articles/mmmfs/mmmfs/$order new file mode 100644 index 0000000..5a5d5ab --- /dev/null +++ b/root/articles/mmmfs/mmmfs/$order @@ -0,0 +1,3 @@ +type_coercion_graph +tree_mmmfs +tree_mainstream diff --git a/root/articles/mmmfs/mmmfs/text$markdown+sidenotes.md b/root/articles/mmmfs/mmmfs/text$markdown+sidenotes.md new file mode 100644 index 0000000..f04e671 --- /dev/null +++ b/root/articles/mmmfs/mmmfs/text$markdown+sidenotes.md @@ -0,0 +1,197 @@ +# 5 system description + +Alongside this thesis, a new end-user computing system has been developed together with the framework presented above. +The system, `mmmfs`, is a personal data storage and processing system that was initially developed as a tool for +generating static websites but has now been extended with capabilities for live interaction and introspection, as well +as embedded editing, as part of this work. + +mmmfs has been designed with a focus on data ownership for users. One of the main driving ideas is to unlock data +from external data silos and file formats by making data available uniformly across different storage systems and +formats. Secondly, computation and interactive elements are also integrated into this paradigm, so that mmmfs can be +seamlessly extended and molded to the user's needs. + +The abstraction of data types is accomplished using two major components, the *Type System and Coercion Engine* and +the *Fileder Unified Data Model* for unified data storage and access. In the next sections, the design and +implementation of these two components will be described in detail. + +## 5.1 data storage model +The Fileder Model is the underlying unified data storage model. +Like many data storage models it is based fundamentally on the concept of a hierarchical tree-structure. + +<mmm-embed path="tree_mainstream">schematic view of an example tree in a mainstream filesystem</mmm-embed> + +In common filesystems, as pictured, data can be organized hierarchically into *folders* (or *directories*), +which serve only as containers of *files*, in which data is actually stored. While *directories* are fully transparent +to both system and user (they can be created, browsed, listed and viewed by both), *files* are, from the system +perspective, mostly opaque and inert blocks of data. + +Some metadata, such as file size and access permissions, is associated with each file, +but notably, the type of data is generally not actually stored in the filesystem, +but determined loosely based on multiple heuristics depending on the system and context. +Some notable mechanisms are: + +- Suffixes at the end of the filename are often used to indicate which kind of data a file contains. However there is no + centralized standardization of suffixes, and often one suffix is used for multiple incompatible versions of a + file-formats, or multiple suffixes are used interchangeably for one format. +- Many file-formats specify a specific data-pattern either at the very beginning or very end of a given file. + On UNIX systems the `libmagic` database and library of these so-called *magic constants* is commonly used to guess + the file-type based on these fragments of data. +- on UNIX systems, files to be executed are checked by a variety of methods<mmm-embed path="../references/linux-exec" + wrap="sidenote"></mmm-embed> in order to determine which format would fit. For example, script files, the "shebang" + symbol, `#!`, can be used to specify the program that should parse this file in the first line of the file. + +It should be clear already from this short list that to mainstream operating systems, as well as the applications +running on them, the format of a file is almost completely unknown and, at best, educated guesses can be made. + +Because these various mechanisms are applied at different times by the operating system and applications, it is possible +for files to be labeled or considered as being in different formats at the same time by different components of the +system. + +This leads to confusion about the factual format of data among users<mmm-embed path="../references/renaming" +wrap="sidenote" style="margin-top: -3rem;">For example, the difference between changing a file extension and converting +a file between two formats is often unclear to users, as evident from questions like this: </mmm-embed>, but can +also pose a serious security risk: +Under some circumstances, it is possible that a file contains maliciously-crafted code and is treated as an executable +by one software component, while a security mechanism meant to detect such code determines the same file to be a +legitimate image<mmm-embed path="../references/poc-or-gtfo" wrap="sidenote" style="margin-top: 2rem"></mmm-embed> +(the file may in fact be valid in both formats). + +In mmmfs, the example above might look like this instead: +<mmm-embed path="tree_mmmfs">schematic view of an example mmmfs tree</mmm-embed> + +Superficially, this may look quite similar: there are still only two types of nodes (referred to as *fileders* and +*facets*), and again one of them, the *fileders* are used only to hierarchically organize *facets*. Unlike *files*, +*facets* don't only store a freeform *name*, there is also a dedicated *type* field associated with every *facet*, that +is explicitly designed to be understood and used by the system. + +Despite the similarities, the semantics of this system are very different: In mainstream filesystems, each *file* stands +for itself only; i.e. in a *directory*, no relationship between *files* is assumed by default, and files are most of the +time read or used outside of the context they exist in in the filesystem. + +In mmmfs, a *facet* should only ever be considered an aspect of its *fileder*, and never as separate from it. +A *fileder* can contain multiple *facets*, but they are meant to be alternate or equivalent representations of the +*fileder* itself. Though for some uses it is required, software generally does not have to be directly aware of the +*facets* existing within a *fileder*, rather it assumes the presence of content in the representation that it requires, +and simple requests it. The *Type Coercion Engine* (see below) will then attempt to satisfy this request based on the +*facets* that are in fact present. + +Semantically a *fileder*, like a *directory*, also encompasses all the other *fileders* nested within itself +(recursively). Since *fileders* are the primary unit of data to be operated upon, *fileder* nesting emerges as a natural +way of structuring complex data, both for access by the system and its components, as well as the user themself. + +<div style="break-after: page;"></div> + +## 5.2 type system and coercion engine +As mentioned above, *facets* store data alongside its *type*, and when a component of the system requires data from a +*fileder*, it has to specify the *expected type* (or a list of these) that it requires the data to be in. The system +then attempts to coerce one of the existing facets into the *expected type*, if possible. This process can involve many +steps such as converting between similar file formats, running executable code stored in a facet, or fetching remote +content. The component that requested the data is isolated from this process and does not have to deal with any of the +details. + +In the current iteration of the type system, types are simple strings of text and loosely based on MIME-types<mmm-embed +path="../references/mime-types" wrap="sidenote"></mmm-embed>. +MIME types consist of a major- and minor category, and optionally a 'suffix'. +Here are some common MIME-types that are also used in mmmfs: + +- `text/html` and `text/html+frag` (mmmfs only) +- `text/javascript` +- `image/png` +- `image/jpeg` + +While these types allow some amount of specificity, they fall short of describing their content especially in cases +where formats overlap: Source code, for example, is often distributed in `.tar.gz` archive files (directory-trees that +are first bundled into an `application/x-tar` archive, and then compressed into an `application/gzip` archive). Using +either of these two types is respectively incorrect or insufficient information to properly treat and extract the +contained data. + +To mitigate this problem, mmmfs *types* can be nested. This is denoted in mmmfs *type* strings using the `->` symbol, +e.g. the mmmfs *types* `application/gzip -> application/tar -> dirtree` and `URL -> image/jpeg` describe a +tar-gz-compressed directory tree and the URL linking to a JPEG-encoded picture respectively. + +Depending on the outer type this nesting can mean different things: +for URLs, the nested type is expected to be found after fetching the URL with HTTP, +compression formats are expected to contain contents of the nested types, +and executable formats are expected to output data of the nested type. + +It is a lot more important to be able to accurately describe the type of a *facet* in mmmfs than in mainstream operating +systems because while in the latter types are mostly used only associate an application that will then prompt the user +for further steps if necessary, mmmfs uses the *type* to automatically find one or more programs to execute, in order to +convert or transform the data stored in a *facet* into the *type* required in the context where it was requested. + +This process of *type coercion* uses a database of known *converts* that can be applied to data. Every *convert* +consists of a description of the input *types* that it can accept, the output *type* it would produce for a given input +type, as well as the code for actually converting a given piece of data. Simple *converts* may simply consist of a fixed +in and output type, such as this *convert* for rendering Markdown-encoded text to an HTML hypertext fragment: + + { + inp: 'text/markdown' + out: 'text/html+frag' + transform: (value, ...) -> + -- implementation stripped for brevity + } + +Other *converts*, on the other hand, may accept a wide range of input types: + + { + inp: 'URL -> image/.*' + out: 'text/html+frag' + transform: (url) -> img src: url + } + +This convert uses a Lua Pattern to specify that it can accept an URL to any type of image, +and convert it to an HTML fragment. + +By using the pattern substitution syntax provided by the Lua `string.gsub` function, converts can also make the type +they return depend on the input type, as is required often when nested types are unpacked: + + { + inp: 'application/gzip -> (.*)' + out: '%1' + transform: (data) -> + -- implementation stripped for brevity + } + +This *convert* accepts an `application/gzip` *type* wrapping any other *type*, and captures that nested type in a +pattern group. It then uses the substitution syntax to specify that nested type as the output of the conversion. +For an input *type* of `application/gzip -> image/png` this *convert* would therefore generate the type `image/png`. + +This last example further demonstrates the flexibility of this approach: + + { + inp: 'text/moonscript -> (.*)' + out: 'text/lua -> %1' + transform: (code) -> moonscript.to_lua code + } + +This *convert* transpiles MoonScript source-code into Lua source-code, while keeping the nested type +(in this case the result expected when executing either script) the same. + +In addition to the attributes shown above, every *convert* is also rated with a *cost* value. The cost value is meant to +roughly estimate both the cost (in terms of computing power) of the conversion, as well as the accuracy or immediacy of +the conversion. For example, resizing an image to a lower size should have a high cost, because the process is +computationally expensive, but also because a smaller image represents the original image to a lesser degree. +Similarly, a URL to a piece of content is a less immediate representation than the content itself, so the cost of a +*convert* that simply generates the URL to a piece of data should be high even if the process is very cheap to compute. + +Cost is defined in this way to make sure that the result of a type-coercion operation reflects the content that was +present as accurately as possible. It is also important to prevent some nonsensical results from occurring, such as +displaying a link to content instead of the content itself because the link is cheaper to create than completely +converting the content does. + +Type coercion is implemented using a general pathfinding algorithm, based on *Dijkstra's Algorithm*<mmm-embed +path="../references/dijkstra" wrap="sidenote"></mmm-embed>. First, the set of given *types* is found by selecting all +*facets* of the *fileder* that match the *name* given in the query. The set of given *types* is marked in green in the +following example graph. +From there the algorithm recursively checks whether it can reach other *types* by applying all matching *converts* to +the *type* that is the cheapest to reach currently, excluding any *types* that have already been exhaustively-searched +in this way. All *types* found that have not yet been inserted into the set of given *types* are then added to the +set, so that they may be searched as well. + +The algorithm doesn't stop immediately after reaching a *type* from the result set, it continues to search until it +either completely exhausts the result-space, or until all non-exhaustively searched paths already have costs higher than +the allowed maximum. This ensures that the optimal path is found, even if a more expensive path is found more quickly +initially. + +<mmm-embed path="type_coercion_graph">excerpt of the graph of conversion paths from two starting facets to mmm/dom +</mmm-embed> diff --git a/root/articles/mmmfs/mmmfs/tree_mainstream/text$mermaid-graph b/root/articles/mmmfs/mmmfs/tree_mainstream/text$mermaid-graph new file mode 100644 index 0000000..3227e47 --- /dev/null +++ b/root/articles/mmmfs/mmmfs/tree_mainstream/text$mermaid-graph @@ -0,0 +1,11 @@ +graph TD + Documents --> Movies --> m1{{A Movie.mp4}} + Documents --> Pictures --> vacation[Summer Vacation] + vacation --> v1{{1.jpg}} + vacation --> v2{{2.jpg}} + Pictures --> Projects + Projects --> p1{{1.jpg}} + Projects --> p2{{2.jpg}} + + classDef file fill:#f9f; + class m1,v1,v2,p1,p2 file; diff --git a/root/articles/mmmfs/mmmfs/tree_mmmfs/text$mermaid-graph b/root/articles/mmmfs/mmmfs/tree_mmmfs/text$mermaid-graph new file mode 100644 index 0000000..7b4f6f4 --- /dev/null +++ b/root/articles/mmmfs/mmmfs/tree_mmmfs/text$mermaid-graph @@ -0,0 +1,21 @@ +graph TD + Documents --> Movies --> m1[A Movie.mp4] + m1 --> m1.f{{video/mp4}} + + Documents --> Pictures --> vacation[Summer Vacation] + vacation --> slideshow{{slideshow: script -> UI}} + vacation --> gallery{{gallery: script -> UI}} + vacation --> v1[1.jpg] + vacation --> v2[2.jpg] + v1 --> v1.f{{image/jpeg}} + v2 --> v2.f{{image/jpeg}} + + Pictures --> Projects + Projects --> p1[1.jpg] + Projects --> p2[2.jpg] + p1 --> p1.f{{image/jpeg}} + p2 --> p2.f{{image/jpeg}} + + classDef default fill:#f00,stroke:#333,stroke-width:4px; + classDef file fill:#f9f; + class slideshow,gallery,m1.f,v1.f,v2.f,p1.f,p2.f file; diff --git a/root/articles/mmmfs/mmmfs/type_coercion_graph/text$mermaid-graph b/root/articles/mmmfs/mmmfs/type_coercion_graph/text$mermaid-graph new file mode 100644 index 0000000..cf2cf1e --- /dev/null +++ b/root/articles/mmmfs/mmmfs/type_coercion_graph/text$mermaid-graph @@ -0,0 +1,22 @@ +graph LR + md_lua[text/lua -> text/markdown] + md[text/markdown] + moon[text/moonscript -> fn -> mmm/dom] + lua[text/lua -> fn -> mmm/dom] + fn[fn -> mmm/dom] + dom[mmm/dom] + moon_url[URL -> text/moonscript -> fn -> mmm/dom] + lua_url[URL -> text/lua -> fn -> mmm/dom] + + md_lua -- cost: 1 --> md -- cost: 2 --> dom + moon -- cost: 5 --> moon_url + moon -- cost: 1 --> fn -- cost: 2 --> dom + moon -- cost: 2 --> lua -- cost: 5 --> lua_url + lua -- cost: 1 --> fn + moon_url -- cost: 10 --> dom + lua_url -- cost: 10 -->dom + + classDef given fill:#ada; + classDef path stroke:#ada; + linkStyle 3,1,0,4 stroke:#8d8,stroke-width:2px + class md_lua,moon given diff --git a/root/articles/mmmfs/motivation/$order b/root/articles/mmmfs/motivation/$order new file mode 100644 index 0000000..accfc0b --- /dev/null +++ b/root/articles/mmmfs/motivation/$order @@ -0,0 +1,2 @@ +app-types +creative diff --git a/root/articles/mmmfs/motivation/app-types/text$markdown.md b/root/articles/mmmfs/motivation/app-types/text$markdown.md new file mode 100644 index 0000000..aedef1c --- /dev/null +++ b/root/articles/mmmfs/motivation/app-types/text$markdown.md @@ -0,0 +1,3 @@ +While there can be a distinction between *Native Applications* and *Web Applications* or *Cloud Services*, the following +arguments apply to all different technical implementations of this same concept. The problems associated specifically +with Web- and Cloud-based application models will be discussed separately below. diff --git a/root/articles/mmmfs/motivation/creative/text$markdown.md b/root/articles/mmmfs/motivation/creative/text$markdown.md new file mode 100644 index 0000000..9dd6162 --- /dev/null +++ b/root/articles/mmmfs/motivation/creative/text$markdown.md @@ -0,0 +1,2 @@ +Note that 'creative' here does not only mean 'artistic': this applies to any field, and limits the ability of domain +experts to push the boundaries of practice by using technology in innovative ways. diff --git a/root/articles/mmmfs/motivation/text$markdown+sidenotes.md b/root/articles/mmmfs/motivation/text$markdown+sidenotes.md new file mode 100644 index 0000000..64a3459 --- /dev/null +++ b/root/articles/mmmfs/motivation/text$markdown+sidenotes.md @@ -0,0 +1,138 @@ +# 2 drawbacks of current systems + +The project that this thesis accompanies was created out of frustration with the computing systems that are currently +popular and widely available to end-users. The following sections document and exemplify the perceived shortcomings that +these systems exhibit, as attributed to specific concepts or paradigms that the systems seem to be designed around. + +2.1 application-centric design +----------------------------------- + +The majority of users interact with modern computing systems in the form of smartphones, laptops or desktop PCs, +using the mainstream operating systems Apple iOS and Mac OS X, Microsoft Windows or Android. + +<mmm-embed path="app-types" wrap="marginnote"></mmm-embed> +All of these operating systems share the concept of *Applications* (or *Apps*) as one of the core pieces of their +interaction model. The functionality and capabilities of digital devices are bundled, marketed, sold and distributed +as applications. This focus on applications as the primary unit of systems can be seen as the root cause of multiple +problems. + +For one, since applications are produced by private companies on the software market, +developers compete on features integrated into their applications. To stay relevant, monolithic software or software +suites tend to accrete features rather then modularize and delegate to other software<mmm-embed wrap="sidenote" +path="../references/appliances"></mmm-embed>. This makes many software packages more complex and unintuitive than +they need to be, and also cripples interoperability between applications and data formats. + +Because (private) software developers are incentivized to keep customers, they make use of network effects to keep +customers locked-in. This often means re-implementing services and functionality that is already available to users, +and integrating it directly in other applications or as a new product by the same organization. +While this strategy helps big software companies retain customers, it harms users, who have to navigate a complex +landscape of multiple incompatible, overlapping, and competing software ecosystems. +Data of the same kind, a rich-text document, for example, can be shared easily within the software systems of a certain +manufacturer and with other users of the same, but sharing with users of a competing system, even if it has almost the +same capabilities, can often be problematic<mmm-embed path="../references/lock-in" wrap="sidenote"></mmm-embed>. + +Another issue is that due to the technical challenges of development in this paradigm, applications are designed and +developed by experts in application development, rather than experts in the domain of the tool. While developers may +solicit feedback, advice, and ideas from domain experts, communication is a barrier. Additionally, domain experts are +generally unfamiliar with the technical possibilities, and may therefore not be able to express feedback that would lead +to more significant advances. +<mmm-embed path="creative" wrap="marginnote"></mmm-embed> +As a result, creative use of computer technology is limited to programmers, since applications constrain their users to +the paths and abilities that the developers anticipated and deemed useful. + +The application-centric computing metaphor treats applications as black boxes and provides no means to understand, +customize or modify the behavior of apps, intentionally obscuring the inner-workings of applications and +completely cutting users off from this type of ownership over their technology. While the trend seems to be to further +hide the way desktop operating systems work<mmm-embed path="../references/osx-files" wrap="sidenote"></mmm-embed>, +mobile systems like Apple's *iOS* were designed as such *walled gardens* from the start. + +2.2 cloud computing +------------------------ + +*Web Apps* often offer similar functionality to other applications but are subject to additional limitations: +In most cases, they are only accessible or functional in the presence of a stable internet connection, +and they have very limited access to the resources of the physical computer they are running on. +For example, they usually cannot interact directly with the file system, hardware peripherals or other applications, +other than through a standardized set of interactions (e.g. selecting a file via a visual menu, capturing audio and +video from a webcam, opening another website). + +Cloud software, as well as subscription-model software with online-verification mechanisms, are additionally subject +to license changes, updates modifying, restricting or simply removing past functionality, etc. Additionally, many cloud +software solutions and ecosystems store the users' data in the cloud, often across national borders, where legal and +privacy concerns are intransparently handled by the companies. If a company, for any reason, is unable or unwilling to +continue servicing a customer, the user's data may be irrecoverably lost (or access prevented). This can have serious +consequences<mmm-embed path="../references/adobe" wrap="sidenote"></mmm-embed>, especially for professional users, for +whom an inability to access their tools or their cloud-stored data can pose an existential threat. + +2.3 inert data (and data formats) +-------------------------------------- + +Cragg coins the term "inert data"<mmm-embed path="../references/super-powers" wrap="sidenote"></mmm-embed> for the data +created and left behind by apps and applications in the computing model that is currently prevalent: Most data today +is either intrinsically linked to one specific application, that controls and limits access to the actual information, +or, even worse, stored in the cloud where users have no direct access at all. In the latter case, users depend solely on +online tools that require a stable network connection and a modern browser and could be modified, removed, or otherwise +negatively impacted at any moment. + +Aside from being inaccessible to users, the resulting complex proprietary formats are also opaque and useless to other +applications and the operating system, which often is a huge missed opportunity: +The .docx format, for example, commonly used for storing mostly textual data enriched with images and on occasion videos, +is in fact a type of archive that can contain many virtual files internally, such as the various media files contained +within. However this is completely unknown to the user and operating system, and so users are unable to access the +contents in this way. As a result, editing an image contained in a word document is far from a trivial task: first the +document has to be opened in a word processing application, then the image has to be exported from it and saved in its +own, temporary file. This file can then be edited and saved back to disk. Once updated, the image may be reimported +into the .docx document. If the word-processing application supports this, the old image may be replaced directly, +otherwise, the user may have to remove the old image, insert the new one, and carefully ensure that the positioning in +the document remains intact. + +2.4 disjointed filesystems +------------------------------- + +The filesystems and file models used on modern computing devices generally operate on the assumption that every +individual file stands for itself. Grouping of files in folders is allowed as a convenience for users, but most +applications only ever concern themselves with a single file at a time, independent of the context the file is stored +in. + +Data rarely really fits this concept of individual files very well, and even when it does, it is rarely exposed to +the user that way: The 'Contacts' app on a mobile phone, for example, does not store each contact's information in a +separate 'file' (as the word may suggest initially), but rather keeps all information in a single database file, +which is hidden away from the user. Consequently, access to the information contained in the database is only enabled +through the contacts application's graphical interface, and not through other applications that generically operate on +files. + +Another example illustrates how a more powerful file (organization) system could render such formats and applications +obsolete: Given the simple task of collecting and arranging a mixed collection of images, videos, and texts to +brainstorm, many might be tempted to open an application like *Microsoft Word* or *Adobe Photoshop* and create a new +document there. Both *Photoshop* files and *Word* documents are capable of containing texts and images, but when such +content is copied into them from external sources, such as other files on the same computer, or quotes and links from +the internet, these relationships are irrevocably lost. As illustrated above, additionally, it becomes a lot harder to +edit the content once it is aggregated. To choose an application for this task is a hard trade-off to make, because in +applications primarily designed for word processing, arranging content visually is hard to do, and image editing and +video embedding options are limited, while tools better suited to these tasks lack nuance when working with text. + +To avoid facing this dilemma, a more sensible system could leave the task of positioning and aggregating content of +different types to one software component, while multiple different software components could be responsible for editing +the individual pieces of content so that the most appropriate one can be chosen for each element. While creating the +technological interface between these components is certainly a challenge, the resulting system would greatly benefit +from the exponentially-growing capabilities resulting from the modular reuse of components across many contexts: A rich +text editor component could be used for example not just in a mixed media collection as proposed above, but also for +an email editor or the input fields in a browser. + +<div style="height: 2rem;"></div> + +To summarize, for various reasons, the metaphors and driving concepts of computing interfaces today prevent users from +deeply understanding the software they use and the data they own, from customizing and improving their experience and +interactions, and from properly owning, contextualizing and connecting their data. + +Interestingly, these deficits do not appear throughout the history of today's computing systems but are based in rather +recent developments in the field. In fact, the most influential systems in the past aspired to the polar opposites, as I +will show in the next section. + +<!-- +Chiusano blames these issues on the metaphor of the *machine*, and likens apps and applications to appliances. +According to him, what should really be provided are *tools*: +composable pieces of software that naturally lend themselves to, or outrightly call for, +integration into the users' other systems and customization, +rather than lure into the walled-gardens of corporate ecosystems using network-effects. +--> diff --git a/root/articles/mmmfs/print: text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/print: text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..615075a --- /dev/null +++ b/root/articles/mmmfs/print: text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,26 @@ +-- main content +-- doesn't have a name prefix (e.g. preview: fn -> mmm/dom) +-- uses the 'fn ->' conversion to execute the lua function on @get +-- resolves to a value of type mmm/dom +=> + html = require 'mmm.dom' + import article, h1, p, div from html + import moon from (require 'mmm.highlighting').languages + + article with _this = class: 'sidenote-container spacious', style: { 'max-width': '640px', 'line-height': '1.5' } + append = (a) -> table.insert _this, a + + append div { + h1 'Empowered End-User Computing', style: { 'margin-bottom': 0 } + p { + style: + 'margin-top': 0 + 'padding-bottom': '0.2em' + 'border-bottom': '1px solid black' + + "A Historical Investigation and Development of a File-System-Based Environment" + } + } + + for child in *@children + append (child\get 'print: mmm/dom') or (child\gett 'mmm/dom') diff --git a/root/articles/mmmfs/references/$order b/root/articles/mmmfs/references/$order new file mode 100644 index 0000000..d2a668b --- /dev/null +++ b/root/articles/mmmfs/references/$order @@ -0,0 +1,22 @@ +poc-or-gtfo +aspect-ratios +memex +appliances +super-powers +dijkstra +subtext +mime-types +alternatives-to-trees +xerox-star +unix +transclusion +adobe +acm-dl +hypercard +inkandswitch +linux-exec +wikipedia +market-share +osx-files +renaming +lock-in diff --git a/root/articles/mmmfs/references/acm-dl/text$bibtex b/root/articles/mmmfs/references/acm-dl/text$bibtex new file mode 100644 index 0000000..8fb36a2 --- /dev/null +++ b/root/articles/mmmfs/references/acm-dl/text$bibtex @@ -0,0 +1,5 @@ +@online{acm-dl, + title = {ACM Digital Library}, + url = {https://dl.acm.org}, + year = {n. d.}, +} diff --git a/root/articles/mmmfs/references/adobe/text$bibtex b/root/articles/mmmfs/references/adobe/text$bibtex new file mode 100644 index 0000000..55904aa --- /dev/null +++ b/root/articles/mmmfs/references/adobe/text$bibtex @@ -0,0 +1,8 @@ +@online{adobe, + title = {Adobe is cutting off users in Venezuela due to US sanctions}, + url = {https://www.theverge.com/2019/10/7/20904030/adobe-venezuela-photoshop-behance-us-sanctions}, + publisher = {The Verge}, + author = {Lee, Dami}, + year = {2019, October 7}, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/alternatives-to-trees/text$bibtex b/root/articles/mmmfs/references/alternatives-to-trees/text$bibtex new file mode 100644 index 0000000..19c134e --- /dev/null +++ b/root/articles/mmmfs/references/alternatives-to-trees/text$bibtex @@ -0,0 +1,7 @@ +@web{alternatives:to:trees, + title = {Alternatives to Trees}, + url = {https://www.oocities.org/tablizer/sets1.htm}, + author = {Jacobs, B.} + year = {2004}, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/appliances/text$bibtex b/root/articles/mmmfs/references/appliances/text$bibtex new file mode 100644 index 0000000..56fa8c8 --- /dev/null +++ b/root/articles/mmmfs/references/appliances/text$bibtex @@ -0,0 +1,7 @@ +@online{appliances, + title = {The future of software, the end of apps, and why UX designers should care about type theory}, + url = {http://pchiusano.github.io/2013-05-22/future-of-software.html}, + author = {Chiusano, Paul}, + year = {2013}, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/aspect-ratios/text$bibtex b/root/articles/mmmfs/references/aspect-ratios/text$bibtex new file mode 100644 index 0000000..37cea92 --- /dev/null +++ b/root/articles/mmmfs/references/aspect-ratios/text$bibtex @@ -0,0 +1,7 @@ +@web{aspect:ratios, + title = {Aspect-ratio independent UIs}, + url = {https://s-ol.nu/aspect-ratios}, + author = {Bekic, Sol} + year = {2019}, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/dijkstra/text$bibtex b/root/articles/mmmfs/references/dijkstra/text$bibtex new file mode 100644 index 0000000..c38a470 --- /dev/null +++ b/root/articles/mmmfs/references/dijkstra/text$bibtex @@ -0,0 +1,17 @@ +@article{10.1007/BF01386390, + author = {Dijkstra, Edsger W.}, + title = {A Note on Two Problems in Connexion with Graphs}, + year = {1959}, + issue_date = {December 1959}, + publisher = {Springer-Verlag}, + address = {Berlin, Heidelberg}, + volume = {1}, + number = {1}, + issn = {0029-599X}, + url = {https://doi.org/10.1007/BF01386390}, + doi = {10.1007/BF01386390}, + journal = {Numer. Math.}, + month = dec, + pages = {269–271}, + numpages = {3} +} diff --git a/root/articles/mmmfs/references/hypercard/text$bibtex b/root/articles/mmmfs/references/hypercard/text$bibtex new file mode 100644 index 0000000..b23cfcb --- /dev/null +++ b/root/articles/mmmfs/references/hypercard/text$bibtex @@ -0,0 +1,6 @@ +@online{hypercard, + title = {Computer Chronicles, Episode 501}, + url = {https://archive.org/details/CC501_hypercard}, + visited = {2019-12-18}, + year = {1987}, +} diff --git a/root/articles/mmmfs/references/inkandswitch/markdown: text$moonscript -> fn -> text$markdown.md b/root/articles/mmmfs/references/inkandswitch/markdown: text$moonscript -> fn -> text$markdown.md new file mode 100644 index 0000000..9439841 --- /dev/null +++ b/root/articles/mmmfs/references/inkandswitch/markdown: text$moonscript -> fn -> text$markdown.md @@ -0,0 +1 @@ +=> "```\n" .. (@gett 'text/bibtex') .. "\n```" diff --git a/root/articles/mmmfs/references/inkandswitch/text$bibtex b/root/articles/mmmfs/references/inkandswitch/text$bibtex new file mode 100644 index 0000000..8b5f298 --- /dev/null +++ b/root/articles/mmmfs/references/inkandswitch/text$bibtex @@ -0,0 +1,7 @@ +@online{inkandswitch, + title = {End-user Programming}, + url = {https://inkandswitch.com/end-user-programming.html}, + publisher = {Ink & Switch}, + year = {2019}, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/linux-exec/text$bibtex b/root/articles/mmmfs/references/linux-exec/text$bibtex new file mode 100644 index 0000000..e0e415f --- /dev/null +++ b/root/articles/mmmfs/references/linux-exec/text$bibtex @@ -0,0 +1,8 @@ +@online{linux:exec, + title = {How does Linux execute a file?}, + url = {https://stackoverflow.com/a/23295724/1598293}, + publisher = {stackoverflow.com}, + note = {answered by osgx}, + visited = {2019-12-18}, + year = 2014, +} diff --git a/root/articles/mmmfs/references/lock-in/text$bibtex b/root/articles/mmmfs/references/lock-in/text$bibtex new file mode 100644 index 0000000..28d780c --- /dev/null +++ b/root/articles/mmmfs/references/lock-in/text$bibtex @@ -0,0 +1,7 @@ +@online{lock:in, + title = {The Cloud is the Ultimate Vendor Lock-in}, + url = {https://www.digital-manifesto.org/the-cloud-is-the-ultimate-vendor-lock-in/}, + author = {Zielemans, François}, + year = {2017}, + visited = {2019-11-18}, +} diff --git a/root/articles/mmmfs/references/market-share/text$bibtex b/root/articles/mmmfs/references/market-share/text$bibtex new file mode 100644 index 0000000..430af2f --- /dev/null +++ b/root/articles/mmmfs/references/market-share/text$bibtex @@ -0,0 +1,7 @@ +@online{market:share, + title = {Operating System Market Share - Desktop and Mobile}, + year = {2019}, + url = {https://s-ol.nu/ba/ref/nms}, + oldURL = {https://netmarketshare.com/operating-system-market-share.aspx?options=%7B%22filter%22%3A%7B%22%24and%22%3A%5B%7B%22deviceType%22%3A%7B%22%24in%22%3A%5B%22Desktop%2Flaptop%22%2C%22Mobile%22%5D%7D%7D%5D%7D%2C%22dateLabel%22%3A%22Trend%22%2C%22attributes%22%3A%22share%22%2C%22group%22%3A%22platform%22%2C%22sort%22%3A%7B%22share%22%3A-1%7D%2C%22id%22%3A%22platformsDesktop%22%2C%22dateInterval%22%3A%22Monthly%22%2C%22dateStart%22%3A%222018-12%22%2C%22dateEnd%22%3A%222019-11%22%2C%22hiddenSeries%22%3A%7B%7D%2C%22tableOrder%22%3A%5B%5B2%2C%22desc%22%5D%5D%2C%22segments%22%3A%22-1000%22%7D}, + publisher = {NetMarketShare}, +} diff --git a/root/articles/mmmfs/references/memex/text$bibtex b/root/articles/mmmfs/references/memex/text$bibtex new file mode 100644 index 0000000..313eec7 --- /dev/null +++ b/root/articles/mmmfs/references/memex/text$bibtex @@ -0,0 +1,8 @@ +@online{memex, + author = {Bush, Vannevar}, + title = {As we may think}, + journal = {Atlantic Monthly}, + year = {1945}, + visited = {2019-12-18}, + url = {https://www.theatlantic.com/magazine/archive/1945/07/as-we-may-think/303881/} +} diff --git a/root/articles/mmmfs/references/mime-types/text$bibtex b/root/articles/mmmfs/references/mime-types/text$bibtex new file mode 100644 index 0000000..c49b553 --- /dev/null +++ b/root/articles/mmmfs/references/mime-types/text$bibtex @@ -0,0 +1,14 @@ +@article{rfc6838, + series = {Request for Comments}, + number = 6838, + howpublished = {RFC 6838}, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC6838}, + url = {https://tools.ietf.org/html/rfc6838}, + author = {Freed, Ned and Klensin, John C. and Hansen, Tony}, + title = {Media Type Specifications and Registration Procedures}, + pagetotal = 32, + year = 2013, + month = jan, + abstract = {This document defines procedures for the specification and registration of media types for use in HTTP, MIME, and other Internet protocols. This memo documents an Internet Best Current Practice.}, +} diff --git a/root/articles/mmmfs/references/osx-files/text$bibtex b/root/articles/mmmfs/references/osx-files/text$bibtex new file mode 100644 index 0000000..7c70a87 --- /dev/null +++ b/root/articles/mmmfs/references/osx-files/text$bibtex @@ -0,0 +1,7 @@ +@online{osx:files, + title = {Where is "Show Package Contents"}, + url = {https://discussions.apple.com/thread/6740790}, + publisher = {Apple Communities}, + visited = {2019-12-27}, + year = 2014, +} diff --git a/root/articles/mmmfs/references/poc-or-gtfo/text$bibtex b/root/articles/mmmfs/references/poc-or-gtfo/text$bibtex new file mode 100644 index 0000000..7cac092 --- /dev/null +++ b/root/articles/mmmfs/references/poc-or-gtfo/text$bibtex @@ -0,0 +1,8 @@ +@article{PoC:or:GTFO, + author = {Albertini, Ange}, + title = {Abusing file formats; or, Corkami, the Novella}, + year = {2015}, + journal = {PoC||GTFO}, + volume = {7}, + pages = {18-41}, +} diff --git a/root/articles/mmmfs/references/renaming/text$bibtex b/root/articles/mmmfs/references/renaming/text$bibtex new file mode 100644 index 0000000..660bc2c --- /dev/null +++ b/root/articles/mmmfs/references/renaming/text$bibtex @@ -0,0 +1,7 @@ +@online{renaming, + title = {Why is it possible to convert a file just by renaming it?}, + url = {https://askubuntu.com/q/166602}, + publisher = {askubuntu.com}, + year = 2012, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/subtext/cite$doi b/root/articles/mmmfs/references/subtext/cite$doi new file mode 100644 index 0000000..2ac65b5 --- /dev/null +++ b/root/articles/mmmfs/references/subtext/cite$doi @@ -0,0 +1 @@ +10.1145/1103845.1094851 diff --git a/root/articles/mmmfs/references/subtext/text$bibtex b/root/articles/mmmfs/references/subtext/text$bibtex new file mode 100644 index 0000000..7e9eb9d --- /dev/null +++ b/root/articles/mmmfs/references/subtext/text$bibtex @@ -0,0 +1,18 @@ +@article{10.1145/1103845.1094851, + author = {Edwards, Jonathan}, + title = {Subtext: Uncovering the Simplicity of Programming}, + year = {2005}, + issue_date = {October 2005}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {40}, + number = {10}, + issn = {0362-1340}, + url = {https://doi.org/10.1145/1103845.1094851}, + doi = {10.1145/1103845.1094851}, + journal = {SIGPLAN Not.}, + month = oct, + pages = {505–518}, + numpages = {14}, + keywords = {copying, non-textual programming, prototypes, visual programming}, +} diff --git a/root/articles/mmmfs/references/super-powers/text$bibtex b/root/articles/mmmfs/references/super-powers/text$bibtex new file mode 100644 index 0000000..5eabda8 --- /dev/null +++ b/root/articles/mmmfs/references/super-powers/text$bibtex @@ -0,0 +1,7 @@ +@online{super:powers, + title = {Super-powers, but not yours}, + url = {http://object.network/manifesto-negative.html}, + author = {Cragg, Duncan}, + year = {2016}, + visited = {2019-12-18}, +} diff --git a/root/articles/mmmfs/references/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/references/text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..7b96c10 --- /dev/null +++ b/root/articles/mmmfs/references/text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,13 @@ +=> + html = require 'mmm.dom' + import div, h1, ol, li from html + + refs = for ref in *@children + li ref\gett 'mmm/dom' + div { + class: 'print-ownpage' + + h1 "references", id: 'references' + ol with refs + refs.style = 'line-height': 'normal' + } diff --git a/root/articles/mmmfs/references/transclusion/text$bibtex b/root/articles/mmmfs/references/transclusion/text$bibtex new file mode 100644 index 0000000..e323662 --- /dev/null +++ b/root/articles/mmmfs/references/transclusion/text$bibtex @@ -0,0 +1,10 @@ +@article{article, + author = {Kolbitsch, Josef and Maurer, Hermann}, + year = {2006}, + month = {06}, + pages = {161-173}, + title = {Transclusions in an HTML-Based Environment}, + volume = {14}, + journal = {CIT}, + doi = {10.2498/cit.2006.02.07}, +} diff --git a/root/articles/mmmfs/references/unix/text$bibtex b/root/articles/mmmfs/references/unix/text$bibtex new file mode 100644 index 0000000..70b139d --- /dev/null +++ b/root/articles/mmmfs/references/unix/text$bibtex @@ -0,0 +1,7 @@ +@book{10.5555/577766, + author = {Kernighan, Brian W. and Pike, Rob}, + title = {The UNIX Programming Environment}, + year = {1983}, + isbn = {0139376992}, + publisher = {Prentice Hall Professional Technical Reference} +} diff --git a/root/articles/mmmfs/references/wikipedia/text$bibtex b/root/articles/mmmfs/references/wikipedia/text$bibtex new file mode 100644 index 0000000..d88d58c --- /dev/null +++ b/root/articles/mmmfs/references/wikipedia/text$bibtex @@ -0,0 +1,7 @@ +@online{wikipedia, + title = {Hyperlink - Wikis}, + url = {https://en.wikipedia.org/wiki/Hyperlink#Wikis}, + publisher = {wikipedia.org}, + visited = {2019-12-18}, + year = {n. d.}, +} diff --git a/root/articles/mmmfs/references/xerox-star/cite$doi b/root/articles/mmmfs/references/xerox-star/cite$doi new file mode 100644 index 0000000..b849172 --- /dev/null +++ b/root/articles/mmmfs/references/xerox-star/cite$doi @@ -0,0 +1 @@ +10.1109/2.35211 diff --git a/root/articles/mmmfs/references/xerox-star/text$bibtex b/root/articles/mmmfs/references/xerox-star/text$bibtex new file mode 100644 index 0000000..870eed4 --- /dev/null +++ b/root/articles/mmmfs/references/xerox-star/text$bibtex @@ -0,0 +1,18 @@ +@article{10.1109/2.35211, + oldauthor = {Johnson, Jeff and Roberts, Teresa L. and Verplank, William and Smith, David C. and Irby, Charles H. and Beard, Marian and Mackey, Kevin}, + author = {Johnson, Jeff et al.}, + title = {The Xerox Star: A Retrospective}, + year = {1989}, + issue_date = {September 1989}, + publisher = {IEEE Computer Society Press}, + address = {Washington, DC, USA}, + volume = {22}, + number = {9}, + issn = {0018-9162}, + url = {https://doi.org/10.1109/2.35211}, + doi = {10.1109/2.35211}, + journal = {Computer}, + month = sep, + pages = {11–26, 28–29}, + numpages = {1}, +} diff --git a/root/articles/mmmfs/statement-of-originality/text$html+frag.html b/root/articles/mmmfs/statement-of-originality/text$html+frag.html new file mode 100644 index 0000000..d6dcbc0 --- /dev/null +++ b/root/articles/mmmfs/statement-of-originality/text$html+frag.html @@ -0,0 +1,13 @@ +<div class="print-only print-ownpage" style="margin: 4cm 0 0;"> +<h1 id="statement">statement of originality</h1> +<p style="margin-top: 5cm"> +This is to certify that the content of this project, documentation and thesis is my own work. It +has not been submitted for any other degree or other purposes. I certify that the intellectual +content of my submission is the product of my own work and that all the assistance received in +preparing it as well as all sources used have been properly acknowledged. +</p> + +<div style="border-top: 1px solid #000; width: 7cm; margin-top: 3cm;"> +Sol Bekic +</div> +</div> diff --git a/root/articles/mmmfs/table-of-contents/text$html+frag.html b/root/articles/mmmfs/table-of-contents/text$html+frag.html new file mode 100644 index 0000000..2b94109 --- /dev/null +++ b/root/articles/mmmfs/table-of-contents/text$html+frag.html @@ -0,0 +1,91 @@ +<!-- +{ + const fmt = x => `<a href="#${x.id}">${x.innerText}</a>`; + + const parse = e => ({ + num: +e.tagName.substr(1), + fmt: fmt(e), + }); + + const render = (list) => { + let str = ''; + let num = 0; + for (e of list) { + while (e.num > num) { + str += '<ol style="list-style: none; padding-left: 2rem;">' + num += 1; + } + + while (e.num < num) { + str += '</ol>'; + num -= 1; + } + + str += `<li>${e.fmt}</li>`; + } + return str; + }; + + render([...$0.querySelectorAll('h1, h2, h3, h4, h5').values()].map(parse)); +} +--> +<section class="print-ownpage"> + <h1 id="table-of-contents">table of contents</h1> + <ol style="list-style: none;"> + <li><a href="#abstract">abstract</a></li> + <li><a href="#table-of-contents">table of contents</a></li> + <li><a href="#1introduction">1 introduction</a></li> + <li><a href="#2drawbacks-of-current-systems">2 drawbacks of current systems</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#21application-centric-design">2.1 application-centric design</a></li> + <li><a href="#22cloud-computing">2.2 cloud computing</a></li> + <li><a href="#23inert-data-and-data-formats">2.3 inert data (and data formats)</a></li> + <li><a href="#24disjointed-filesystems">2.4 disjointed filesystems</a></li> + </ol> + <li><a href="#3historical-approaches">3 historical approaches</a></li> + <li><a href="#4evaluation-framework">4 evaluation framework</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#41qualities-of-successful-end-user-computing">4.1 qualities of successful end-user computing</a></li> + <li><a href="#42modularity">4.2 modularity</a></li> + <li><a href="#43content-transclusion">4.3 content transclusion</a></li> + <li><a href="#44end-user-programming">4.4 end-user programming</a></li> + </ol> + <li><a href="#5system-description">5 system description</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#51data-storage-model">5.1 data storage model</a></li> + <li><a href="#52type-system-and-coercion-engine">5.2 type system and coercion engine</a></li> + </ol> + <li><a href="#6example-use-cases">6 example use-cases</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#61publishing-and-blogging">6.1 publishing and blogging</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#611blogging">6.1.1 blogging</a></li> + <li><a href="#612scientific-publishing">6.1.2 scientific publishing</a></li> + </ol> + <li><a href="#62pinwall">6.2 pinwall</a></li> + <li><a href="#63slideshow">6.3 slideshow</a></li> + </ol> + <li><a href="#7evaluation">7 evaluation</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#71examples">7.1 examples</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#711publishing-and-blogging">7.1.1 publishing and blogging</a></li> + <li><a href="#712pinwall">7.1.2 pinwall</a></li> + <li><a href="#713slideshow">7.1.3 slideshow</a></li> + </ol> + <li><a href="#72general-concerns">7.2 general concerns</a></li> + <ol style="list-style: none; padding-left: 2rem;"> + <li><a href="#721global-set-of-converts">7.2.1 global set of converts</a></li> + <li><a href="#722code-outside-of-the-system">7.2.2 code outside of the system</a></li> + <li><a href="#723type-system">7.2.3 type system</a></li> + <li><a href="#724type-coercion">7.2.4 type-coercion</a></li> + <li><a href="#725in-system-editing">7.2.5 in-system editing</a></li> + <li><a href="#726end-user-adoption">7.2.6 end-user adoption</a></li> + </ol> + </ol> + <li><a href="#8conclusion">8 conclusion</a></li> + <li><a href="#references">references</a></li> + <li><a href="#ba-log">appendix: project log</a></li> + <li><a href="#statement">statement of originality</a></li> + </ol> +</section> diff --git a/root/articles/mmmfs/text$moonscript -> fn -> mmm$dom.moon b/root/articles/mmmfs/text$moonscript -> fn -> mmm$dom.moon index 7bb192d..6c5b1d3 100644 --- a/root/articles/mmmfs/text$moonscript -> fn -> mmm$dom.moon +++ b/root/articles/mmmfs/text$moonscript -> fn -> mmm$dom.moon @@ -4,260 +4,23 @@ -- resolves to a value of type mmm/dom => html = require 'mmm.dom' - import article, h1, h2, h3, p, div, a, sup, ol, li, span, code, pre, br from html + import article, h1, p, div from html import moon from (require 'mmm.highlighting').languages - article with _this = {} + article with _this = class: 'sidenote-container spacious', style: { 'max-width': '640px', 'line-height': '1.5' } append = (a) -> table.insert _this, a - footnote, getnotes = do - local * - notes = {} + append div { + h1 'Empowered End-User Computing', style: { 'margin-bottom': 0 } + p { + style: + 'margin-top': 0 + 'padding-bottom': '0.2em' + 'border-bottom': '1px solid black' - id = (i) -> "footnote-#{i}" - - footnote = (stuff) -> - i = #notes + 1 - notes[i] = stuff - sup a "[#{i}]", style: { 'text-decoration': 'none' }, href: '#' .. id i - - footnote, -> - args = for i, note in ipairs notes - li (span (tostring i), id: id i), ': ', note - notes = {} - table.insert args, style: { 'list-style': 'none', 'font-size': '0.8em' } - ol table.unpack args - - -- @TODO: s/filesystem/a way of organizing files/g - append h1 'mmmfs', style: { 'margin-bottom': 0 } - append p "a file and operating system to live in", style: { 'margin-top': 0, 'padding-bottom': '0.2em', 'border-bottom': '1px solid black' } - - append h2 "motivation" - append p "Today, computer users are losing more and more control over their data. Between web and cloud - applications holding customer data hostage for providing the services, unappealing and limited mobile file - browsing experiences and the non-interoperable, proprietary file formats holding on to their own data has - become infeasible for many users. mmmfs is an attempt at rethinking file-systems and the computer user - experience to give control back to and empower users." - - append p "mmmfs tries to provide a filesystem that is powerful enough to let you use it as your canvas for thinking, - and working at the computer. mmmfs is made for more than just storing information. Files in mmmfs can interact - and morph to create complex behaviours." - - append p "Let us take as an example the simple task of collecting and arranging a mixed collection of images, videos - and texts in order to brainstorm. To create an assemblage of pictures and text, many might be tempted to open an - Application like Microsoft Word or Adobe Photoshop and create a new document there. Both photoshop files and - word documents are capable of containing texts and images, but when the files are saved, direct access to the - contained data is lost. It is for example a non-trivial and unenjoyable task to edit an image file contained - in a word document in another application and have the changes apply to the document. In the same way, - text contained in a photoshop document cannot be edited in a text editor of your choice." - - append p "mmmfs tries to change all this. In mmmfs, files can contain other files and so the collage document - becomes a container for the collected images and texts just as a regular directory would. This way the individual - files remain accessible and can be modified whenever necessary, while the collage document can be edited to - change the order, sizes and spatial arrangement of it's content if this is wanted, for example." - - append p "The mmmfs file-type system also allows storing types of information that have become impractical to use - with current filesystems simply because noone has cared to make suitable applications for them. It is not common - practice, for example, to store direct links to online content on the disk for example. In mmmfs, a link to a - picture can be stored wherever an actual picture is expected for example, the system will take care of retrieving - the real picture as necessary." - - -- @TODO: motivation / outline problem + need - -- * applications don't let users *do* things (http://pchiusano.github.io/2013-05-22/future-of-software.html) - -- * applications are just (collections of) files - most users don't know this (anymore) - -- * users should know their system and how to move around in it - -- * filesystem trees are only *okay* for organizing information: - -- - users sooner or later choose something smarter because: - -- * filesystems work the same in every folder, even though the context can be very different - -- * appliances put their complex, structured data into opaque blocks - -- * the FS should be able to solve the structure issue - -- * the benefit is interoperability: edit the image of your report - -- * in image editor while the document editor automatically refreshes - -- * file formats dont mean much to users, they are meant for applications - let applications take care of converting them - -- * report.doc, report.pdf, report_orignal.pdf, report_old.doc, report2.doc.... - - append p do - fileder = footnote "fileder: file + folder. 'node', 'table' etc. are too general to be used all over." - - -- @TODO: mention: - -- can store anything - text, an image, a link to a website or video, - -- a program and anything else you can think of. - "in mmmfs, directories, files and applications are all kind of the same thing, or something like that. - Listen, I don't really know yet either. The idea is that there is only one type of 'thing' - - a fileder", fileder, ". A fileder can store multiple variants and metadata of its content, - such as a markdown text and a rendered HTML version of the same document. - It could also store a script that transforms the markdown version into HTML and is executed on demand, - automatically." - - append p "Fileders can also have other fileders as their children (just like directories do in a normal - filesystem). You can make a fileder view query these children and display them however you want. - A 'Pictures' fileder, for example, could contain a script within itself that renders all the picture files - you put into it as little previews and lets you click on them to view the full image." - - append p "This means the 'Pictures' fileder can also have an alternate slideshow mode, with fullscreen view and - everything (some of this is built, check out the gallery example below), or one that displays geotagged images - on a world map, if you really want that. Maybe you could build a music folder that contains links to youtube - videos, spotify tracks and just plain mp3 files, and the folder knows how to play them all.", br!, " - In this way fileders fulfil the purpose of 'Applications' too." - - -- @TODO: BUT doesn't have to be only for one type of file: - -- @TODO: rework - -- making a multi-media collage representing your thoughts and mental organization of a topic - append p "A fileder is also responsible for how it's children are sorted, filtered and interacted with. - For example you should be able to create a fileder that is essentially a 'word document' equivalent: it can - contain images, websites, links and of course text as children and let you reorder, layout and edit them - whenever you open the fileder." - - append p "Sounds cool, no? Here's some examples of things a fileder can be or embed:" - - -- render a preview block - preview = (child) -> - -- get 'title' as 'text/plain' (error if no value or conversion possible) - title = child\gett 'title', 'text/plain' - - -- get 'preview' as a DOM description (nil if no value or conversion possible) - content = child\get 'preview', 'mmm/dom' - - div { - h3 title, style: { margin: 0, cursor: 'pointer' }, onclick: -> BROWSER\navigate child.path - content or span '(no renderable content)', style: { color: 'red' }, - style: { - display: 'inline-block', - width: '300px', - height: '200px', - padding: '4px', - margin: '8px', - border: '4px solid #eeeeee', - overflow: 'hidden', - }, + "A Historical Investigation and Development of a File-System-Based Environment" } + } - append div for child in *@children - preview child - - append h2 "details" - -- @TODO s/parts: dimensions, aspects? - -- @TODO: first mention both facets & children; then go into detail - -- @TODO: main content - append do - name = html.i 'name' - type = html.i 'type' - - p "Fileders are made up of two main parts. The first is the list of ", (html.i 'facets'), ", - which are values identified by a ", name, " and ", type, ". These values are queried using strings like ", - (code 'title: text/plain'), " or ", (code 'mmm/dom'), ", which describe both the ", name, - " of a facet (", (moon '"title"'), " and ", (moon '""'), ", the unnamed/main facet) and the ", type, - " of a facet. Facet types can be something resembling a MIME-type or a more complex structure - (see ", (html.i "type chains"), " below). A fileder can have multiple facets of different types - set that share a ", name, ". In this case the overlapping facets are considered equivalent and the one - with the most appropriate ", type, " is selected, depending on the query. - The unnamed facet is considered a fileder's 'main content', i.e. what you are interested in when viewing it." - - append p "The second part of a fileder is the list of it's children, which are fileders itself. - The children are stored in an ordered list and currently identified by their ", (code 'name: alpha'), - " facet for UI and navigation purposes only (not sure if this is a good idea tbh)." - - append do - mmmdom = code ('mmm/dom'), footnote span (code 'mmm/dom'), " is a polymorphic content type; - on the server it is just an HTML string (like ", (code 'text/html'), "), - but on the client it is a JS DOM Element instance." - - p "What you are viewing right now is the main facet of the root fileder. - The facet is queried as ", mmmdom, ", a website fragment (DOM node). This website fragment - is then added to the page in the main content area, where you are most likely reading it right now." - - p "Anyway, this node is set up as a very generic sort of index thing and just lists its children-fileders' - alongside this text part you are reading.", br!, "For each child it displays the ", (code 'title: text/plain'), - " and shows the ", (code 'preview: mmm/dom'), " facet (if set)." - - append h3 "converts" - append p "So far I have always listed facets as they are being queried, but a main feature of mmmfs is - type conversion. This means that you generally ask for content in whichever format suits your application, - and rely on the type resolution mechanism to make that happen." - - append pre moon [[ --- render a preview block -preview = (title, content) -> div { - h3 title, style: { ... }, - content or span '(no renderable content)', style: { ... }, - style: { ... } -} - -append div for child in *@children --- get 'title' as 'text/plain' (error if no value or conversion possible) -title = child\gett 'title', 'text/plain' - --- get 'preview' as a DOM description (nil if no value or conversion possible) -content = child\get 'preview', 'mmm/dom' - -preview title, content - ]] - - append p "Here the code that renders these previews. You can see it ", (html.i "asks"), " for the - facets ", (code 'title: text/plain'), ' and ', (code 'preview: mmm/dom'), "), but the values don't actually have to - be ", (html.i "defined"), " as these types. - For example, the markdown child below only provides ", (code 'preview'), " as ", (code 'text/markdown'), ":" - - append pre moon [[ -Fileder { - 'title: text/plain': "I'm not even five lines of markdown but i render myself!", - 'preview: text/markdown': "See I have like - - - a list of things - - (two things) - - and some bold **text** and `code tags` with me.", -} - ]] - - append p "Then, globally, there are some conversion paths specified; such as one that maps from ", - (code 'text/markdown'), " to ", (code 'mmm/dom'), ":" - - append pre moon [[ -{ - inp: 'text/markdown', - out: 'mmm/dom', - transform: (md) -> - -- polymorphic client/serverside implementation here, - -- uses lua-discount on the server, marked.js on the client -} - ]] - - append h3 "type chains" - append p "In addition, a facet type can be encoded using multiple types in a ", (code 'type chain'), ". - For example the root node you are viewing currently is actually defined as ", (code 'fn -> mmm/dom'), ", - meaning it's value is a pre moon function returing a regular ", (code 'mmm/dom'), " value." - - append p "Both value chains and 'sideways' converts are resolved using the same mechanism, - so this page is being rendered just using ", (moon "append root\\get 'mmm/dom'"), " as well. - The convert that resolves the moon type is defined as follows:" - - append pre moon [[ -{ - inp: 'fn -> (.+)', - out: '%1', - transform: (val, fileder) -> val fileder -} - ]] - - append p "The example with the image is curious as well. In mmmfs, you might want to save a link to an image, - without ever saving the actual image on your hard drive (or wherever the data may ever be stored - it is - quite transient currently). The image Fileder below has it's main (unnamed) value tagged as ", - (code 'URL -> image/png'), " - a png image, encoded as an URL. When accessed as ", (code 'image/png'), " - the URL should be resolved, and the binary data provided in it's place (yeah right - I haven't build that yet)." - - append p "However, if a script is aware of URLs and knows a better way to handle them, then it can ask for and - use the URL directly instead. - This is what the image demo does in order to pass the URL to an ", (code 'img'), " tag's ", (code 'src'), " attribute:" - - append pre moon [[ -Fileder { - 'title: text/plain': "Hey I'm like a link to picture or smth", - 'URL -> image/png': 'https://picsum.photos/200?random', - 'preview: fn -> mmm/dom': => - import img from require 'mmm.dom' - img src: @gett 'URL -> image/png' -- look for main content with 'URL to png' type -} - ]] - - append getnotes! + for child in *@children + append child\gett 'mmm/dom' diff --git a/root/articles/mmmfs/title/text$html+frag.html b/root/articles/mmmfs/title/text$html+frag.html new file mode 100644 index 0000000..063b52a --- /dev/null +++ b/root/articles/mmmfs/title/text$html+frag.html @@ -0,0 +1,21 @@ +<div class="print-only print-ownpage" style="font-size: 1.5rem; width: calc(100% + var(--sidenote-width))"> + <div style="font-size: 2rem; margin-top: 4cm"> + <h1>Empowered End-User Computing:</h1> + <span>A Historical Investigation and Development of a File-System-Based Environment</span> + </div> + <div style="width: 14cm; margin: 7cm auto 0"> + <p>by</p> + <p> + Sol Bekic<br /> + Student ID 11114279<br /> + sol.bekic+ba@s-ol.nu + </p> + <p> + written in the Winter Term 2019/20<br /> + for BA Digital Games<br /> + at Cologne Game Lab / TH Köln + </p> + <p>supervised by Prof. Dr. Gundolf S. Freyermuth</p> + <p>submitted on 2020-01-07</p> + </div> +</div> diff --git a/root/articles/realities/text$moonscript -> mmm$dom.moon b/root/articles/realities/text$moonscript -> mmm$component.moon index 7689dbb..a7dc365 100644 --- a/root/articles/realities/text$moonscript -> mmm$dom.moon +++ b/root/articles/realities/text$moonscript -> mmm$component.moon @@ -24,7 +24,7 @@ if MODE == 'SERVER' render: => rplc = with div id: @id, :style \append '(diagram goes here)' - -- \append "<script type=\"application/lua\"> + -- \append "<script type=\"text/lua\"> -- local rplc = js.global.document:getElementById('#{@id}'); -- local fn = #{compile @func} -- diag = Diagram(fn) diff --git a/root/articles/xy-workshop/$order b/root/articles/xy-workshop/$order new file mode 100644 index 0000000..4600622 --- /dev/null +++ b/root/articles/xy-workshop/$order @@ -0,0 +1,10 @@ +01 +02 +03 +05 +04 +07 +01b +06 +08 +01c diff --git a/root/articles/xy-workshop/01/text$html+frag.html b/root/articles/xy-workshop/01/text$html+frag.html new file mode 100644 index 0000000..2441f62 --- /dev/null +++ b/root/articles/xy-workshop/01/text$html+frag.html @@ -0,0 +1,7 @@ +<div style="margin-top: 4em"> + <h2>Oscilloscope Music and Games with Pure Data</h2> + <br /> + <br /> + <br /> + <p>sol bekic, 2019</p> +</div> diff --git a/root/articles/xy-workshop/01b/text$markdown.md b/root/articles/xy-workshop/01b/text$markdown.md new file mode 100644 index 0000000..22c1454 --- /dev/null +++ b/root/articles/xy-workshop/01b/text$markdown.md @@ -0,0 +1,12 @@ +who am i? +========= + +my name is sol, +i like to program, build hardware and play with technology. + +- github: @s-ol +- mastodon: @s-ol\@merveilles.town +- twitter: @S0lll0s +- links to all of those, email, and more info: + https://s-ol.nu + diff --git a/root/articles/xy-workshop/01c/$order b/root/articles/xy-workshop/01c/$order new file mode 100644 index 0000000..2b68b52 --- /dev/null +++ b/root/articles/xy-workshop/01c/$order @@ -0,0 +1 @@ +video diff --git a/root/articles/xy-workshop/01c/text$markdown.md b/root/articles/xy-workshop/01c/text$markdown.md new file mode 100644 index 0000000..ba5718c --- /dev/null +++ b/root/articles/xy-workshop/01c/text$markdown.md @@ -0,0 +1,5 @@ +what am i going to talk about? +============================== +Plonat Atek - E317 - B14 / Pavillon 6 + +<iframe width="1220" height="630" frameborder="0" src="//www.youtube.com/embed/SIQAk9_nc-s"></iframe> diff --git a/root/articles/xy-workshop/01c/video/URL -> youtube$video b/root/articles/xy-workshop/01c/video/URL -> youtube$video new file mode 100644 index 0000000..bf07555 --- /dev/null +++ b/root/articles/xy-workshop/01c/video/URL -> youtube$video @@ -0,0 +1 @@ +https://www.youtube.com/watch?v=SIQAk9_nc-s diff --git a/root/articles/xy-workshop/02/text$markdown.md b/root/articles/xy-workshop/02/text$markdown.md new file mode 100644 index 0000000..3496b23 --- /dev/null +++ b/root/articles/xy-workshop/02/text$markdown.md @@ -0,0 +1,12 @@ +what am i going to talk about? +============================== + +<br /> + +- sound + scopes + - what is sound? + - what is an oscilloscope? +- pd + the audiovisual + - osc~ + output~ + - numbers boxes + sliders + - lissajous figures + sync diff --git a/root/articles/xy-workshop/03/text$markdown.md b/root/articles/xy-workshop/03/text$markdown.md new file mode 100644 index 0000000..c90491e --- /dev/null +++ b/root/articles/xy-workshop/03/text$markdown.md @@ -0,0 +1,12 @@ +what is sound? +============== +<br /> + +- *vibrations* in the air +- movement of your ear drum +- movement of a speaker membrane +- numbers in a file on your computer + +what do they all have in common? +- something is *changing over time* + - a wave! diff --git a/root/articles/xy-workshop/04/text$markdown.md b/root/articles/xy-workshop/04/text$markdown.md new file mode 100644 index 0000000..e07fbca --- /dev/null +++ b/root/articles/xy-workshop/04/text$markdown.md @@ -0,0 +1,9 @@ +what is sound? +============== + +waves are *something* changing over time: + +- in the air: pressure (in one spot) +- ear drum and speakers: distance from normal position +- audio cable: voltage over time +- sound file: number over time diff --git a/root/articles/xy-workshop/05/text$markdown.md b/root/articles/xy-workshop/05/text$markdown.md new file mode 100644 index 0000000..256c654 --- /dev/null +++ b/root/articles/xy-workshop/05/text$markdown.md @@ -0,0 +1,12 @@ +what is sound? +============== + +attributes of waves: + +| waves <div style="display: inline-block; width: 50px;"></div> | sounds <div style="display: inline-block; width: 10px;"></div> | | +|-------------|--------------------|----------------------------------| +| `amplitude` | `volume` | how far does the wave fluctuate? | +| `frequency` | `pitch` | how often does the wave repeat? | +| `shape` | `timbre` | (literally just the shape) | + +...let's look at + hear some examples! diff --git a/root/articles/xy-workshop/06/text$markdown.md b/root/articles/xy-workshop/06/text$markdown.md new file mode 100644 index 0000000..fa5b139 --- /dev/null +++ b/root/articles/xy-workshop/06/text$markdown.md @@ -0,0 +1,6 @@ +on computers, sound is stored as a list of `samples`: + +- `sample rate`: how many samples per second are recorded +- `sample size` or `bit depth`: how accurate is each sample + + diff --git a/root/articles/xy-workshop/07/text$markdown.md b/root/articles/xy-workshop/07/text$markdown.md new file mode 100644 index 0000000..518b9fb --- /dev/null +++ b/root/articles/xy-workshop/07/text$markdown.md @@ -0,0 +1,6 @@ +what is an oscilloscope? +======================== + +- machine for measuring and visualizing electronic waves (voltage) + + diff --git a/root/articles/xy-workshop/08/$order b/root/articles/xy-workshop/08/$order new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/root/articles/xy-workshop/08/$order @@ -0,0 +1 @@ +image diff --git a/root/articles/xy-workshop/08/image/image$png.png b/root/articles/xy-workshop/08/image/image$png.png Binary files differnew file mode 100644 index 0000000..ff82a9d --- /dev/null +++ b/root/articles/xy-workshop/08/image/image$png.png diff --git a/root/articles/xy-workshop/08/text$markdown.md b/root/articles/xy-workshop/08/text$markdown.md new file mode 100644 index 0000000..92ab316 --- /dev/null +++ b/root/articles/xy-workshop/08/text$markdown.md @@ -0,0 +1,4 @@ +what is an oscilloscope? +======================== + + diff --git a/root/articles/xy-workshop/description: text$plain b/root/articles/xy-workshop/description: text$plain new file mode 100644 index 0000000..c3fefe0 --- /dev/null +++ b/root/articles/xy-workshop/description: text$plain @@ -0,0 +1,2 @@ +workshop: oscilloscope music and games with pure data + diff --git a/root/articles/xy-workshop/text$moonscript -> fn -> mmm$dom.moon b/root/articles/xy-workshop/text$moonscript -> fn -> mmm$dom.moon new file mode 100644 index 0000000..701a14c --- /dev/null +++ b/root/articles/xy-workshop/text$moonscript -> fn -> mmm$dom.moon @@ -0,0 +1,70 @@ +import ReactiveVar, tohtml, fromhtml, text, elements from require 'mmm.component' +import article, button, div, span from elements + +=> + index = ReactiveVar 1 + slide = index\map (index) -> @children[index] + + local view + view = div { + style: + position: 'relative' + 'padding-top': '56.25%' + + div { + style: + position: 'absolute' + display: 'flex' + 'flex-direction': 'column' + top: 0 + left: 0 + right: 0 + bottom: 0 + padding: '1em' + background: '#eeeeee' + 'box-sizing': 'border-box' + + slide\map => @get 'mmm/dom' + } + } + + local left, right, viewNode + if MODE == 'CLIENT' + left = (_, e) -> + e\preventDefault! + index\transform (a) -> math.max 1, a - 1 + + right = (_, e) -> + e\preventDefault! + index\transform (a) -> math.min #@children, a + 1 + + viewNode = tohtml view + viewNode.tabIndex = 1 + viewNode\addEventListener 'keydown', (_, e) -> + switch e.key + when 'r' + e\preventDefault! + size = viewNode.offsetHeight / 15 + viewNode.style.fontSize = "#{size}px" + + when 'ArrowLeft' + left _, e + when 'ArrowRight' + right _, e + + tohtml with article! + \append div { + style: + display: 'flex' + + button '<', onclick: left + ' ' + span index\map (t) -> text t + ' ' + button '>', onclick: right + div style: flex: '1' + button 'fullscreen', onclick: (_, e) -> + e\preventDefault! + viewNode\requestFullscreen! + } + \append view |
