What are your opinions on "replacement" programs for core utilities - Programming On Unix

Users browsing this thread: 1 Guest(s)
z3bra
Grey Hair Nixers
Warning: wall of text ahead ! TL;DR at the end.

I've been using vis full-time to replace vim for the last few years, and can't see myself switching back to vim now. I'm convinced vis is more powerful than vim for text editing, for a couple reasons. Before I get into these, you must first understand how I used vim:

No plugins. I was one of those weirdo that though vim was best used with no plugins, in order to truly master the editor. My .vimrc was only a few lines, mostly to disable syntax HL (personnal preference), and set sane default for my needs. I made heavy use of macros for bulk edits, and though it was the best feature an editor could have to make arbitrary edits in a large scale way. I used recursive macros like a boss and looked down on everyone using plugins while not even trying to do stuff directly with "vanilla" vim.

In my quest to minimalism, I found vis(1) which was announced on the suckless mailing list, and advertised as "90% of vim features, with 10% of the code". This sounded delicious, and I started using it. Despite some bugs, it filled the promise, and some missing stuff were on the way to get implemented (like macros), so I used it more and more alongside vim, which I only used for some specific use cases (like digraphs, macros, which were not builtin at the time). The git log of vis was showing up new features and fixes every week, making it even more usable and powerful.

I spent more and more time in vis, loving it more and more everyday.

Then a new feature came in: sam's structural regular expressions. This is when vim's editing capabilities started feeling painful to me.

Sam is a Plan 9 text editor built around the "structural regular expressions" concept. To put it simply, you don't edit a full text buffer anymore, but rather small portions of it, that you pre-select using regular expressions. Then your commands will be applied to the "dot", which is your selection. As an example, take the following buffer:

Code:
Hello there !

This is a simple text, that you'll want to edit. I know you want it !
There are multiple lines, that you might want to mdoify.
We'll see how simple that really is with vis(1).

Let's first fix that ugly typo. You'll first need to set the "dot" (current selection) to that word. Then, you can apply a command to this selection ('d' for delete, 'c' for change, 'i' for insert, … You know them as they somehow match ed and vi commands):

Code:
:x/mdoify/ c/modify/

The 'x' command sets the "dot" using a regexp: then the 'c' command will replace the "dot" with the provided text. The above command is similar to the "substitute" command in vi, except that it's actually made of two separate commands: select + change, which is much more modular. Note that commands are bound to the same keys as the letter commands, which means that the above change can also be done interactively with:

Code:
:x/mdoify/<CR>
cmodify<Esc>

Let's now show how vim and vis differ for a few use cases.

Using the text above, I want to do these 3 tasks:

1. add "really" before all occurence of "want" (prepend)
2. emphasis "really" by uppercasing it (change)
3. delete word "simple" on line 3 (delete)

With vim command mode:
Code:
:%s/want/really &/g
:g/really want/s/really/\U&/g
3s/simple //

As you can see, vim leverages on the "substitute" command to do all three "verbs": prepend, change, delete. This doesn't follows the "vim grammar" that makes its normal mode so "powerful". But anyway, vim is not made for command line edition, so let's see the same edits in normal mode (commented out):

Code:
qq/want<CR>ireally <ESC>eq2@q
|        |            ||   `- terminate + replay macro 2 times
|        |            |`- move past "want", to avoid performing the change twice
|        |            `- insert 'really ' before it
|        `- lookup the 'want' string
`- start a macro in 'q' register

qq/really want<CR>gUeq2@q
|               |  |   `- terminate + replay macro 2 times
|               |  `- uppercase current word
|               `- lookup the 'really want' string
`- start a macro in 'q' register

3G3wdw
| | `- delete current word ("simple")
| `- go to 3rd word
`- go to line 3
[code]

This makes a good use of macros to edit this, and to be honest, (like
with most macros…), I had to do multiple iterations to get it right
(for example, to move past the current search and avoid having "really
really really want").

In the end, experienced vim users will use a mix of both solutions (macros + substitute command) to get the best results.


Let's see the same, with vis now ! (note that the normal mode one will also work in vis "as-is" because it supports vim-style macros).

[code]
:x/want/ i/really /
:x/really want/ { x/really/ c/REALLY/ }
:3x/simple / d

As you can see, this is fairly different from vim. For each action, I use the corresponding sam command (insert, change, delete) rather than the "substitute" command everytime.
You'll note that I selected "want" only once (":x/want/"). This is because all commands apply to the whole buffer, unless specified, and the 'x' command (which means eXtract), will select ALL occurence of the search, so the command specified afterward applies to each occurence, kind of like a "for" loop.
For the last command, I limited the 'x' command to like 3, so it only select occurence of the word "simple" on line 3.

Let's see the normal mode way of doing it, using multicursor instead of macros:

Code:
/want<CR>^N^N^N<Esc>bireally <Esc><Esc>
        | |   |    |        |         `- switch back to normal mode and delete the additional cursors
        | |   |    |        `- insert word "really before the current word
        | |   |    `- switch back to normal mode (note, there are now 3 cursors visible)
        | |   `- select the next two occurence of "want"
        | `- select current word ("want") and switch to visual mode
        `- move cursor over the "want" keyword
        
/really<CR>^N^N^Ngu<Esc><Esc>
          | |   | |         `- switch back to normal mode and delete the additional cursors
          | |   | `- make all selections upper case
          | |   `- select the next two occurence of "really" (note, you can "skip" a match with ^X instead)
          | `- select current word and switch to visual mode
          `- move cursor over the "want" keyword

3G3wdw
     `- same as vim, it's simple enough I guess !

So the way you'd do it with vis is by using multiple cursors. There are multiple ways to create them, and the ^N used here is not the most efficient (and you can't "repeat" it by using 3^N for example, it's a feature limitation). This is however much more easy to figure out what's going on, because all selections are updated in real time. This also make the selection interactive, and you can decide for each match wether or not to include it (hence why I didn't search "really want", and just "really", because I can press ^X to skip the one I don't want to edit).

However in this case, you'd rather use ":x/want" to create all multiple cursors at the same time, which is much more efficient. The biggest avantage to it hover macros is that you get a realtime feedback of the changes you do. And of course, the "undo/redo" work just as expected: per cursor. Same goes for yank/paste ! Each cursor has its own register for yanked text.

So yeah, I've switched to vis(1) fulltime, and whenever I have to use vim instead, I am disapointed. I miss the better commands, and I miss the multiple cursors. And just in case you're affraid to "loose" your vim editing skill: don't be scared, you won't loose them. After years of using vis, I can still kick some ass with my powerful vim editing skills. Just less efficiently than with vis ! It's kind of like typing again on QWERTY after years on DVORAK. You can still do it, but it feels awkward…

Oh, and did I mention that vis has a '|' command, to use external tools to edit selections ? Try to figure out the following:

Code:
:x/caesar/ |tr a-m n-z

Ok vim has it built-in… The real question is: WHY BUILTIN ??!


TL;DR: vis multicursor and structural regexp are a must, making vim feels old and clunky in comparison.

Edit: Screencast of these edits on both vim and vis : http://0x0.st/i7cA.webm.
Note that I forgot mid edit how to change the primary selection when multiple cursors are used, hence the popped up manpage (answer: ^D to cycle through selections, note the bold 'y' at the end of the word, indicating the primary cursor position).


Messages In This Thread
RE: What are your opinions on "replacement" programs for core utilities - by z3bra - 30-11-2020, 08:48 AM