The colon I'm a little on the fence about myself. It's a throwback to an earlier iteration of the syntax and it does add a little "code smell" to the interpreter and code behind the command prompt. In fact I did nearly remove it from murex just last week. However it is also an optional token so you're free to ignore it if you'd prefer.
The JSON magic is just Go's standard library unmarshalling JSON into a slices and maps and then remarshalling it back to JSON at the end. This design means I can swap out a JSON interface with a YAML, TOML or most other serialisation formats at runtime. For example you can have JSON coming in then output it as YAML (or visa versa). Tabulated data such as CSV is also supported but I had to be a little more creative in how are interchanged with formats like JSON since they represent different ideas of structured data -- sadly converting between CSV and other formats is still rather buggy but I'd definitely on my road map to fix.
In terms of how a file is recognised as JSON (or any other format), there is two methods: you use the `open` builtin which is a bit like `cat` but works with HTTP URLs as well as file paths. If it's a HTTP address it uses the Content-Type header to get the MIME (just like your desktop browser would do) and passes that type information down the pipeline. If it's a local path then it checks the extension. You can see the supported extensions and MIME types by typing:
config get shell mime-types | pretty
config get shell extensions | pretty
The issue is when using a classic UNIX tool like `cat` which wouldn't know a JSON from a CSV. So to support them you can also cast if you want to. for example the following two examples do the same thing: open file.json | ...do something
cat file.json | cast json | ...do something
I completely agree there's a lot of quirkiness to the shell. Some stuff I might even do differently if I were to start again from scratch and definitely some POC code in there I really need to rewrite. This shell was born out of a desire to solve some personal annoyances with Bash and I think it's fair to say I overindulged myself in places. But I figured if I design it for myself then at least I'm guaranteed one person will use it :) Of course if anyone else likes the project and finds themselves wanting to use it then I will absolutely take their feedback on board too.edit: also thanks for pointing out the areas where the documentation was unclear or lacking entirely. Documenting this thing has proven to be more time consuming (and less enjoyable) than writing the code! But I'll work on that.
That's the big question mark to me, how is the type information passed along. If I do
open foo.json | bar
then how will bar know (or will it?) that its input is json? Or is the type information only internal to the shell and not exposed to the individual pipeline parts?The long answer is that all commands in the pipeline are treated as either a murex shell script or a builtin function. Any external commands are actually the builtin function called "exec" which is calling an external command as its parameters. This means I could effectively write my own pipeline with richer APIs beyond just reading []bytes of data. This doesn't come without significant drawbacks as well (which I can also talk about if your interesting) but I'm working to mitigate them.
So the following two lines of code are equivalent:
open foo.json | grep foobar
open foo.json | exec grep foobar
So if you then were to pipe that into another builtin you'd need to cast it again. eg open foo.json | grep foobar | cast json | ...do something
This is just illustrative though. Technically this would break the JSON file because "grep" just works on dumb lines and JSON isn't a linefeed document. This is why murex comes with such an extensive number of builtins, for example if you wanted to do a grep-like regex match against elements in a JSON array and output that as valid JSON you could the following pipeline: open foo.json | regexp m/foobar/
However going back to your original question, if someone wanted to write a shell script or any other utility that support murex data-type but wasn't part of the murex shell binary, then there's no way murex could pass that type information to it.This is a problem I've been mulling over for a few years now and I've considered a few options in that time - none of them are without their problems. At one point I even laid down some POC code but that has since been deleted because pragmatically it seems a premature problem to solve while I'm the only person developing and using the shell.
edit:
It's also worth noting that there is a default data-type that is assumed even when no data-type is specified. That type is a loosely tabulated "catch all" type format for your standard unix tools. That means output from commands like `ls -l`, `ps`, and other classic utilities can be parsed and fields selected intelligently. eg if you were to type the following partial command line then hit tab:
ps -fe | [ <tab>
You'd see the headings from `ps` in your autocompletion suggestions: UID PID PPID C STIME TTY TIME CMD
So you could select one or more of them: ps -fe | [ UID PID CMD ]
...and murex would filter the output of ps to only those 3 columns.It's not perfect by any means - since there are a thousand different ways developers can output data to the terminal - but it does seem to be an asset more than a hinderance for my particular use cases. Of course YMMV and I'd welcome any feedback if that were the case :)
How does the magic with JSON etc work? The docs do mention something about mime types but that is never really explained properly. If I make my own command that outputs JSON, can I make Murex understand that without explicit casts?
Overall the whole thing feels bit quirky to me, but there is cool stuff in there too.