GUI is better for discoverability of the most common scenarios (I can right-click to see everything that can be done with the file, including some third party programs). But it's bad for composing programs and interoperability, often it's impossible or very hard to automate (how many people are doing UI testing? there is a good reason it's not many -- it completely sucks)
TUI/console is very good for interoperability/automation/muscle memory, but doing one-off things is harder.
If I don't remember the `df` command... what do I do apart from searching on the internet? Maybe searching man pages, but it isn't as fuzzy (e.g. `man -K "free space"` isn't very fruitful).
In comparison, I know that if I start going through GUI, eventually I'll eventually find the free disk space info.
It's interesting that there is some analogy to object-oriented and functional paradigms -- if I have a rich object in a debugger in Python, I can call dir() on it to immediately see what I can do with it. Whereas if it's a simple dataclass, I'd need to search through code to find how I can use it. Might be a too far fetched analogy though.
I think we need all of it, and also need to make the distinction less apparent. Would be nice to make GUIs more composable, and TUIs more discoverable. Ideally it should be a spectrum of interfaces, so you don't have to make a hard choice and can gradually move into the direction you want.
I totally agree, and this is one reason why, broadly speaking, command line applications often turn me off, even though in theory I prefer them for the reasons you laid out. There's a sort of implication that you're not "in the club" if you don't remember this or that flag.
Why then isn't a kind of very simple approximation of a GUI (or, at least, easily-discoverable commands) more common in command line applications? I see no technical reason for the lack of it. Look at something like htop -- it has a sort of "command line version of a macOS menu bar" with each menu selected by a function key. I could easily seeing this idea being extended to, say, being called by the familiar --help flag, or each menu visualizing a sub-menu upon pressing a function key, etc...there's no reason CLIs can't have the same discoverability as GUIs.
The practice you recommend was basically codified as IBM Common User Access, now recognized by some as the UX convention of IBM mainframe software --- one component of CUA was a list of available actions and their assigned function keys, at the bottom of the screen. CUA itself was not widely used, but was highly influential in IBM's greater orbit of software vendors, including Microsoft. As a result, many, but not all, Windows GUI conventions and keyboard shortcuts come from CUA, and this is its lasting legacy.
That CUA was originally defined for text-mode applications as well, and indeed was based on loose conventions that had emerged within IBM for text-mode applications, has been largely forgotten. But even in the '80s there was an appreciable divide between the IBM paradigm, which was more oriented towards menus and actions (what we think of as GUI today), and the AT&T/UNIX paradigm, which was more oriented towards composition of commands.
Of course there are things like newt which have crossed the lines, but generally speaking UNIX derivatives such as Linux have tended to "stay in their lane" of command-oriented environments with minimal user assists. This could be seen as a long-lasting influence of the different I/O paradigms these platforms tended to feature in the influential '80s: UNIX systems were built around line input and output (e.g. TTYs) while IBM systems of the same era were more often built around video terminals (e.g. CRTs). This was basically because UNIX was predominantly running on hardware of opportunity (e.g. whatever the institution already had), and thus had to be flexible and not assume much, while IBM systems were more often used with terminals leased from IBM along with the machine and thus could assume the latest era of video terminal capabilities.
And then, of course, sometime around the '90s all of these platforms more or less ossified in their differences from each other, as each respective camp came to view their UI paradigm as a core feature of the platform which should not be modified.
This is just one of the ways in which UNIX and its family are much more "line-oriented" than even many of their contemporary competitors. This was partially by necessity but also partially by design as the line-oriented paradigm was easy to understand and work with, conceptually if not in practice. Ironically line-oriented input and output is often justified as being reminiscent of punched cards, when the software lineage with a far longer background in punched paper media (IBM, CDC, etc) were far quicker to get away from this model of human-computer interface than UNIX.
Put more generally, "GUI" vs "TUI" is to some degree a false dichotomy. Many of the real capabilities and interactions we associate with GUIs are also quite possible in TUIs (although the GUI version is clearly a refinement), and indeed were often implemented prior to the common availability of raster displays. When people talk about "GUI" vs "TUI" they are almost always actually talking about differing fundamental UI paradigms, which I might call action-oriented and line-oriented. Each can be implemented in a raster-mode or text-mode environment, although both generally work better in a raster-mode display (we might consider Jupyter to be an example of a line-oriented paradigm on a raster display).
You touch upon the problem.
The space is actually bidimensional instead of unidimensional.
On one axis we have graphical (raster mode) at one end and text at the other.
On the other we have as you calld them action-oriented (WIMP) and line-oriented (I would call it command-oriented).
There are text mode action-oriented apps: ncurses/turbo vision/etc. based applications like *Commander, or the old Borland IDE, or Tilde, or the old FoxPro, or plenty others.
And there are graphical command-oriented apps like Jupyter or ReGIS or Sixel or iTerm or TermKit or Kui or the command palette in VSCode or Atom or others.
And you can have them mixed like in youtube-dl GUI or ffmpeg GUI where the changes you make in the GUI are reflected in different arguments for the command and you can see and edit the command before executing it. This is similar to getting keyboard shortcut suggestions in menus or tooltips.
We need more innovation in this space. Ways to achieve both discoverability and scriptability. We need more hybrids and less systems that stay in their lane.
Graphical text editors with command pallettes, PowerShell with its object oriented piping, Jupyter are moves in this direction.
This is a power user direction. And it is opposed both to the minimalist touch friendly trend and to the terminal-first mindset.
> There are text mode action-oriented apps: ncurses/turbo vision/etc. based applications like Commander, or the old Borland IDE, or Tilde, or the old FoxPro, or plenty others.*
These are graphical programs, just with a substandard drawing api.
Actually even this two axis classification is imprecise.
CLI programs like the coreutils are actually sort of missing a user interface. They are just programs that receive arguments on launch.
How should we classify the following?
- Programs like coreutils that receive arguments and return a result
- Programs that start a menu or wizard in text mode
- Programs that start a interactive command line like various database CLI interfaces, shells
- Programs like Vim that have a TUI and are command line driven.
- Programs like Tilda that have a WIMP TUI
I think the last four have graphical equivalents (eg. Windows installers, Jupyter, VSCode, Notepad++ respectively) and what is missing is a graphical interface for passing arguments to programs.
I understand your point and your definition of GUI is much more inclusive. I however disagree with your definition and I consider it is not that commonly accepted.
I do agree with your definition of a command line interface as a stream of commands and responses.
> Why then isn't a kind of very simple approximation of a GUI (or, at least, easily-discoverable commands) more common in command line applications?
On IBM i (originally known as OS/400), you can press a function key and automatically get a fill-in-form for any command.
This is because command line syntax is defined, not in your program's code (getopt calls etc), but using declarations in what you might consider to be a separate command definition file (technically called a "*CMD object"). The OS does command line parsing and validation, marshals the result into a memory block, and passes that to your program rather than the raw command line. And the OS uses the same command syntax declarations to generate the (text mode) fill-in form for display.
Other systems which use the idea of command line syntax declarations, with the shell doing option parsing based on those declarations instead of each program doing them itself, include OpenVMS DCL and PowerShell. (PowerShell actually copied this idea from OpenVMS DCL and IBM OS/400.)
I think the big reason why this is less common in Unix-like systems, is the design decision to give each command responsibility for parsing arguments/options, rather than doing it in the shell. This makes the whole approach of automatically generating fill-in forms at the worst impossible, at the best unreliable. You can try parsing --help output or man pages, but that method isn't always going to work, centralising option parsing in the shell does. It is likely rather too late for Unix-like systems to change their approach.
Macintosh Programmers Workshop and I believe AU/X had this sort of functionality (different implementation, though) back in the 80s/early 90s. It was nice. :)
I don't think there is a club to be in, but if you want to feel in the club about such things, just say something like "I expect that there is an option for like '-w whatever_madeupoption' that is useful here, but I'd have to take a look at the man page or use '--help' to know for sure". Be prepared to respond to "how would that work?" with APIs/syscalls/etc that you might use to implement that or say something like "I'm not sure, it sounds like an interesting problem if I had time to solve it"
There are shells that help with discovery. And auto completion helpers. These are great. You might infer from documentation. There was a big thing about spacial awareness years back, my brain works well like that, familiar brain paths for controls in certain places. But that relies on repetition. I pretty much always forget shell incantations. So any helper tools are a boon for me. Self described to GUI or richer UI would be welcome. If it's not already done.
File explorer multi pick is the thing I desperately claw for for a pointer.
More to your point. I think TUI/CLI apps would be much more usable if help files where written for Beginner, Intermediate and Advanced (or similar). With the flat format we have now man pages and --help are overwhelming when something is brand new to you.
I just keep cheatsheets handy. For new scenarios, if I find they aren't already on the sheet, I add them. The best command line tools have good documentation you can find with a command like "help" or the "-h" flag. I am slightly annoyed there isn't a convention for this though. Perhaps it should be made into a RFC standard.
Cheat sheets are not form of discoverability. People generally want to use software and learn-while-using. By searching beforehand for a cheatsheet or reading a man page you are already studying how to use the software before actually using the software.
Compare that to most GUI apps where you can just open and use and learn as you go.
I just want to achieve an outcome. An argument could also be made that GUIs are a pita because you have to spend too much time discovering when you could just read the manual and do the task.
A fair part of what I do includes ERP implementation project work. Way back, when TUI/keyboard centric ERP system dominance was starting to give way to GUI/mouse centric ERP systems, I was working with one client where replacing a TUI with GUI based system. One measure we made during the project was the impact to new employee training time and we saw significant reductions in training time due to the sorts of discoverability you mention found in the GUI based system. It was just easier to use. This didn't come for free however. At a different client making the same transition from TUI based system to GUI based system (same target software), we measured the productivity of well trained staff and the TUI was well ahead in daily productivity. Now the different companies had different employment profiles; they were both retail businesses, but the first one that measured training was more decentralized and saw higher staff turnover rates and so cared more about training efficiency; the other had more centralized operations and so had fewer, more senior staff members with longer tenures where daily performance was a more important metric for efficiency.
Now a TUI isn't the same as command line and most GUIs allow for substantial keyboard functionality, but I think developing for a TUI tends to get you thinking about a person working a keyboard whereas developing a GUI you're thinking more about the person with a mouse/trackball/trackpad/touchscreen.
Personally, I do a lot of database work; mostly PostgreSQL. I decided some years ago to bite the bullet and get rid of the GUI and just use straight psql. I largely haven't looked back, though if I'm doing heavy development work I just started using DataGrip since it helps avoid stupid errors that a simpler text editor doesn't find.
What about a system that shows actions in a GUI as a list of equivalent plain text commands. New users would have the discoverability of a GUI while being able to see what goes on command-wise. With time they would be able to convert to plain-text commands and scripting for increased efficency.
AutoCAD sort of does that - actions can be launched both via the GUI and the command line, and all actions launched via the GUI also appear in the command line history, so you can pick up the names of the commands over time as you're using them (alternatively, they're also mentioned in the mouseover tooltip in the GUI).
I've actually contemplated this very idea and think it has merit. What I've found in many applications is that there is a stark distinction between GUI and TUI/CLI that isn't completely necessary... I speculate that there's more room for grey between the two. To be clear many GUIs can be used via keyboard alone, but often times that ability feels bolted on in that you only get things like shortcuts for a button presses whereas many text oriented interfaces offer more actions which are composites or which might not make sense in a visual presentation of the functionality.
Having said that, I think that the inertia of "good enough" is a real danger to the concept. The new user that uses the less efficient GUI aspects of the interface to learn quickly may not have much incentive to go the next step and work the keyboard oriented workflow into their muscle memory. Also, if you realize that issue, there's also the problem that if the keyboard interface were less used, there would be less incentive to fix issues or add features to it as the application changed. Rightfully, it could become less useful because of less attention. I can tell you that in practice I find it fairly uncommon to see staff using the keyboard capabilities insofar as it's already supported by their GUI applications.
An interesting UI paradigm I've run across [0] is using a keyboard-accessible hierarchical menu for all actions. It's similar to how AutoCAD works, but the "commands" you type are actually just sequences of menu hints. Most desktop apps support these hints with Alt, so the capability is there, but there is something about using the hint sequences as primary keyboard shortcuts that appeals to me.
The nice thing is that by using the keyboard to navigate menus, you develop muscle memory for "shortcuts" without really trying. And if you ever get "stuck", not knowing how to complete the sequence, you only have to look at the currently open menu.
Formica doesn't do this, but this could be extended into rudimentary scripting.
This kind of paradigm won't fit all software, for example I don't think it's a good fit for software where typing mildly structured text is the main mode of interaction. It might be mainly useful for shortcut-heavy software.
FoxPro worked like that. The language itself had commands for various IDE actions, like editing a source file (MODIFY PROGRAM ...) - these worked everywhere, but were really meant to be used in the Command window, basically a REPL. And then if you use the GUI to do the same thing - e.g. File -> Open - it would simply execute the corresponding command in the Command window.
This worked surprisingly well. New users mostly stuck to the menus to discover things, but then gradually switched over to commands for common actions, because they were faster. It also helped that the Command window had context-sensitive help, so once your menu action generated the corresponding command, you could easily open the manual page for it to read up on the details.
Maybe one day everyone will adopt PowerShell as the CLI standard.
PS scripts (and even functions) declare command line arguments up front, and depending on how much time and thought you put into it, you can constrain the arguments quite well. See [0] for overview of the available functionality. A quick TL;DR:
- You can make parameters typed, and PS will handle relevant conversion if the user just types strings in. E.g. you can mark a parameter as [DateTime], and if the user types e.g. "2021-04-01", the script will receive an object that represents the midnight on that day. If the user types in "foobar" instead, they'll get an immediate error[1] telling them the parameter cannot be read as a date.
- Add [] to parameter type (e.g. [DateTime[]] instead of [DateTime]), and now the parameter can accept multiple values (arrays), - but behaves smartly if only one is given.
- You can mark parameters as mandatory. You can mark parameters as positional (i.e. provided without specifying parameter name on invocation). You can mark a parameter as designated "catch-all". You can define aliases for parameters, to allow user to write e.g. -Runs, -Run or -R, and have all three refer to the same parameter.
- You can mark parameters as "accepting values from pipeline" (and define how exactly). Since PS pipes transport typed objects, not raw bytes, this is how you can both set expectations, and write scripts that can flexibly mix pipes with commandline arguments.
- You can define validation for every parameter individually.
- You can group parameters into sets, based on what other parameters are provided, or some custom logic. So e.g. if arguments -A and -B only make sense together, and then -C doesn't do anything, you can encode this cleanly.
- Autocomplete in PowerShell is aware of all these things! It'll hint you appropriately. And you can provide your own autocomplete hints too.
How is all that relevant to this thread? The last point is a spoiler: all these declarations can be extracted from the script, and they provide enough information to build a high quality GUI for the script automatically. PowerShell ISE, that comes with Windows, exploits this to a limited degree - it contains a GUI for running PS cmdlets that lists parameters and their types, makes use of optional/mandatory status, and groups them by parameter sets. There's nothing stopping one from building an equivalent UI generator that would also provide custom widgets based on argument types (e.g. file pickers for paths, calendars for DateTimes, etc.).
[1] - Errors in PowerShell are a bit user-unfriendly. Niceties like invocation with underlined mistake are surrounded by long error text and small stack trace. I wish they improved on that; even for script developers, most of the error message is quite useless.
Good to know, thanks! I've been mostly developing on the Windows PowerShell, but I'm about to move to PowerShell/.NET Core, so I'm happy to know error messaging improves there.
I like powershell, but I find its Syntax very hard to learn for casual usage.
-eq is just cruel if you are used to proper programming languages.
I'd love to see a sane script language ala typescript established as general purpose shell/shell scripting language!
TypeScript is not yet expressive enough for direct shell usage, but not much is missing imo (most importantantly a pipe operator).
Agreed. Having recently written a bunch of PowerShell scripts that were too big for their own good[0], I'm pretty much in love with it, but the language itself does bug me constantly. Operators are one of the big annoyances. -eq, -gt, -icontains, -match...
But I get it. It's the consequence of trying to use the same language for code and command line input. > and < are already used in pretty much every single shell to indicate IO redirection; particularly with >, it would be really dangerous for it to have context-dependent meanings. And then foo -match bar is more CLI-input-friendly than foo.match(bar) or match(foo, bar). You can get a similar experience if you try to use (or design) a Lisp shell. S-expressions are awesome, but having to move the caret back and forth to add/modify structure in your command is too annoying for a shell language. For shells, you essentially want as much appending and as little editing as possible.
And as much as I don't like JavaScript ecosystem, I would like something like TypeScript in the shell. Personally, my main requirements are 1) optionally typed, and 2) piping structured data instead of unstructured text/byte streams.
(And then I'd like a terminal emulator that makes full use of type system in pipes and command arguments.)
--
[0] - They started simple, then they grew, and before I noticed, they've crossed the threshold where, if I were to write them again, I'd use a regular programming language. I think the point in which I started including bits of C# code in the scripts should've been a wakeup call... but on the other hand, isn't it just cool you can drop down to C# in the middle of a script and have it Just Work?
I have, but it's been awhile since I looked. My recollection was that it felt sluggish, but that might be a false memory. I think what it brings to the table is helpful, but not enough for me to warrant it's use. When I'm writing simpler queries at the command line, I'm usually well within my knowledge of the databases I'm writing for or would have to appeal to something like the table definition anyway... which as I recall I couldn't really do in pgcli (start writing, flip to the table definition, pick up where I left off).
When the sorts of things that pgcli does becomes most helpful is when I'm writing functions and procedures, but then the command line isn't well suited for that. That's where I'm finding something like DataGrip helpful: a database tool focused on development rather than administration. DataGrip has a lot of faults, but for the past couple of weeks I've been using it, it's been on balance a win.
All GUI apps should be controllable entirely through the keyboard.
This is generally true of built in Windows applications (even if the transition to ribbon interfaces complicated flows). It is spotty for third party applications.
Unfortunately on Linux, at least on KDE (I don't like Gnome since v3), keyboard navigation is broken even on default applications like Dolphin or Discover.
Mac OS, I remember (Tiger -Lion) being pretty good.
Out of curiosity, what's the practical difference between TUI and GUI when it comes to discoverability? The kinds of TUI I'm familiar with - mostly from DOS, so stuff like e.g. Borland IDEs (and various third party apps written using Turbo Vision), FoxPro, and VB for DOS - are essentially the same as GUI in that regard; you get a drop-down menu on top, windows with various widgets, often a help bar at the bottom and/or context-sensitive help with F1 etc.
You can use the .psqlrc for this purpose, though I suppose you could also real that in via a file on demand, too. You make entries something like:
\set show_slow_queries
'SELECT
(total_time / 1000 / 60) as total_minutes,
(total_time/calls) as average_time, query
FROM pg_stat_statements
ORDER BY 1 DESC
LIMIT 100;'
and then later at the command prompt you access it as; ":show_slow_queries".
I have a few system queries like this in my .psqlrc file, but I don't do much which this feature often truth be told. I have a pretty strong knowledge of the database schema I work with, I do a lot of work on systems I don't regularly control so its not dependably available, and readline history suffices for more immediate needs.
>GUI is better for discoverability of the most common scenarios (I can right-click to see everything that can be done with the file...
You know the secrets on how to use the Microsoft Windows 95 GUI so it's easy for you. Consider the person who has not been trained over years in its use. The concept of a context menu that pops up at the mouse position when clicking button number two is not intuitive or discoverable.
My wife, for example, grew up before Windows 95 and its descendents were invented, holds multiple post-secondary degrees, and works with computers every day. She has no idea a second mouse button exists let alone that she can use it to perform file manipulation operations. She doesn't quite get the idea of "home directories" or "nested folders" or anything that is hidden like menus (or, frankly, tabs in the browser.. or multiple browser windows in fullscreen mode). Those things are not intuitive or discoverable in any way if you haven't been trained in their use. I, too, often forget the context menu is there although with practive I'm getting better. I certainly would never forget the `df` command though because it's second nature to me after over 40 years of use.
People need to be very careful when making an argument that something is better because it's what they're familiar with as if they are some definitive exemplar.
You're right that there's some irreducible aspects to even GUIs that isn't intuitive and you just need to be told how to use it once, but GUIs have an advantage in that the overall 'language' of those things is far more limited at a basic level.
Once you've figured out that mouse movements correspond to moving the pointer, clicking your left button usually means you want to do the primary interaction with whatever you're clicking on (opening a program, pressing a button, checking a checkbox), and right click gives you additional things you can do with the thing you're right clicking on, you've figured out enough to be able to at least use the system (I agree you're by no means proficient in it though).
To get comparable proficiency with a command line requires a much larger set of things to remember for even basic usage.
> "People need to be very careful when making an argument that something is better because it's what they're familiar with as if they are some definitive exemplar."
That is not the argument they made, they said right-click acts as a "tell me what I can do with this file" discoverability tool, not that right-click is itself discoverable. There is approximately no way to discover this on a command line, but if you right-click and "play with Windows Media Player" is there, it tells you something useful.
But I'm going to make the argument that it is discoverable. Why isn't the context menu second nature to you after over 25 years of use? You put your hand on the mouse, it has two buttons, you click one of them in ordinary operation, what kind of hyperbole is it to say that "clicking the second button does things" is "not discoverable in any way"? You discover that by accidentally mashing it one day, if nothing else.
That's apple's problem. I've been fixing apple devices since the puck mouse. They choose to go against the grain on purpose. Sometimes it makes sense and sometimes it makes absolutely none.
It means it's not the fault of the Windows 95 GUI paradigm most middle-class North Americans millennial age or younger have been trained with. Windows 95 is not the GUI paradigm, it's one single product that implements a GUI paradigm.
Meh if my grandma can get folders and hidden menus with just using simple box in a box analogies and a couple of drawings of the difference between RAM, hard drive, and CPU I'm sure your wife can too. Sometimes there's just the lack of curiosity about such things that prevents people from learning it, not age. I had a friend who mf'ing wizard at spreadsheets and vba because she likes what you can do with it. I tried to talk her though just installing an adblocker and newpipe install for better access to youtube and I might as well as have walked outside and started talking to my wood fence to get the same end result. So she drove over and I installed it for her.
> You know the secrets on how to use the Microsoft Windows 95 GUI so it's easy for you. Consider the person who has not been trained over years in its use.
it's easy because MS has spent years in formal user studies for almost every element of the 95 UI to make sure that it was easy for pretty much everyone.
I work in a public library and it has come to be my opinion that there's nothing at all intuitive about MS GUIs. Of special note is the awfulness of printing about which I'm asked 3-6 times a day, every day.
The thing about graphical interfaces is that a lot of the lack of standardization is purely cosmetic. A context menu may have rounded corners, or a black background and so on but the user doesn't have worry about these differences.
Cosmetic differences in CLI applications are actually important to get them to work in the first place. dash vs double dash, equals sign or no equals sign. CLI parsing is completely nonstandardized. Each command reinvents parsing and is completely unpredictable.
The only way you could possibly solve this is by letting the shell parse CLI arguments and just pass them as a JSON like object to the application. The ship for that has sailed a long time ago.
What if there was such a thing as a right click menu for command line programs?
Like if I type ffmpeg or youtube-dl with no args, it lists the 3 most common ways to use it, and maybe allows an interactive CLI menu where you can build up the correct argument list by answering a few questions.
I would love the most useful commands to look like:
ffmpeg --resizeVideoTo input.mp4 50% (0.5 also works of course)
youtube-dl --do-the-thing-you-know-i-want-to-do <YOUTUBE_URL>
cd --show-a-menu-of-the-last-10-paths-i-changed-to
git --i-fd-up-my-last-commit-please-help
Most realistically, I'd want the invocation without arguments to show an interactive menu of the top 3 uses, so I could just select what I want to do.
Or if I provide a partial argument list, it should ask me to supply the rest of the args. Or maybe it should guess and do the right thing.
For example:
ffmpeg input.mp4
>> What would you like to do with input.mp4? 1) resize 2) rotate 3) crop 4) change video format
youtube-dl URL
>> Download the best video for URL to the current path? Press Enter to confirm.
cd
>> Here are the last 5 paths you switched to. Choose 1...5.
find
>> Start typing a partial file name and we will show the top 10 matches from this path and its subdirectories. CTRL-<period> to turn on regular expression search.
That's basically what cheat.sh does. It's an editable wiki that contains common use cases (cheat sheets) and can be called directly from the command-line, e.g.:
That's what aliases or shell functions are for. Put them into your .bashrc/.zshrc/.whatnotrc and you can have commands like that, without messing up the fine tools you mentioned for the rest of us. Just drop the first space.
ffmpeg--resize-video video.mp4 50%
.bashrc:
ffmpeg--resize-video() {
ffmpeg ... "$1"
}
You'll have added benefit that ffmpeg--<TAB> will suggest you only your own UI, without interference from the tool's own options.
I make extensive use of aliases and bash functions. It's my only way to keep sane since I'm not smart enough to remember all these command line arguments....
While not entirely matching your vision for this, TLDR [1] does provide for a similar functionality (discoverability of functions of specific applications).
This doesn't help when you want to map the fuzzy idea of performing a specific action to a particular existing program but it has helped me avoid having to search online for how to perform a particular task with ffmpeg.
There is something like Gooey [1] that you can put to your own applications. I think it is technically possible to use Gooey to wrap existing applications, but not sure about the automation.
When I enabled tab completion for git and google cloud CLI, my life became much better.
However, I still think there needs to be a "right click menu" for command line programs. Someone needs to determine the 3 most common uses and make it so that --help lets me choose one of them by pressing 1, 2, or 3.
Right now, --help usually gives me something that is difficult for me to understand, especially if I have never used that command before.
Tab completion works great if I have used the command before and want to save time.
Tab-completion could additionally list the "most common things given the context* I have".
Tab-completion needs not nessecarily be postfix. I've seen completion tooling** that would work somewhat like `invoice.pdf<tab> -> `open invoice.pdf\n cp invoice.pdf` etc.
And if `<tab>` conflicts, or breaks your mind because it must only work on postfix, it could be anything really, such as `<cmd>-r`.
Additionally, or underlying, a reasonable simple command like `whatcan` or `ctxt` (context) could work and be leveraged: `whatcan invoice.pdf` -> a list of common commands given the context* I have.
---
* Context I have would be your ~.\_history, the current directory-tree, permissions (why show `mv` if you don't have write access?), applications available, etc. pluggable maybe?
** e.g. the <ctrl>-r, interactive bash history search come to mind as pattern. But also tools like FZF https://github.com/junegunn/fzf#fuzzy-completion-for-bash-an... that don't nessecarily only "complete" on tab, but may replace larger parts of the commandline.*
'help' is already the shell's built-in help function in most cases. That'd be a poor choice of alias.
There are a small number of seed keywords which are ueeful to know. 'help' (shell), 'apropos', 'man' (online manual), 'info' (GNU documentation), and dwww (local documentation presented through a Web interface, available on Debian-based Linux, see https://ostechnix.com/dwww-view-complete-debian-documentatio...) are among them.
Knowledge requires a certain baseline.
If that's too much ... perhaps a GUI is in fact advisable.
just once to (re)build the index. Results are guaranteed to be of high quality only on a real UNIX, preferrably one of open source Solaris (illumos) distributions, and likely FreeBSD.
Except modern UI design sort of threw the aspect of discoverability out the window. Context-sensitive elements, dependent elements, hidden elements, and the dreaded hamburger menu are all awful for discoverability, and they're present on nearly every GUI.
For everything negative you can say about modern UI patterns like the hamburger menu, lack of discoverability isn‘t one of them imho. You have a single button with an almost-standardized icon, from which you can get an overview of all the (non-context-sensitive) actions. Relative to menu bars, the actions are sorted more by their importance than some vague categories. (Where do you find Settings? Under File, Edit or Help? No, as a top-level entry of the hamburger menu.) Of course it has its own problems, like number of clicks...
Hamburger menus work because software that employs them is trivial. Often not far from a toy MVP. Discoverability is easy when there's not much to discover.
All the pre-Web UI patterns start to shine when you're working with more powerful software tools - where there are more than half-dozen available actions, so you can't just stuff them under a single hamburger list. You have to start categorizing, grouping actions by their commonalities. You can't sort by importance, because importance changes from minute to minute.
And menus of old were plenty discoverable. They weren't categorized for discoverability, because that's not the job of categorization. If you want to discover what the software can do, you spend 60 seconds expanding every single menu and reading available options. The categorization is there to introduce grouping concepts that are easy to remember, so that next time you're looking for an action you know (or suspect) exists, you know where to look for it.
There's always a space tradeoff, of course. If you didn't make some things contextual or put them behind a menu, you'd have to find permanent space for it on-screen. At some point, your UI then turns into a "Find Waldo" scenario.
Yeah I'm confused about what OP meant was wrong with hamburger menu, the paradigm is "if the screen is too small for File | Edit | View | Etc. | Help, then collapse them behind the hamburger, which is generally good and sane.
I'm surprised there is a distinction between the two at this point. What we have are "user interfaces" and both are graphical, whether it's interacting with text or graphics.
I think the main issues of usability are paradigm-independent—how do you make the UX more discoverable for text interfaces? How do you make the GUI more powerful and accessible to scripts? GUI development was introduced to make computers more tactile, and feel more life-like and accessible; and it works.
The reason Text-UIs work better for automation is that programming languages these days are text-based. How might one shift to a more graphical-programming paradigm? Machine learning I think has a lot of potential in this area and I would love to see some new work in this space.
This reminds me of my first experience with (DEC) Unix at JHU. I had been a VMS user, so when I logged into the unfamiliar system I typed in "help." The JHU site admin had helpfully set the output of the help command to be, paraphrasing, "I see you know nothing about Unix, please talk to the staff member." He told me, "oh, in Unix help is spelled man." Obvious!
$help
GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
These shell commands are defined internally. Type `help' to see this list.
Type `help name' to find out more about the function `name'.
Use `info bash' to find out more about the shell in general.
Use `man -k' or `info' to find out more about commands not in this list.
> If I don't remember the `df` command... what do I do apart from searching on the internet?
I'd try "ls /bin" and see if any of the names sounded familiar or possibly relevant. Or "man -k space" which shows "df (1) - report file system disk space usage" on line 24, which isn't a lot of reading.
GUI's aren't always intuitive. Nothing worse than not having the option in your right-click menu because you tried right-clicking in the left "explorer" column, but really needed to open the parent dir then right-click on the folder in the right-hand side. GUIs can be infinitely more difficult/complex.
Back in the Win95 days, I recall a case where someone couldn't figure out how to format a floppy. After struggling for hours, he did a search which found format.exe, and used it. It's hard to discover that you can right-click on the drive to get the option, because there are many things that don't show up there... You can't create partitions or change drive letters in the right-click menu there, for example, but how would you know? You've got to learn the options/capabilities for your system, whether its GUI or CLI.
What a GUI really has going for it, is that it offers a limited set of options, greatly simplifying the exploration. Something like Norton Commander, DOSBox or other limited/restricted shell (which shows only the most common commands) has similar discoverability benefits without the graphics, and still with those cli benefits available to you.
what do I do apart from searching on the internet?
On a real UNIX like HP-UX, IRIX, Solaris, FreeBSD or illumos (and any of its distributions), you'd run catman -w as root only once for the lifetime of the system, then run:
man -k "disk space"
and then you'd search for SEE ALSO with "/", eventually you'd run into df(1), under the very bad presumption that it isn't the first hit.
EXAMPLE (Solaris 10, identical for illumos / SmartOS)
> man -k "disk space"
cfsadmin cfsadmin (1m) - administer disk space used for caching file systems with the Cache File-System (CacheFS)
df df (1b) - display status of disk space on file systems
df_ufs df_ufs (1m) - report free disk space on ufs file systems
snmpdf snmpdf (1m) - get a listing of disk space usage on a remote machine by means of SNMP
space space (4) - disk space requirement file
df df (1) - report file system disk space usage
df df (1gnu) - report file system disk space usage
...on a real UNIX, manual pages are THE resource, they are very comprehensive because they were written by professional documentation departments, respectively professional technical writers in those departments working with the actual engineers who developed the software.
The manual page system on a real UNIX is designed to locate exactly the type of information you would be looking for quickly, efficiently and most importantly, consistently.
It's GNU/Linux manual pages that are utter garbage, ergo switch to a system like SmartOS and never look back.
> GUI is better for discoverability of the most common scenarios (I can right-click to see everything that can be done with the file, including some third party programs). But it's bad for composing programs and interoperability, often it's impossible or very hard to automate
I think that's more a design-problem than actual trait of GUIs.
GUIs have evolved that way, but there is no reason why they can't support composing and interoperability too. MacOS, KDE and Web-UI showed how it's possible to do. It's just that nobody ever went to the full way to build a GUI-Framework from ground up that is reaching the same level of automation as shells.
> TUI/console is very good for interoperability/automation/muscle memory,
TUI and console is not the same. TUI is a GUI inside the terminal, thus usually only with text. Vim, emacs, mc or any curses-app is an example of TUI. And how well can you automate and support interoperability with them really? As I know, all the automation and interoperability comes from the devs adding it on purpose, it's not there by design, or as easy as with a shellscript.
> If I don't remember the `df` command... what do I do apart from searching on the internet? Maybe searching man pages, but it isn't as fuzzy (e.g. `man -K "free space"` isn't very fruitful). In comparison, I know that if I start going through GUI, eventually I'll eventually find the free disk space info.
To be fair, GUIs can also have complex workflows and undiscoverable features. It's just common sense that GUIs have menus for every possible action. A GUI is a canvas, and there are established languages which creates frameworks of content which you should paint on this canvas. But this doesn't mean you speak one of this languages well or even at all.
> I can right-click to see everything that can be done with the file, including some third party programs
Smart move by (for instance) Microsoft when they did that in Windows 95 and continued it til now. You could theoretically design the same functionality into a text user interface. Like if you type the name of something (a filename) and hit enter (or maybe tab? space? Whatever the designer comes up with) it could give you a menu to choose from context specific commands. It would seem pretty natural in that case if you are using post-fix (arguments(s) and then commands, like in Forth). Maybe something already exists like that.
> Like if you type the name of something (a filename) and hit enter (or maybe tab? space? Whatever the designer comes up with)
How about:
$ file --help | grep util
-u, --utils output utilities related to FILE
$ file -u index.html
index.html: HTML document, ASCII text, with very long lines
cat index.html
ed index.html
lynx index.html
That sounds like a GUI; how do I pipe [open, copy, rename, etc] into sed or awk? (Because the^Wa problem with GUIs is that the answer tends to be "Why would you want to do a wierd thing like that?".)
I can try... Specifically, given a command that produces a list of "everything that can be done with the file", how do I cause the (unstructured) text of that list to be piped into a arbitrary other program, in the same way that `grep foo a.txt | bar` causes a list of occurences of 'foo' in a.txt to be piped into arbitrary program bar.
Ah, thanks for the clarification, it definitely cleared up what you mean.
As I understood the suggestion re. file actions it is meant as some sort of interactive completion. So if I type the name of an image file and press tap, I am given the suggestions or options about resizing, format conversion etc. Several shells already have interactive completion of file names.
And I think that pattern makes sense from an exploration perspective. If you learn that file name + tab gives suggestions, then a lot of the learning about what the command line can do can be done directly in the command line.
And maybe it could be a command rather than a tab-press. Then it, given a file, prints typical actions/commands/tasks to stdout and then subsequent CLI tools can be used to process that output.
I really don’t see how this is incompatible with existing workflows :-)
Update. I tried the `file -u` example you gave above and the `-u` flag doesn't exist in my version of `file`. I also find it a bit hilarious that the example lists `ed` as the editor of choice.
> the `-u` flag doesn't exist in [any] version of `file`
Yeah, I was giving a example of a sensible way to design it, not documenting something that already exists; sorry if that wasn't clear.
> And maybe it could be a command [like `file -u FILE`] rather than a tab-press. Then it, given a file, prints typical actions/commands/tasks to stdout and then subsequent CLI tools can be used to process that output.
Pretty much that, yes.
> I also find it a bit hilarious that the example lists `ed` as the editor of choice.
I don't think unix had TECO as a standard utility, so I went with what was available.
In bash I can type, for example, "git <tab><tab>" and it will list out all of the git commands. Not quite as nice as a menu, I suppose, but still helpful for discoverability.
GUIs have a nice ramp-up and a fixed ceiling, whereas command lines require you to climb a brick wall (the part where you learn enough commands to make it worthwhile, pretty much by rote) but, as long as they're scriptable, the ceiling is close to unlimited.
(TUIs are, or can be, GUIs with box drawing characters instead of pixel displays. They're not necessarily any more scriptable or any less discoverable; however, a TUI on top of a command line, like Norton Commander or Midnight Commander, can be a real winner of a design paradigm.)
By nearly the same token, though, one could say that Windows NT, which is for most practical purposes a descendant of VMS, implemented these ideas... and UNIX lost out to it.
I think that some version of this dichotomy has existed at nearly every point of computer history where technology allowed it, and that is surprisingly far back!
How did UNIX lose out to NT, when market forces coerced Microsoft to include a shoddy copycat version of UNIX named GNU/Linux inside of NT? That is almost the ultimate punishment for Dave "Gettabyte" Cutler, the father of NT and a notorious UNIX hater.
"free space" doesn't turn it up, but on my system only turns up one result that obviously isn't it, no big loss.
"free" also doesn't turn it up, which seems like a missed opportunity. Going through the 40ish results before you're confident it's none of them is needlessly painful, but not crazy.
Both "disk" and "space" do turn it up, though, and also surface du (amongst about 50 other things).
I don't think scanning through <100 text items is clearly worse than digging through (say) the Windows control panel GUI.
~~~
I'd also note that TUI encompasses two kinds of thing - the utility in the shell (like df) and the captive interface that takes you away from your shell for an extended time as you navigate possible actions in some other manner. The latter has more of the benefits and drawbacks of a GUI.
~~~
In any case, I don't think your thesis is too far off, and I certainly welcome improvements to composability and discoverability across the board.
> I can right-click to see everything that can be done with the file, including some third party programs
Everything? Almost certainly not! That is the main problem with GUIs. The "everything" is defined by the programmer, not the user. Sometimes that works for you, sometimes it doesn't.
It's important not to confuse TUI with "console". TUIs are essentially the same as GUIs in this discussion. CLI (console) is completely different. CLIs use a language to describe what you need. To use an analogy, imagine ordering food in a restaurant. You could get away with pointing at the menu as long as you're happy with getting the default configuration. If you want to ask for no cheese, or less mayonnaise, you have to use language.
Text-based interface with fuzzy contextual autocomplete is the best of both worlds. Think of an IDE's autocomplete popups, but for terminal commands. Or how the Command Palette in means I almost never have to memorise where some obscure setting because I can just type the first few letters and find it as a top match.
No such UI exists for terminal emulators because they don't work that way, but I'm convinced if someone made a program entirely around text with autocomplete it would be just as accessible to non-technical people.
I think this is because of the "default" behaviour pattern. You can rightclick or do a context click on the most systems. Even on smartphones you can hold your finger on the file to get a context menue. This is not the case for cli. There is not global pattern like "context file" or "options file" that works on every cli. There are not a lot of easy common patterns in the cli world. Even for autocomplete you have to change the default shell on the popular systems.
> f I have a rich object in a debugger in Python, I can call dir() on it to immediately see what I can do with it. Whereas if it's a simple dataclass, I'd need to search through code to find how I can use it.
No OOP language can have a search feature as useful as Hoogle:
One thing that I hate to admit is great at this, is JIRA. It is definitely a UI centric product! But when I want to compose it with something, the REST API is right there. In fact, when a mostly-background system needs a human in the loop, sometimes we can grab JIRA to be our UI.
> GUI is better for discoverability of the most common scenarios (I can right-click to see everything that can be done with the file, including some third party programs).
No. One has to be trained to right-click. What about interfaces that don't have a right-click, such as a touch interface?
Not only that, but the right-click menu has to be programmed. A lot of designers want minimalistic interfaces and would remove anything that isn't used often. So your right-click menu won't have those features.
> TUI/console is very good for interoperability/automation/muscle memory, but doing one-off things is harder.
Are you kidding?! I've found that doing one-off things is massively easier and faster in a TUI than in a GUI!
> In comparison, I know that if I start going through GUI, eventually I'll eventually find the free disk space info.
I've found plenty of GUIs that simply don't have what I want. Or... maybe they do have what I want but I couldn't find it.
> Are you suggesting that we switch to TUIs/CLIs on touch interfaces? If not, what's your solution?
My solution is that touch interfaces are a bad design in the first place. They're significantly less accessible to people with disabilities. They present a lot more problems with feedback about which buttons you're _about_ to press. And they're ficking obnoxious because everyone and their marketing team wants a completely different interface so nothing is ever consistent even on the "same" operating system.
> For example?
Example 1: download one file from a url mentioned somewhere
curl -fLsS "$(query for url)" -o ~/Downloads/file
Example 2: download a bunch of PDF files
cat ./file | grep -P '\.pdf$' | while read -r url; do curl -fLsS "${url}" -o ~/Downloads/"$(basename "${url}")"; done
sort <(grep -lRIiw "magic" /path/with/content | while read -r path; do basename "${path}" .txt; done) <(pdfgrep -l "magic" /path/to/pdfs | while read -r path; do basename "${path}" .pdf; done) | uniq
And now, I have accepted a file from a team member which describes URLs to PDF reports with magic. I have generated a one-off report describing which files have magic content that needs to be reviewed because it contains magic that's described in in a local database.
How about generating a git-diff, encrypting it, and emailing it?
cat <(echo Subject: diff for the work you needed) <(gpg -a -u inetknght -r recipient -o - -e <(git diff new..old)) | sendmail recipient
... Okay so those one-off things are complex things. How about simple things?
Example 6: move a file.
mv ~/Downloads/foo ~/Documents/
Example 7: open a file
xdg-open file
Example 8: delete a file
rm file
Example 9: mount a thumb drive
mount /dev/device /mnt/filesystem
Example 10: unmount a thumb drive
umount /mnt/filesystem
Example 11: shutdown, and don't let any bad app stop the shutdown
It certainly is easier for you or me, but not for an average person. Let's look at the command names. find, sort, and even mount are ok. curl? Does it have anything to do with curling? cat? What do cats have to do with files? Oh, it's because I'm using a mouse, isn't it. mv? Why not move? Or going back to previous examples, why not fnd or srt? Consistency is important and you don't want users to guess. grep, xdg-open, and systemctl are just random letters for most.
And that's just those who can speak English. If someone doesn't, it's just nonsense for them.
> One has to be trained to right-click.
One has to be trained to understand which commands exist and what do they do. I can't imagine someone without any training typing `grep -nRIiw`. Sure, you can look it up in the manual, but that's the thing - you shouldn't. You should consult the manual when you're using something for the first time or something isn't working. I can pick up any vacuum cleaner or get in a rental car and start operating them right away. I have to look up how flag works with different CLI apps. I shouldn't have to. Good design should be obvious.
That's why we're not typing `systemctl poweroff --force` to turn off a TV, we just press a button on a remote. And I can pick up remotes from other TV sets and turn them off without looking up their manuals.
> nothing is ever consistent even on the "same" operating system.
Funny you mention that. I tried some of your commands. Turns out, I don't have systemctl or pdfgrep installed. So much for consistency.
> My solution is that touch interfaces are a bad design in the first place.
Don't get me wrong, I also hate touch interfaces, for all the reasons you mentioned. But saying they're "bad design" is not a solution – it's a starting point at best.
What alternative are you suggesting for smartphone-sized devices? Mobile phones did have physical buttons, but once touchscreen-only devices came out, customers voted with their money. So much so, in fact, that smartphones with a physical keyboard are a tiny niche today. That's because keyboards just don't work well with small devices. Using a CLI with a smartphone keyboard would be an awful experience.
I feel like the autocomplete offered by fzf with <command> * is a step in the right direction. I don't think it supports flags atm but that could probably be done with a script.
GUIs are great, but not having a CLI is an anti-pattern. Also, having an API, but no reference CLI is an anti-pattern (depends on your API, but if your examples are poorly constructed bash scripts with cURL lines you need a proper CLI).
TUI/console is very good for interoperability/automation/muscle memory, but doing one-off things is harder. If I don't remember the `df` command... what do I do apart from searching on the internet? Maybe searching man pages, but it isn't as fuzzy (e.g. `man -K "free space"` isn't very fruitful). In comparison, I know that if I start going through GUI, eventually I'll eventually find the free disk space info.
It's interesting that there is some analogy to object-oriented and functional paradigms -- if I have a rich object in a debugger in Python, I can call dir() on it to immediately see what I can do with it. Whereas if it's a simple dataclass, I'd need to search through code to find how I can use it. Might be a too far fetched analogy though.
I think we need all of it, and also need to make the distinction less apparent. Would be nice to make GUIs more composable, and TUIs more discoverable. Ideally it should be a spectrum of interfaces, so you don't have to make a hard choice and can gradually move into the direction you want.