1. 3

    The recent story on the front page about cd reminded me of this one.

    1. 6

      I think BeOS was probably the only system to get this right. The problem with UNIX is that the APIs pretend that a file is a thing with a name and higher-level abstractions reinforce this. The term ‘directory’ is far more accurate than ‘folder’ on these systems: it’s a mapping from names to identities, not a containment hierarchy. You see this in exciting ways in modern *NIX systems. For example, with Linux you can set up inotify to tell you if any file in a directory is modified, then you can modify a file in that directory via a different hard link and not receive a notification.

      In BeOS, a folder was just the result of a saved search. The user abstraction was that you had a sea of files with metadata and you could construct views on this. For example, you could order your music in directories of {artist}/{album} or {genre}/{decade}, of anything else. This made it easy to track in the filesystem all of the possible ways in which a user could find a file.

      1. 1

        That’s really interesting actually.

        I wonder how feasible it’d be to build a utility which mimics this: i.e. perform some search using find or rg, and for each file automatically create links in $HOME/.views/$VIEW_NAME.

        In every day usage it’d work a little something like:

        mkview my_scripts $HOME/git/custom_scripts/**/*.sh
        cv my_scripts
        ls # shows all .sh files returned by the pattern passed into mkview
        

        I guess there isn’t so much you can do re: automatically keeping views up to date. I still wonder if a utility similar to this exists, I’d definitely use it.

        1. 3

          The author of BFS went to work at Apple and the metadata stream that the XNU kernel emits is designed for this. It provides a fire-hose stream of events to userspace telling it what directories have had contents modified so that they can then go and inspect file modification times and re-parse things. Spotlight uses this and you can create saved searches with it. The event thing is designed so that userspace can’t block the kernel: it’s a ring buffer and if you don’t consume it fast enough then you miss events, but they have an event counter and so you can tell that you’ve missed them. You can then do a background scan and catch up by looking for every file with a modification time after you were behind. If there are a load of file updates, Spotlight will get behind for a bit but will eventually catch up when the system is more idle.

          I don’t know of any open source *NIX system with an equivalent system (inotify on Linux is closest, but not quite the right shape). We’ve discussed using the hooks in FreeBSD that were added for the audit system to build such a thing, but never got around to writing it.

          1. 2

            For archival purposes, git-annex can be used as a symlink farm, so that the different directories in a single git-annex repository constitute many multiple views onto a single data store. It is not at all as ergonomic as the BeOS demos that I’ve seen, though.

      1. 1

        I think the solution in Elixir is pretty clean and readable. Being able to pattern match on binaries is really neat:

        defmodule Solution do
          @input "aaaabbbcca"
        
          def run(input \\ @input, acc \\ [])
        
          def run("", acc) do
            Enum.reverse(acc)
          end
        
          def run(<<char::bytes-size(1)>> <> remainder, [{char, n} | rest] = _acc) do
            run(remainder, [{char, n + 1} | rest])
          end
        
          def run(<<char::bytes-size(1)>> <> remainder, acc) do
            run(remainder, [{char, 1} | acc])
          end
        end
        
        iex(1)> Solution.run
        [{"a", 4}, {"b", 3}, {"c", 2}, {"a", 1}]
        

        I literally just threw this together, theres probably a much better way to do it

        1. 6

          BTW I’ve added Ruby-like blocks to Oil, which I think can be used to replace YAML in many circumstances. Shell is a natural place to put configuration because shell starts processes.

          I didn’t document it fully but there’s a snippet here:

          https://www.oilshell.org/release/0.8.1/doc/oil-proc-func-block.html#configuration-files

          It looks a lot like HCL. Just like you have a block like

          cd / {
            echo $PWD
            ls
          }
          

          in Oil, you can also have

          server foo {
            port = 80
            root = '/'
            section bar {
              ...
            }
          }
          

          It still needs a user-facing API and I’m looking for help/feedback on that!

          1. 2

            This looks like Nix’s attribute set syntax as well which is super nice to work with! Nice