CLUI: Building a Graphical Command Line
blog.repl.it
blog.repl.it
The only valid point made here is that it is hard to learn for someone who never used any editing software at all. But it certainly isn't slow or "unfocused". That source monitor is on screen for a reason. Keyboard shortcuts will always be faster than moving your mouse around. And by the way: Premiere has a modular interface, so if you hate the clutter or don't need it, you can get rid of it.
If you are the person who just wants to edit some stuff together once a year Premiere _Pro_ is not for you. Turns out software interfaces that are meant to be used by people 8 hours a day for weeks at a time follow different design paradigms than stuff made for amateurs. I'd go completely insane if I had to edit a movie on anything simpler tho.
I like their TLI ideas, but I am honestly a bit alergic against designers who lack the phantasy of realizing that sometimes a UIs complexity is a reflection of the complexity of the problem it helps to solve in conjunction with the level of control you want to give to the user.
Steep learning curves should be avoided — sure — but sometimes they are necessary to shave of that extra second. Something that multiplies if you do it hundred times an hour.
Premiere is like vim: not for everybody, but if you wield it in the right way, there is not much that can beat it.
I found they were, like CLIs, all very similar.
Source: I am experienced in several nonlinear and linear video editing technologies from the 90's and early 2000's, since my father was in the videography business.
There are basically two classes of editors:
* "pro" editors, like Premier, and (old?) Final Cut Pro * "home" editors, like iMovie, Windows Movie Maker, OpenShot etc.
You want something from the latter category. The general idea is:
1) Add your source video file to a new project 2) Drag that video onto your timeline 3) Edit the timeline to crop your video (various methods depending on user preference) 4) Export your new clip
You haven't mentioned your platform, so lets give a simple example using the free, cross-platform OpenShot:
1) Add your source video file to a new project 2) Drag that video onto your timeline 3) Grab the edges of your video clip in the timeline, and drag them to crop your video 4) Export your new clip
Short YouTube video (not mine) demonstrating this visually (you don't actually need to select the razor tool): https://www.youtube.com/watch?v=P8zmqfXXS60
---
Is this an easy enough method? I think to get any easier than that, you may be looking at a purpose-built tool to do only the simple thing you want, rather than a general purpose editing tool.
---
edit: I didn't see your file format requirement. I honestly don't know anything about .gifv; it appears to not actually be a file format at all, but some tomfoolery that Imgur is engaging in? You'll have to export to an actual video format (say webm or mp4) and figure it out from there.
complexity is always relative but I think the end point here is that there's always room for simplification and shallower learning curves, even for advanced/pro users.
While there are solutions that both experts and beginners can benifit from (like Blenders 2.8 UI overhaul), everybody who has done every manual job ever might have learned that the optimized professional tool you used has a learning curve for a reason: when you know how to use it, it is literally faster and gets less in your way than the friendly intuitive and self explainatory variant of the tool.
The kind of dynamic scaling you mentioned is always desireable, but not always possible without introducing considerable complexity into a software — especially in complex domains like editing, audio or 3D the hard thing usually is to develop a language of adjectives and verbs the user can throw onto the objects they work with. And learning this can feel like learning a new language for a reason. And like with languages a simple combination of grunts and gestures might be enough for certain communicative goals, but sometimes it pays off to learn the actual developed language to really express what you want.
The most powerful software that gets in your way the least I ever learned had incredibly steep learning curves, but once you've got it, it felt like speeking a language you mastered.
We are literally commanding machines here — and problems of high complexity paired with a high level of control usually demand a very precise communication. So while I could e.g. imagine an editing suite which interprets your grunt and edits a bunch of videos for you using AI, you are still losing a level of control there: because the computer has to assume what you are unable to tell it. There is literally no way around it.
Ever wondered why the language used in the military, in an operation room or on a film set is so specialized and hard to understand for amateurs? It is because they need that level of control to communicate in order to get the desired result.
I think what's key here, and why I like the direction of the work in the linked post, is that none of the affordances of the UI they're augmenting -- the command line -- are being taken away,* merely made more visible based on context. I think that gets at a hole in the notion that UI complexity mirrors domain complexity -- in the case of Premiere, surely the entirety of what's on the screen doesn't mirror the complexity of the workflow you're executing right now, it's much closer to the sum total of everything you might ever do. Not that a UI based on progressive disclosure would be trivial or maybe even possible to implement effectively for something like a professional video-editing application, but it's worth considering whether something like that is merely a local maximum in the space of all possible UIs.
* I guess in the case where you know exactly what you want to do and the added context might distract or slow you down, that's an affordance being removed, but I think it's outside the scope of what we're talking about here -- especially because, given the scope of the command line, you will inevitably have to do something with it that involves an invocation that isn't right at the tip of your fingers.
And existing editing GUIs might very well be a local maxima — however we designers need to be careful in quickly condemning existing solutions that we don't understand by calling them "unfocused", "slow" or "ugly".
It is the responsibility of any designer to be more aware than the rest of tradeoffs like these — making it look good is merely a nice to have you can achieve as well. To decide that for a domain as complex as editing demands at least some degree of awareness of the common problems an editor needs to solve, as your software or UI will have to solve them as well.
Sometimes this comes with a learning curve, as your user will have to learn how to tell the computer what they want. They will have to learn some language that allows them to express this, if they don't want the computer to take the wheel and just assume what they want. And that very language is what makes it complex and hard to learn, and there is not much way around it. Might there be a different language that lets you express more things with better ease while beeing easier to learn? Sure. But will it still be harder to learn a language which allows you to express a lot, compared to a language which allows you to express only little? Yes - as well.
That beeing said: I they made all the right usability choices on their own thing there, my comment was more an aside stemming from my own values as a designer.
Annoyances are a bit harder to quantify, but they also add up over the weeks.
Sometimes it is just easier to fight the world.
I feel my drive to de-frustrate the world make me a better engineer/designer.
Another demotivating argument one might hear often is that building X, learning Y or using Z has no business value because there already exists something that you could do/use.
That argument makes sense if your primary concern is to solve a particular domain problem AKA you are a 'business person'. But a craftsman/engineer/designer etc. Your primary value comes from your skills and knowledge.
1. You can multiply the number by amount of users of your automation.
2. If your automation is valuable to others you gain social attraction or financial leverage or both/similar.
I'm a programmer first and foremost, so the following things are true in my case as well:
3. Automating a task can lead to learning valuable lessons about: automation itself, the task, any tools/languages you use to automate it. This cannot be encoded easily and is not deterministic. As a programmer learning new skills, improving my craft and gaining pieces of domain knowledge is my primary way of investment.
4. Enjoyment of doing the automation, non-deterministic value.
5. Avoiding suffering, the task might not be time consuming but "hard".
Good examples of 5:
* interfaces or synchronizations of values that are not failure proof, so you need to concentrate, which is taxing.
* the task is boring it itself (often the case)
* the task is associated with boring/stressful/generally negative things.
The other question is discoverability. I mean I'm sure vim is incredibly powerful, but none of the features are obvious and you have to trudge through two decades of websites to discover anything.
I've been unable to find out (actually I haven't really looked) how to use vim as a software developing tool (with basic features like autocomplete/suggest and error reporting)
I tried all modern ides, and while vscode is certainly awesome, i always go back to my vim :-)
However: the more expressive this language has to be and the more problems you should be able to solve with it in precision, the steeper the learning curve will get. And as with spoken language, there are hard to learn languages that let you express certain aspects very precisely and there are simpler languages that might be easier to learn but make it harder to express certain things (e.g. "You" in English vs "Du"/"Sie" in German vs. all the formal variablity of Japanese).
Vi is a text editor with an incredibly powerful language to edit text tied to keyboard keys.
Emacs is a lisp interpreter that's optimized for text editing.
They are not IDEs.
That said, vim and emacs can be in a way a component of a DIY IDE - you just need to put the work in and build it yourself. I exclusively use vim with a handful of useful plugins, scripts, and additional CLI tools in other terminal splits.
The terminal is my IDE.
(Of course if you're writing programs in Elisp, Emacs is a more tightly integrated IDE, but the success of Emacs, org-mode, Magit, and Amazon notwithstanding, Elisp is not a very good programming language. Also, if you run Emacs in a terminal, you can quite reasonably use it over a low-bandwidth, high-latency ssh -C connection, and it becomes good for remote pair programming, which is not true of running Emacs in VNC. I haven't tried running it in Xpra.)
Historically Emacs started up far too slowly and used far too much RAM to be convenient to use it in the way you're describing, as a text editor invoked by a larger IDE; I remember waiting over a minute for a new Emacs process to start up in the mid-90s. Nowadays it might be reasonable, but it still takes almost 4 seconds on this laptop, which I find to be a painfully long wait for opening a file. Also, Emacs's language-agnostic autocomplete M-/ works a lot better if you have a lot of files open in the same Emacs session.
Although there are packages that configure Vim to work the same way, it is more common to use Vim in the way you describe, as a component of the IDE rather than an IDE in its own right. And Vim has the great advantage that it starts up instantly, and the advantage or disadvantage that its equivalent of M-/ (^P and ^N) is buffer-scoped, so it doesn't matter if you have more files open.
That is one of the use cases for emacsclient/Emacs server.
As for learning VIM, it is a complex professional editor, and I personally recommend just reading a book about it.
>type :help<Enter> or <F1> for on-line help
This is not for show!
Now, I am probably not a "professional TV user"... but neither are 99% of people who use TVs. Even if most of the complexity of a TV is important to the few people who, say, install one as part of an IMAX-certified home-theatre setup, most people want a TV that "just works" and gets out of their way—even if it's working in a sub-optimal way! They want a remote that can 1. turn the thing on, 2. control volume on their TV and/or soundbar; 3. switch input sources; and 4. proxy through to menu around in the streaming boxes/game consoles/etc. they own; and that's it. You don't even need the setup button on there—you can get up and press that on the TV itself.
The funny thing is, by default, TVs both have more functionality, but actually fewer desired features, than what I'm describing. People tend to have to buy a ridiculous 100-button (or digital touch-screen) Harmony remote just in order to get "turn on the TV" and "menu around in your streaming box" on the same remote. Why?
Tooling this complex needs to provide controlled methods for controlling state, both in the tooling and that tooling's impact on the data it is operating on.
I set breakpoints and they were ignored.
https://stackoverflow.com/questions/4388192/eclipse-doesnt-s...
One time it was the top answer -- I had "skip all breakpoints" on. How it got on, I have no idea, since I did a fresh install of Eclipse pretty recently.
Yesterday it was still ignoring my breakpoints even though that was NOT on. Why? I have no idea.
So I still debug with gdb when the 'bt' command suffices. When I want to do more advanced stuff, I'll fire up Eclipse maybe, but I'm honestly loathe to do so.
We're able to fix typos and bugs and have it live-deployed as it's serving traffic. I recorded a gif here of what it looks like from the inside: https://twitter.com/amasad/status/1235742525056380929
Where is the fabled "hackernews hug of death" if a tiny container can handle the traffic? :-)
For reference the other HN post and the comments therein - "Let’s use Kubernetes. Now you have eight problems" - https://news.ycombinator.com/item?id=22491170
https://repl.it/python 404s and I rather suspect they support python. ;)
https://repl.it/languages/perl6 and https://repl.it/languages/raku both work. :)
They're both 2019.03.1 so their "raku" is presumably raku in name only. (Eg doesn't support $*RAKU etc.) Be nice to see it upgraded to a real 2020 raku.
This is really cool.
> Since we have a GraphQL backend, we know all the potential fields and arguments a client can use. By using an introspection query we generate a tree of commands/sub-commands that map onto their respective resolve functions. Now, to add a new admin command all that's needed is a new field on a GraphQL type.
And that's really really cool.
The main thing I see that could be improved would be a clear, simple underlying model or metaphor, a semantic layer that sits between the CLUI and the GraphQL backend, to unify and simplify the various contexts and languages and runtimes and whatever.
I've been toying with a UI demo that unifies GUI and CLI through a dialect of the Joy language. Everything you can do at the CLI can be done through the mouse, and everything done through the mouse has a corresponding textual representation as Joy code. It's inspired by Oberon OS and Jef Raskin's "Humane Interface" (among other influences.) I haven't integrated widgets (yet) because you mostly don't need them, mostly.
W/O getting into a lot of details, there are no menus nor buttons because any text can be used to activate any command and/or enter any data; there are no forms because the UI metaphor (Joy) is stack-based so you just put values onto the stack; and so on.
If I understand the idea, when you want to invoke an operation that requires four arguments, you first push four arguments of the right type onto the stack (by clicking them or something) and then you invoke the operation by clicking its name (maybe after typing it)? How can you tell when you have the right types of arguments on the stack for the operation — does its name light up? If you want to invoke the operation, how do you find out what the types and purposes of those four arguments are — do you mouse over the name? How are you handling undo — can you just revert to previous stack states, or is there a lot of important state that isn't on the stack?
> Do you have a demo or a DHTML mockup?
I do, but the project's in a weird state right now. It was in Python 2 (and that code should still work fine) but I'm transitioning to a Prolog implementation, and I haven't nailed down the [G]UI for that yet.
The original Python-based project is here: http://joypy.osdn.io/
The code on PyPI is old, the latest code is here: https://osdn.net/projects/joypy/scm/hg/Joypy/summary
There's some Prolog code in there under the "thun" directory but the main new project isn't published yet.
The Joypy code contains two GUI demos, one in joy/gui based on Tkinter (TCL/Tk widget lib), and the other in joy/vui based on SDL via PyGame that renders the GUI using low-level graphic primitives (blitting a bitmap font, etc.)
> If I understand the idea, when you want to invoke an operation that requires four arguments, you first push four arguments of the right type onto the stack (by clicking them or something) and then you invoke the operation by clicking its name (maybe after typing it)?
Yes, exactly.
> How can you tell when you have the right types of arguments on the stack for the operation — does its name light up?
The Tkinter GUI highlights commands when you hover: green if the command type-checks, orange if not (and it won't be run), and grey if the type-checker can't figure it out. (It's crude and incomplete, some details here: http://joypy.osdn.io/notebooks/Types.html )
The "vui" (visual user interface, a distinction w/o a difference; I suck at names) doesn't do that. It's meant as a model to be reimplemented later in Joy so I'm keeping it as simple as possible. It's basically just a text editor that only has to be good enough to bootstrap itself into something more like the Tkinter GUI.
> If you want to invoke the operation, how do you find out what the types and purposes of those four arguments are — do you mouse over the name?
There is a simple "open doc" command (that can also be activated directly from the mouse using "mouse chords", or from a function key), so you can type:
<Newline>[FOO] opendoc<Ctrl-Enter>
anywhere to get the docs on FOO command. The UI has a default system log
as the main user interface (sort of like a terminal; Oberon OS has one)
so I just print the command docs to that.Without getting off on a big tangent, Joy code requires a lot of documentation to understand (although it does become readable once you have some practice, like APL or Forth) but the code tends to be very concise, almost like haiku. (It's like Forth, you use lots of little definitions and build up a DAG, and refactoring gives what some call "semantic compression".) So basically you have to have detailed docs, but you kind of generate those as you derive new Joy functions. (Examples: http://joypy.osdn.io/notebooks/index.html )
(Have you ever used Factor lang? I really like how they have integrated hypertext docs in their "monitor" UI. I've often thought that the thing to do would be to write a thin Joy-to-Factor translation layer and leverage all their amazing work.)
I imagine a mature Joy-based OS+GUI would have a ratio of docs to code of 1000:1 or greater, and resemble an extended mathematical treatise (lots of prose and some equations.)
> How are you handling undo — can you just revert to previous stack states,
Well, the Tk Text widgets have an undo facility built-in (which is nice) but uh, I just store everything in a git repo, including the serialized ("pickled") stack. You can use any git tools you like on it. (There is as yet NO internal interface to history, although the TK undo is enabled for convenience its history is orthogonal to the git history. I have a lot of ideas about how to represent history to the users but they aren't in the demo yet.)
> or is there a lot of important state that isn't on the stack?
Nope. :-) I'm using a Continuation-Passing Style in the Joy implementation (combinators work by modifying the pending expression rather than recursive calls into the interpreter) so all state is either in the current stack or expression. (You can define new constant commands that are then effectively named variables stored in the dictionary, but you shouldn't.) This enables a lot of cool things, like easy concurrency, task migration, etc.
- - - -
BTW, your post on memory models ( http://canonical.org/~kragen/memory-models/ ) was very helpful to me, I read it just a few weeks ago! I'm working on a simple compiler for Joy and I had to read up on all that to decide how to do the tricky bits. (I'm going with the "list-structured memory" from SICP for now.) Cheers!
I really like how your notebooks integrate (judiciously chosen) execution trace display with explanation. I think this is something literate programming benefits a lot from. I wonder if there's a way to include a smooth gradient from specific examples like your V('80 P') to more general cases, either with abstract interpretation or a Bret-Victor-style overwhelming battery of data points.
I watched an Aaron Hsu talk from Functional Conf not long ago where he claimed that Co-dfns has a comment-to-code ratio of 400:1 or something, because his dissertation is the comments, and there are several pages of it per line of code. Having seen the glyphs in the talk, I haven't dared to open the dissertation yet; I'm afraid it may open a gate, causing cenobites to come out of xpdf.
I really like RPN calculators because of their immediate feedback — http://canonical.org/~kragen/sw/dev3/rpn-edit is one keyboard-driven prototype with a structure editor — but I think that while they reduce the gulf of evaluation, making it easy to see if the step you just took was the right step, they may expand the gulf of execution, making it harder to figure out what you need to do to get closer to your goal.
An extreme version of this, which is not RPN, is
InputStream s = foo();
return new BufferedReader(new InputStreamReader(s, Charsets.UTF_8));
where it takes considerable familiarity with java.io to immediately know how to get a BufferedReader given only an InputStream, because of the intermediate step via an InputStreamReader.Today I was thinking about the cisco IOS CLI described in https://news.ycombinator.com/item?id=22498665#22500151 — something I haven't used in a long time — and it occurred to me that LOGO or REBOL is close to being FORTH or Joy spelled backwards. Instead of reverse Polish notation, it's forward Polish notation, enabled by all the functions having fixed arity. So, if you're writing left to right, you write your code top-down, as in C or bash, instead of bottom-up, as in Smalltalk or FORTH. You've built a noun-verb system, like the Macintosh, while Unix and IOS verb-noun. Is one or the other globally more usable? I don't know! The Java above is hard for programmers new to Java to write, but it's verb-noun.
One thing that has occurred to me is that in purely functional contexts, in a verb-noun system, it might be reasonable to execute every type-applicable operation and display the results, maybe as a balloon next to the operator name; then the user need only select which of all the possible next states they want to go to. So, for example, if you have two numbers on the stack, you might have their sum, their difference, their product, their quotient, and the results of dup, drop, and swap, each displayed next to the relevant operator; then you can select the desired operator to go to that stack state. That seems like it might help with the gulf of execution, providing you with one step of lookahead. But maybe it would be more distracting than helpful?
But then, you could imagine doing the same thing with a verb-noun system, as long as all the arguments have reasonable default values so that you can somehow get useful visual feedback on the results even before you have chosen all the arguments; for example, for arithmetic operations like that, the default value might be λx·x, the identity function, so that you see graphs of all possible results.
I used to chat with Slava when he was first working on Factor (before he started working at Apple) but I'm embarrassed to admit I've never actually tried Factor. (Or Joy!) Is there a screencast of the hypertext features you mention?
What do you think about Cat?
Cheers!
> I'm happy my article was helpful to you.
It was just the thing! Very helpful. Thank you for writing it.
> I really like how your notebooks integrate (judiciously chosen) execution trace display with explanation. I think this is something literate programming benefits a lot from.
Cheers again. I find those traces aesthetically pleasing in and of themselves. I can imagine a (strange, niche) art gallery that had large prints of them on display. Jupyter notebooks have so many good things going on. (Not that they're perfect, but they hit a sweet spot IMO.)
> I wonder if there's a way to include a smooth gradient from specific examples like your V('80 P') to more general cases, either with abstract interpretation or a Bret-Victor-style overwhelming battery of data points.
I'm sure there is, there are so many possibilities. Just the traces alone could be animated or made into (partial) graphs (have you seen http://pythontutor.com/ ?)
Concerning abstract interpretation, if you squint a little, the Prolog code already does that. Markus Triska suggested using the CLP(FD) integer constraints for the math primitives, which was brilliant, so it's doing a kind of abstract interpretation. You can give it a completely general stack "type" (just a logic variable) and it will tell you, e.g. '+' is:
int(A), int(B) -> int(A+B)
and so on. It's also pretty easy to replace the main operators to get a
different (but related) semantics, and I'm pretty sure that relates to
what Conal Elliot's "Compiling to Categories".I'm not sure which Bret Victor thing you're thinking of, but it's easy to do things like evaluation over a domain (rather than a single value), or partial evaluation (again with specific values, domain, or logic vars.) And you can do that trick where you give it the result and ask it to generate programs (as in http://webyrd.net/quines/quines.pdf) and variations on that. I think it would also be easy to e.g. add slider widgets and have them evaluate expressions (possibly already partially evaluated for efficiency) when the user "sweeps" them.
Also, and this is more hand-wavey, I think there should be a way to use the traces to extract information about how programs unfold over time. What I mean is, the traces typically have clear initialization and completion phases with a loop or recursive function in between, those repetitive parts show up clearly in the traces, and it should be possible to overlay them on each other and find the static vs dynamic terms, and maybe do something with that information. (Unroll loops or create new versions that do less work or whatever. Hand wave.)
> I watched an Aaron Hsu talk from Functional Conf not long ago where he claimed that Co-dfns has a comment-to-code ratio of 400:1 or something, because his dissertation is the comments, and there are several pages of it per line of code. Having seen the glyphs in the talk, I haven't dared to open the dissertation yet; I'm afraid it may open a gate, causing cenobites to come out of xpdf.
Heh heh heh. Yeah, that makes sense if you're working in a system that allows for easy refactoring: code should approach the Kolmogorov complexity limit of the problem it solves as it ages, eh? Ripen instead of rot.
> I really like RPN calculators because of their immediate feedback — http://canonical.org/~kragen/sw/dev3/rpn-edit is one keyboard-driven prototype with a structure editor —
Okay that is freakin cool. I'm probably going to have steal some ideas from that if you don't mind? I like the idea of being able to edit and re-evaluate sort of like a spreadsheet. And making the structure of the expression visible like that seems like it would be very useful.
> but I think that while they reduce the gulf of evaluation, making it easy to see if the step you just took was the right step, they may expand the gulf of execution, making it harder to figure out what you need to do to get closer to your goal.
> An extreme version of this, which is not RPN, is
InputStream s = foo();
return new BufferedReader(new InputStreamReader(s, Charsets.UTF_8));
> where it takes considerable familiarity with java.io to immediately know
how to get a BufferedReader given only an InputStream, because of the
intermediate step via an InputStreamReader.That's where Joy seems to shine, it's been pretty easy so far to set up the context for a function I want to write and then derive an implementation in a kind of mathematical way.
> Today I was thinking about the cisco IOS CLI described in https://news.ycombinator.com/item?id=22498665#22500151 — something I haven't used in a long time — and it occurred to me that LOGO or REBOL is close to being FORTH or Joy spelled backwards. Instead of reverse Polish notation, it's forward Polish notation, enabled by all the functions having fixed arity. So, if you're writing left to right, you write your code top-down, as in C or bash, instead of bottom-up, as in Smalltalk or FORTH. You've built a noun-verb system, like the Macintosh, while Unix and IOS verb-noun. Is one or the other globally more usable? I don't know! The Java above is hard for programmers new to Java to write, but it's verb-noun.
> One thing that has occurred to me is that in purely functional contexts, in a verb-noun system, it might be reasonable to execute every type-applicable operation and display the results, maybe as a balloon next to the operator name; then the user need only select which of all the possible next states they want to go to. So, for example, if you have two numbers on the stack, you might have their sum, their difference, their product, their quotient, and the results of dup, drop, and swap, each displayed next to the relevant operator; then you can select the desired operator to go to that stack state. That seems like it might help with the gulf of execution, providing you with one step of lookahead. But maybe it would be more distracting than helpful?
I had that idea too. The Prolog code does that anyway to type-check (the interpreter is also the inferencer, because Prolog is awesome that way) so there's no reason to throw the result away rather than display it somehow. But with infinite undo you've got that tree of possible evaluation already, eh? It comes down to ergonomics.
> But then, you could imagine doing the same thing with a verb-noun system, as long as all the arguments have reasonable default values so that you can somehow get useful visual feedback on the results even before you have chosen all the arguments; for example, for arithmetic operations like that, the default value might be λx·x, the identity function, so that you see graphs of all possible results.
That would be pretty cool.
> I used to chat with Slava when he was first working on Factor (before he started working at Apple)
That's cool! :-)
> but I'm embarrassed to admit I've never actually tried Factor. (Or Joy!)
Heh, me neither. I want to use it just because it's so cool.
> Is there a screencast of the hypertext features you mention?
Dunno, but you can just download it, fire it up, and click "Help". It's nothing fancy, just a little mini-browser with hyperlinks.
> What do you think about Cat?
I looked at it when I first started with Joy but it wasn't quite right somehow. Slightly too complicated, or wrong emphasis or something, I forget.
I like Philip Guo's Python Tutor, and I used it a few weeks ago to show my girlfriend some algorithmic stuff, but (following Victor's Magic Ink) I think its mandatory interactivity is a significant drawback. To the extent that it's possible to visualize a program's behavior as a static image — perhaps a zoomable one — rather than an animation or a slideshow, I think doing so is an improvement. (In many cases it's adequate to just use a comic strip, as Victor did in his binary-search visualization in Inventing on Principle, or as you are doing with your V, but sometimes that involves too much compromise.) But Python Tutor is already tackling a very difficult visualization problem, and the static equivalent is an even harder visualization problem.
I enjoy Conal's work but I haven't read Compiling to Categories yet. I don't know much about category theory or Haskell, so I always struggle with his papers.
The particular Victor thing I was thinking about when I said "overwhelming battery of data points" was Up and Down the Ladder of Abstraction, but it also applies to, for example, the circuit example in Inventing on Principle.
I think Prolog CLP(FD) is less powerful than miniKANREN, except in the sense that you can of course implement miniKANREN in Prolog, but I'm no expert. I haven't seen an equivalent to Byrd's mindblowing quine-generation paper that uses Prolog instead of Scheme for either the implementation or the language being interpreted; I wonder if you could get some mileage out of that approach?
What you're describing about modeling traces of programs for a Turing-complete machine with a finite state machine is something I'd like to see explored more. Of course it's straightforward to produce a conservative NFA approximation of a more powerul automaton: whenever the automaton makes a decision based on information that's excluded from the NFA's state, the NFA makes a nondeterministic choice among the possible alternatives. So, given any possible mapping from the state of the more powerful automaton into some finite set of states, you can straightforwardly compute the NFA, and from that you can compute a DFA. Bjoern Hoehrmann's parselov takes such an approach to the problem of parsing context-free grammars, for example. (For better or worse, his favorite logic programming language is SQL.)
A difficulty I have with the programming-as-Kolmogorov-compression approach is that, at least in the case of Co-dfns, it didn't really speed up the process of creating the software; in fact, it slowed it down. It might speed up the process of understanding the software for other people, which is the major benefit in my view of the similar compression of algebraic notation for equations, but I haven't seen strong evidence of that, and I've seen weak evidence of the opposite — legions of programmers throwing up their hands at maintaining APL code, calling it unreadable, and flocking to alternatives as soon as they became available, such as VisiCalc, MATLAB, S, and Lisp, and their modern replacements such as Gnumeric, Octave, Numpy, TensorFlow, R, and Python. I guess I finally need to buckle down and learn an APL after 25 years of dithering.
It's possible that with better visualizations of examples, some of that perceived difficulty will evaporate.
Thank you for this wonderful conversation! Forgive me for not having responded earlier.
In re: visualizing program behavior I look forward to implementing something like an SVG rendering of the dataflow diagrams implied by Joy expressions. It would be easy enough to use Dot but I want something more like the railroad diagrams that e.g. git history tools often have for visualizing branches.
Long ago there was a wonderful website that showed 3D dataflow diagrams (hand-drawn I believe) that had recursion as data lines that went backward to earlier stages in the computation. (IIRC the demo was the GCD function.) I lost track of that, but there's a guy working on "generalized arrows" (in the Category Theory sense) that has something very similar.
In any event, the train yard would be static with data/cars flowing through it.
I don't know much about category theory or Haskell either, but in this case I kind of stumbled across the same thing, I think. I was writing a type inferencer in Python of Joy, and I realized I could use the stack effect comments as the stack itself, and just execute combinators, and that got me most of the way to full inference (it's still incomplete: looping generates one type per loop iteration, etc.)
In a nutshell, the point-free style allows you to swap out the categories that your expressions operate over very easily, and get multiple meanings: diagrams, circuits, types, values, incremental re-evaluation, and so on, from one expression.
In re: the quine gen, yeah I haven't tried it out much yet but the Prolog version of Joy can do that with "iterative deepening". I'm more interested in auto-generating and testing new semantics for existing functions that give greater performance. I appreciate the beauty of quines but I want self-tuning.
I actually got into logic programming from studying a Kanren in Python implementation a few years back. Now you can also implement Prolog in Lisp, so I won't quibble about power, eh? I like Prolog. I found that embedding (imperative, functional) Joy into Prolog was so elegant and so powerful that that, combined with the research on compiling with it, turned me into a complete Prolgo fanboy. So I'm biased. But in general I think it makes more sense to work mostly in the logical paradigm and only "descend" to the more imperative paradigm when the shape of your problem requires it than to camp out in imperative land with mere excursions to the realm of pure logic.
> Bjoern Hoehrmann's parselov takes such an approach to the problem of parsing context-free grammars, for example. (For better or worse, his favorite logic programming language is SQL.)
Ha! That's awesome! I'm going to have to look into him. You probably know that the relational model is the same as the logical relations that Prolog models, eh? In other words, SQL is Datalog, more or less.
> A difficulty I have with the programming-as-Kolmogorov-compression approach is that, at least in the case of Co-dfns, it didn't really speed up the process of creating the software; in fact, it slowed it down.
I think you'd have to ask arcfide to estimate how long it would take to write Co-dfns again. It sounds to me like he bushwacked through a lot of conceptual ground that hadn't been explored before.
I have just enough experience reading Joy code to credit the APL people when they say they can grok a page of line noise, the Forth folks report the same thing. "Intuitive" means "familiar" in computers (Jef Raskin.)
I agree that ease of understanding beats mere compression of code.
Thank you too! This has been great.
Router# configure ?
memory Configure from NV memory
network Configure from a TFTP network host
overwrite-network Overwrite NV memory from TFTP network host
terminal Configure from the terminal
<cr>
It's really quite a great experience.1: https://www.cisco.com/en/US/docs/general/Test/dwerblo/broken...
The difference in usability between the two was quite notable, exactly for that reason.
[1] Configure from NV memory
[2] Configure from a TFTP network host
[3] Overwrite NV memory from TFTP network host
[0] Return to previous menu
Enter your selection> |
For things that don't fit well into a hierarchical tree of selections augmented with bureaucratic forms — either because it isn't obvious what category you're going to find something in (why is "Preferences" on the "Edit" menu‽) or because it involves operations on more than one object at a time, or creating objects that don't exist yet — the improvement is zero or negative.This appears even in the above example: you can get configuration data from three places and send it to two places (running-config and startup-config), but only four of the six combinations of source and destination are available. If you want to overwrite NV memory from the terminal, you first "configure terminal", and when you're done, you use a totally different command, "copy running-config startup-config", to overwrite NV memory. And there's a third unrelated command to send a configuration to your terminal, "show running-config" (or, as you would expect, "show startup-config" or for that matter "sh start".)
When it comes to things like "ip route 10.2.0.0 255.255.0.0 10.1.0.2" I really don't want to be using the CLI interactively; I want to be using a text editor so that I can copy the line for 10.4.0.0/16 which goes through the same router and just change 4 to 2, and then I can diff the config with the config I'm setting on the other router and see if the differences are only the intended differences. But if I were using it interactively, it would sure be nice to be able to move the damn cursor field by field rather than character by character and see some kind of real-time indication that 10.1.0.2 is not a valid netmask if I get the order of fields wrong.
Aside from it I've run into Xiki [4] that seems to bridge the gap on multiple levels between GUI and CLI. GUI to bring the discoverability and CLI to keep it scalable.
[1] https://fishshell.com/ [2] https://github.com/jethrokuan/z [3] https://github.com/jethrokuan/fzf [4] https://xiki.org/
Apple’s first Unix copied that in 1988 (http://toastytech.com/guis/aux3.html)
Powershell has ‘Show-Command’ which also is similar (https://docs.microsoft.com/en-us/powershell/module/microsoft...)
I think PowerShell generates the GUI, while MPW commando had human-designed dialogs (and, for complex commands such as compilers, sub-dialogs)
I think this is worth copying in modern Unixes. Those GUIs make it way easier to use rarely used flags than man pages.
https://docs.microsoft.com/en-us/powershell/scripting/compon...
I recently switched to VS Code for creature comforts that come from a much large ecosystem and using more modern OS affordances. VS Code gets close but not quite as pleasant as Emacs.
Libreoffice has a feature request for such a function [1].
[1]: https://bugs.documentfoundation.org/show_bug.cgi?id=91874
Not being sarcastic, even - it's a pretty powerful approach that deserves better, unfortunately distribution of knowledge in Computing Science, especially historical knowledge if you never encountered it yourself, is pretty hard.
I pay homage to the Lisp community w/r/t programming interfaces in this post: https://amasad.me/disintegrated
There's some documentation about 'Commands' in CLIM II here for example: http://www.lispworks.com/documentation/lwu41/climuser/GUID_1...
Commands are first class objects which live in command tables and which CLIM can look at to generate bits of UI and allow parameters to be specified. Central to this in CLIM is the idea of presentations - where domain objects are 'presented' onto the screen and the link to the domain object is maintained. That way you can invoke a command on that object in various ways, for example you can type a command name and then click a presented object which is acceptable as a parameter.
The Symbolics S-packages used these concepts to make (I presume) powerful 3d modelling programs back in the day (I haven't used them): https://www.youtube.com/watch?v=gV5obrYaogU - sorry for the poor video quality.
https://twitter.com/rainerjoswig?lang=en (lispm on here) sometimes posts interesting things about Genera
What I would like to see is something like CLUI to be integrated with an IDE or a productivity tool like Adobe Photoshop. PyCharm/JetBrains already embraces the keyboard with double-Shift => Search Everywhere, and other similar shortcuts. Similarly, Photoshop would benefit from keyboard interaction for common tasks. We already have single-pixel nudge actions via the arrow keys, but a CLI prompt you could conjure up and type into would be a game changer for actions that require repetition and precision.
That is, rather than bringing GUI to the CLI, bring CLI to the GUI.
What kind of autocomplete does bash have? Do I need to enable it? I've just tried bash 5.0.16. I don't see any. For example, I've typed `pw`, but `pwd` was not suggested to me.
(I know there's Tab-completion, this is not what I'm talking about. I'm looking for automatic completion. Similar to Google's search suggestions and CLUI demo.)
bash: no auto suggestion at all, Tab twice to see a list
fish: shows single auto suggestion, Tab once to get a list
zsh + zsh-autosuggestions: looks similar to fish behaviour
Is there some combination of shell/plugin/terminal that provides multiple auto suggestions?
Out of curiosity, how often do you use Photoshop, and for what tasks?
One more bit of prior art that might be interesting to you: I worked on the Mozilla Bespin project a long time ago with Joe Walker. Joe was also really big on the command line idea for much the same reason and created [GCLI](https://github.com/joewalker/gcli/blob/master/docs/index.md).
GCLI ultimately landed in Firefox Developer Tools, but I don't think it's in the current shipping version. Funnily enough, I just found a video on YouTube of me demoing the command line in Firefox Dev Tools: https://www.youtube.com/watch?v=YwOwJ1_JaKE
The state of the art in web UIs has definitely moved forward, and I'm really happy to see more experimentation with graphical command lines.
My dream would be to have something like built into an IDE so I could save edits directly.
I do still think it's a valuable interaction style for being able to activate less-frequently-used features all from the keyboard. It's possible that the fact that web browsers also have the JS Console is just too much, because the JS Console has a command line that people are familiar with. The interaction model is very different, though. GCLI made it quick to type commands, whereas the JS console requires valid JS.
https://en.m.wikipedia.org/wiki/Common_Lisp_Interface_Manage...
I think this idea can be refined further and made more and more robust and is a design pattern in the right direction. With more and more percentage of the population heading in coding-friendly direction I see this as a very viable next step.
I do see some problems with it that were not addressed. The way the demos are setup are by definition an NP!=P problem. It is easy to verify you found the right command, but may be fiendishly difficult to navigate the tree to get there. Menus with sub-menus having sub-menus at least makes it visually clear which paths you have not taken and allow retracing your steps. Something akin to Ctrl-R in shells may be needed to allow you to type certain keywords to find all possible actions.
Options and parameters are not part of a decision tree as they don't specify a logical action that will follow, they just change the action. Those parameters need evaluating the entire progress in the tree to be able to suggest a next available parameter, option and action. Try it with something like ffmpeg. Modelling this to work in a CLUI will evolve into a hard problem very quickly.
The more actions, options, parameters I add as a user the more important it becomes that I can backtrack and correct mistakes. Corrections may or may not have consequences for the position in the tree I already choose. Starting over even from there might not be the right solution in terms of usability if the correction does not necessitate it.
Taking a sprawling interface like that of git and making it work in a console window in Emacs is an idea that bears repetition across other tools, e.g. tar.
Would I'd the time to work on such.
You could start an emacs process just in order to use Magit -- you wouldn't have to use it for anything else. However, I totally understand that you might well not want to mess about configuring emacs to load magit and working out how to start it etc. How about these?
"Because the tree is hierarchical, you might think that it actually resembles a large dropdown menu. The difference is that search is built directly into its navigation, not just pointing and clicking. One clear improvement that could be made is being able to search for any subcommand without having to specify its parent command first. That way you can access any deeply nested information instantly, similar to spotlight search."
IntelliJ also, more recently, with its actions input.
https://www.youtube.com/watch?v=Hgz2kqm0rsY
20 years ago I remember seeing a person drawing mechanical plans using a lot of keyboard and just a bit of mouse. That seemed really productive.
In my personal experience, the search functionality was extremely useful when using for the first time one a complex application such as Gimp or Libre Office. Unfortunately all extra functionalities (autocomplete, for instance) required the applications to explicitly support the HUD and few (any?) application added the necessary code once GNOME 3 appeared.
[Edwin Brady - Idris 2 - Type-driven Development of Idris]
My idea originally came from using ssh on my iPad and thinking it would be cool if more native controls were used over RPC instead of text to display what was happening on the server. Then I could more easily navigate the responses and maybe even if there was more intelligent autocomplete which a UI on iOS could take advantage of. Or maybe interactive confirmations and stuff (similar to what was Demo’d). And also then provide an easy way to edit files using either a remote editor or a way to sync changes being done in a local editor. Kind of how vscode seems to do it (e.g. a remote service handling the work)
The one thing a system like I’m describing would still need is the ability to switch from this rich interface back to the terminal when using things like tmux, curses, or vim/emacs because obviously those things still work well.
But the cool thing was realizing that this would also be great on the desktop. Looked into some terminals like Hyper thinking maybe I could hack those up to get a proof of concept for myself, but can’t find the time. And obviously it wouldn’t work for the iPad where I really wanted it.
Something like that would lower the intimidation factor for beginners even further.
[0] https://github.com/railsware/upterm [1] https://github.com/Inlustra/hyper-autocomplete
Also, at least some of the scaffolding for CLUI seems to be available at https://github.com/replit/clui
EDIT: I would like to point out that I've only been in the industry for 6/7 years so it's not like I started my career where this established environment was the only choice.
The fish shell does much of this as well but is not as attractive.
I think this is a corollary to Greenspun's Tenth Rule ('Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp'): any sufficiently powerful UI will be an ad-hoc, inextensible, inconsistent, weaker version of Emacs.
And thought provoking. I find myself increasingly being annoyed by GUI's with their rich interfaces. An interesting project is lazygit which uses gocui. For me it is useful and appealing alternative to the command line git. With each pane you press a meta key to get list of commands for the pane, and it would be interesting to see a mash up with replit somehow.
For those unfamiliar, modern Office versions use ribbons instead of menus. Ribbons have a few tabs like home, layout etc. The tabs change depending on what object you're interacting with, so i.e. if you're editing a pivot table in Excel, you get two new tabs for working with pivot tables. That means you only see the options that are actually relevant to you. Each tab has buttons separated into groups. So, there might be a "alignment" group with "left", "center", "right" and "justify" inside. Most buttons have detailed descriptions of what they do and multi-layered, visible keyboard shortcuts that activate them quickly. Some even have an additional drop down for more options, so i.e. the "view" button in Access might switch you between the two most common views when clicked, but you can expand it and select a different view if need be. The latest office versions also have a search field that allows you to find any command, no matter what tab it is in. It has autocomplete, so typing piv usually shows you "pivot table" as one of the first suggestions.
I use Excel and Access pretty often, and do some moderately complex things with them, but I almost don't use the traditional ribbon at all. I use shortcuts for the commands I need very often, and search for the rest. If I don't know how something is called, I go through the commands on the relevant tabs and find it eventually.
I think this kind of UI scales pretty well. MS Office apps are pretty complicated and packed with features, especially the pro versions, but I think that UI paradigm is pretty scalable and nice for users.
The ribbon in MS Office came along roughly at the same time as 16:9 and 16:10 screens (on laptops in my memories anyway). Already on a 4:3 screen, WYSIWYG editing wastes much space on left and right of the screen, to show paper margins and page limits. And that goddamned ribbon eats up all the top of the screen, making you see only a limited band of what you could see on that very screen. Had no one the idea to make the ribbon a vertical tool bar on the left or right, like in Photoshop/Gimp and a number of other tools? Such a feeling of UI failure at the time. At that moment my computers were already all running Linux anyway, so I've never used it more than a few times on a coworker's machine.
Now I no longer use WYSIWYG software. Text editing with the WYSIWYG paradigm feels superficially seducing, until you realize it actually hides the actual document content. How many times has Word shown some items in a bullet list with a different size without any visible reason ? Or in Google docs one bullet horizontally misaligned? Why? No one knows.
When editing text, seeing how the final document would look like is not that important. It's more important to know the state of what you're editing. With markdown or asciidoc what you see it what your document actually contains.
On top of that, WYSIWIG assumes that there is one final document appearance, which is just not true for a digital document in a digital world that could be rendered countless ways in different styles (unless your workflow targets documents in try-to-mimick-paper-form, like PDF, until that changes).
Sounds like walking the tree of a REST api... potential CLUI framework for REST?
That being said code completion, contextual help and form-ish guis give a better user experience.
The most used UI element is a button and thereafter is the search input.
(mad props to ~donnemartin for the implementation!)
(And unwanted Bing search results that open in Edge, but that’s Something else)
Windows is 15+ years behind Mac in simply implementing menu search inside programs.
Part 2 of 4721: Let us now persuade you there is a better way by demo'ing a souped-up terminal window that helps non-specialist Unix enthusiasts enter a record into a database.
???
Part 4721 of 4721: As we have clearly shown, our realtime video-editing CLUI application is more approachable, discoverable, interactive, and scalable than Adobe Premiere.
I think the technique of creating UI forms based on GraphQL metadata is going to be key for building the admin tools of the future.
Command Line Again SHell
I think the idea they have is awesome. Managing servers with this would be a dream!
This includes parameters, flags (with documentation), context (eg files in current directory).
Autocomplete is available for most commands on modern Linux installations.
But yeah, agreed that pursuing this path would be less effort and get 90% of the way to the goal.
Selenium comes to mind..
think of: the website (and search results) updates in realtime with every letter you type
Its a bit daunting at first, and can be overwhelming if you don't really have the patience to dig into it and find where everything is, in terms of grouped functionality.
However, one key thing made learning to use REAPER smooth as butter - the '?' key. This shows the "Action List", which is a list of all the things you can do in REAPER, in a text list .. so I can quickly type '?' - then 'section' and find all the actions related to sections. VERY useful, and quite a great way to explore the periphery of features I would otherwise not have discovered.
In fact, its the very first thing I teach anyone I'm introducing to REAPER, that they should use. I'd say, without this "text-based UI", the rest of the program wouldn't be nearly as accessible. A lot of that has to do with the fact that the REAPER developer seems to have a Power > Eye-candy attitude about the UI design - its clean, minimal, and functional when you first get started - but the UI is also fully tweak-able such that once you start getting productive with it, you find ways to make the GUI really shine (track colours, Layout customisations, etc.)
Anyway, I think its pretty interesting that the entire UI is accessible from the text-based '?' Action list query... I wish more programs would adopt this abstraction.