geophile / marcel

A modern shell
https://marceltheshell.org
GNU General Public License v3.0
338 stars 13 forks source link

New behavior for existing standard-shell commands? #6

Open bhakta0007 opened 4 years ago

bhakta0007 commented 4 years ago

I am exploring marcel and I see that existing commands have different behavior in marcel. Most of us have ingrained muscle memory with regular shell commands (like I always do "ls -ltr").

Is this by design or are these bugs that need to be fixed?

for e.g.

(with bash)

(venv) bhakta@blr:~/dev/marcel$ ls -fr
.  ..  .git  .gitignore  .idea  COPYING  LICENSE  README.md  bin  experiments  marcel  notes  setup.py  test  venv
(venv) bhakta@blr:~/dev/marcel$ ./bin/marcel

(with marcel)


/home/bhakta/dev/marcel> ls -fr | less
Missing filename ("less --help" for help)

/home/bhakta/dev/marcel>
/home/bhakta/dev/marcel> ls -fr > x
/home/bhakta/dev/marcel> vim x

<hangs - I had to ctrl-c>
^C

Ctrl-c did not come out, I had to kill the window


/home/bhakta/dev/marcel> ls -ltr
Operator ls: Unknown flag -ltr
/home/bhakta/dev/marcel>
geophile commented 4 years ago

My thought was that I want to keep using ls (and ps, head, tail, and a few others), but I don't mind changes in behavior. In Linux, flags mix behavior (what is reported) and formatting (how it is reported). Linux's ps flags, in particular, are a complete mess, inheriting flags and even incompatible flag syntax from different species of Unix. I thought a clean slate for ps and ls was a better way to go, and resulted in better compatibility with other marcel concepts: piping streams of objects; a separate operator (out) writing to the console instead of adding that logic to other operators; and the "rendering" of objects, e.g. marcel.object.file.File.render_full().

However, I do recognize the downside of this choice which is that ls (for example) doesn't work as it does in bash. Other possible designs include:

What are your thoughts? It is early enough that nobody is relying on marcel, so fundamental changes like this are still possible.

As for ctrl-C not killing your command. That is a regression. Working on a fix now.

Other items you raised:

I expect to have a new release fixing the ctrl-c and vim issues in a day or so.

geophile commented 4 years ago
    • Ctrl-c is now working again.
    • vim should now work
    • was working as intended, but the documentation on > and >> needs to be improved.

    • Invoking less from marcel still does not work.

Not closing this due to items 3 and 4.

bhakta0007 commented 4 years ago

I do see your point on new behavior versus muscle memory and supporting existing ways of doing things. I do think that muscle-memory-friendly products would help in initial adoption and building a community of users.

I am not sure what your design goals are for marcel are but I have always felt the need of some of the below features in a modern-day programmer/power-user friendly shell:

(of course, this list is not complete - there are a lot of interesting things that can make life easier)

geophile commented 4 years ago

Thank you for your thoughts. Some of what you ask about is already present, and I like many of the other ideas. (I really need to step up the documentation. A tutorial is probably a good thing to provide.)

I'm open to suggestions.

Not sure what you mean here, can you expand on this?

There are certainly repetitive patterns in shell usage, e.g. yesterday I ran make, cd .., runtests repeatedly. It should be feasible to design something to support this and reduce repetition. But AI? (I want to avoid a Clippy-like "You seem to be writing a business letter! Can I help?")

I've been thinking about this. There is a file string command history, of course, (~/.marcel_history), but things get messy when there are concurrent sessions. (Currently, one sessions's history will overwrite another's.) To avoid those difficulties you would need some concept of a named session. And then it would be easy to record the marcel namespace on exit. Perhaps there is one default session, but you can create named ones?

That exists, although the syntax is probably not what you expect. If you do "ls -fr > x", that saves the result of "ls -fr" in the environment variable x. "ls -fr >> x" appends to x. Marcel pipes streams of tuples, and what you are doing here is gathering up the stream and placing it in a variable, (it's just the stream stored as a list).

You can then read out from the saved stream, turning the contents of x back into a stream, e.g. "x > select (...) | map (...) | ..."

See above. You can process these stored streams using set operations (union, intersection, difference), and join (which is like a relational join). Note that difference is set difference, not a source management diff operation. But that certainly would be useful. I will start thinking about a design for a diff operator.

I'll have to investigate. Marcel has pretty traditional auto-complete for operators, arguments, and options.

CSV support is there (see read --csv and --tsv). I've been thinking about JSON, but that's a bit tricky. Here's the problem: The "data model" of shell usage is typically tabular. You have a stream of files or processes, for example. These types have attributes, so you can turn a stream of files, for example, into a stream of (file name, mode, user, group, size). That's tabular. JSON is hierarchical. I don't really see how piping JSON from one command to another would work in practice. Can you provide an example that would help me see this?

That already exists (for Python)! Take a look at this: https://www.marceltheshell.org/scripting. Or do you mean a remote API?

I completely agree that this would be a useful thing to have. It's on my mind, and I'll start on it once there is some interest in marcel.

I think this may be present in part. As mentioned above, you can use > and >>, set operations, and join to build up collections of data in memory. You can then pass all of this to the out operator, which supports Python formatting, e.g. "ls -fr | map (f: (f.name, f.size)) | out '{}: {}'". You can also write arbitrary Python functions in ~/.marcel.py (or import them), and use those to format strings for output, e.g. "ls -fr | map (f: format_file(f))", where format_file is a functioh you provide.

About compatibility ("muscle memory"): Do you think, for example, that it would be useful to have a -l flag that was ignored? (Or maybe printing a warning?) Or more generally, providing a way to approximate the behavior of commonly used flags? (I have no idea how "commonly used" would be defined for ps which has a huge assortment of flags.)

geophile commented 4 years ago

One important additional point, on set ops: The set ops do not guarantee order. For the scenario you describe, order is important, and of course, the traditional diff does preserve order.

bhakta0007 commented 4 years ago

<meaning to respond to this thread - been tied up with things, I will reply back on this>