-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use of subcommands in the CLI syntax #82
Comments
Hmm. I could think about this over the weekend and try to sketch a subcommand-based syntax that's easy to script reliably yet not too verbose for common tasks. It's not trivial to balance those conflicting needs but maybe a decent solution can be found. I have lots of experience dealing with the pain points of various command line tools and the nitpicky personality to do it 😄 |
Awesome! We definitely need that 😄 . Your input is very much appreciated. I have not thought about the CLI much lately -- have been working on website/documentation and Unibeautify CI preparation. Looking forward to hearing more of your ideas! |
Thanks :) I'll try to sketch it up. In a way, it's good that Emacs package has to rely entirely on the CLI, since developing those in tandem ensures that the CLI ends up actually being easy and reliable to script. I think a Vim plugin would also have to be done completely via the CLI (and probably most other editors that don't have native JavaScript). If you can recruit someone to do a Vim plugin, we would have even more assurance that the CLI is done right 😄 |
Late with this, but finally arrived at a solution that I personally think is OK:
It might be reasonable to combine This syntax is easy to extend, easy to script reliably and ought to be pretty easy to comprehend at first sight. In my opinion, it's also aesthetically good enough (but I'm quite heavily biased toward reliability and simplicity at the expense of brevity and shortcuts). Some might find it too verbose. The biggest problem here is that one can't simply do Most of these subcommands would take flags (filenames, output formats, quiet/verbose, etc.) but I thought it'd be best to agree on the basic command set before getting into those details. |
Actually I just realized that the filename arguments should probably not be optional. If the list of source files comes from an array that happens to be empty, then
Generally, all kinds of optional arguments tend to be a bad idea in a CLI syntax, for similar reasons :D The purpose of |
Here are some examples of how one might script this interface, in Unix shell syntax:
|
For comparison, if we lumped all the subcommands together instead of dividing them in groups, it would look something like this:
Still reliable and extensible, but IMHO not as elegant, and maybe not as easy to understand at a glance. |
@lassik This looks great! 🎉
I like the groups as described in #82 (comment) 👍 .
Could you explain a little more what
Looks like it checks for metadata specifically involving the
I am OK with
Your case there makes sense. In general, Unibeautify treats the filename as being optional. This is valuable in cases such as beautifying an unsaved text editor. |
Yes, exactly. Quoted from above:
That's awesome 🎉 We can also provide tab completion for bash/zsh. I can look into that.
Agreed. |
Trying to work out the details of the This is the most elegant thing I could manage:
So All of these would take the following common flags (maybe add one-letter abbreviations):
I can explain in painful detail why all of this is the way it is :D But how do you think it looks at face value? I think the main problem now is that with 3 levels the commands are so long. One thing that could be simplified about this is that |
Here's a variant that replaces the word
Actually I now prefer this because it's even more obvious. And having |
Since
This now gets my vote 😄
|
Here's yet another attempt 😄 Thought more about the So the main point of And diffs are just one kind of side product. We can produce any number of other kinds of side products: JSON reports, HTML reports, XML reports, lists of filenames - even the exit code of Since beautified code is the primary product, we could structure the commands around where it goes:
All of these commands would have the same flags for generating side products:
Each flag would take a filename argument saying where the output goes. Since |
Even more 😄 After playing around with it, I think
So all these commands have identical It would work like this to write some stats to stdout:
You could do the same with You could redirect stats to a file:
Maybe to a file descriptor:
The
So the applications can get quite bewildering in the end when many of these flags are combined, but the important thing is that the option scheme is still very simple and symmetrical. Should be easy to implement and use safely. And the common use cases also look very simple. |
Okay, check this out, this is the simplest yet:
So The The So you'd use it like this:
I think this is about as simple, natural and extensible as we can make it. |
The file descriptor support seemed weird at first but it's starting to grow on me. Tempfiles are the bane of inter-process communication. It's much cleaner to pass everything around with pipes. If we support routing output to arbitrary file descriptors, callers can create a pipe for every kind of output they need, then just assign the pipes to pre-determined file descriptors and tell |
On safety Because we use prefix syntax in the
And since The commands work properly when sourcefile names come from an array (they don't do anything weird for zero-length arrays):
|
Normally Unix commands have a
|
@Glavin001 General impressions so far? I have some inspiration so I could make a feature branch and try coding a first draft in about a week if you're on board with the general direction the design is going. Mainly I'd like to try out how intuitive it feels to use the |
@lassik A goal I share. I'd be open to receiving a Pull Request implementing this. Of course, we need to continue support for Linux, Mac, and Windows. @lassik I think you have a great understanding of what needs to be done and a strong future-proof design. Could you update the Issue body with a summary of your final proposal? And use Task Lists so we can track progress: https://help.github.com/articles/about-task-lists/ |
Thanks for entrusting this :) I'll try to get a working prototype in an experimental branch soon. As for the proposal and task list, I think that depends heavily on how the design works out. It's almost impossible to tell how good an interface is without building prototypes, trying actual use cases and gathering feedback, as there are often unexpected edge cases lurking that can make a whole design unsound, and then the "gut factor" - a design that looks good on paper may not be good to use and vice versa. Honestly, the criterion I always use is, "keep trying things until it's pleasant to use" 😄 The sketches in this issue cover a wide range of use cases, so that gives some confidence that the overall design is workable, but by intuitive guess, 1-2 big changes are needed still. |
I think since Unibeautify is a beautifier I would not add the beautification function as a subcommand. This would take users to type even more to beautify a file. I think we should keep this as simple as we can. So when the user is typing |
I agree that it would be simplest if people could just type Some things we could do to help:
Personally, I like options 1 and 2. Option 3 seems a bit too complex to me (what if installation is messed up so some of the commands point to a different version of Unibeautify than the others?) |
The other question: Should the Many things can possibly go wrong when beautifying a file, so the user should always have a backup of the file. Usually people have the file in version control (Git) which is a good backup. But we'd need some way to make sure of that before we overwrite their files. In my opinion, the default operation should not be destructive unless we have backups. We could do this by:
Unfortunately, if we don't do any of the above, it's likely that there will be some bug or problem and someone will complain that we deleted their code or messed up their files without warning |
Using a Unibeautify editor plugin (VScode, Vim, Emacs, etc.) is great because the editor's own "undo" feature provides an automatic backup. But I agree that calling |
@lassik Is it not possible to have both? Using I agree that it makes more sense to have it the other way around, so the user choose by its own to rewrite the file and I like your idea (2.) to look for version control. (maybe something we can add to global unibeautify options, for those who are sure about what they are doing) |
We actually have this in the current CLI syntax, but it's not customary to do that. The reason is that command line arguments should not have "magic" values that do something different from all the other possible arguments at that position on the command line. E.g. Often command arguments come from a variable in a shell script, e.g. The traditional Unix convention is that flags that start with a dash ( |
I don't know if some programs also turn off subcommand processing after |
I'm late with these comments, but anyway, the issue of subcommands needs some long-term thinking. On one hand, it's nice to be able to do just
unibeautify file.c
. On the other hand, this makes theunibeautify
command's syntax harder to extend in the future.The current
unibeautify
command supports giving the filename asunibeautify foo
, but also supports the subcommandunibeautify support
. I would strongly encourage us not to mix these two usages. Shell commands should be easy to call from shell scripts and other programs, so it's customary to do things likeunibeautify $file
, where the value of the variable$file
can basically come from anywhere. Usually this is protected asunibeautify -- $file
so that$file
is not interpreted as a command line option if it happens to start with a dash (the--
argument disables option parsing for the rest of the command line, any options that come after it are treated as ordinary arguments even if they start with a dash).Anyway, the overarching principle is that any command line argument can come from a variable, so an argument at a particular position should always have only one kind of meaning. So we should have either:
unibeautify $file
andunibeautify --supports
, or:unibeautify beautify $file
andunibeautify supports
For the same reason, command line flags should not take a variable number of arguments. I don't think we have any of these :)
Of course, the subcommand names are up for debate :)
The text was updated successfully, but these errors were encountered: