But, of course, it doesn't. I find the conclusions of these types of articles totally baffling. "But it's not pretty under the covers!!" Who cares? It gets the job done fast enough for 99.9% of real world users who will never know it wasn't implemented in an "elegant" manner.
This article has it exactly backwards: you shouldn't use technical implementations to rule out features—instead, you should use features to rule out technical implementations. The users care about what your program can do, not how you implemented it—and certainly won't be sympathetic if how you implemented it hinders them from accomplishing what they're trying to do.
The author's point is that "smart" editors (Vim or Emacs for instance) already have macro systems and block/rect edition features which subsume and go far beyond multiple cursors, and furthermore ("if you don’t buy my arguments about multiple cursors being tasteless") multiple cursors play hell on gap buffer editors, therefore:
> get more comfortable with your editor’s macro feature. If your editor doesn’t have a good macro feature, get a new editor.
They also link to an essay[0] pointing out numerous ways in which multiple cursors don't play well with advanced editor features (using Vim for the demonstration but the point likely works just as well for Emacs).
Sure you can also take the inverse tack and switch to an editor implemented in such a way that multiple cursors is efficient, but… is multiple cursors really the feature you want to stop at?
Macros live in a different (albeit adjacent) space to multiple cursors.
When you record a macro, you need to be careful to encode commands that will work well wherever you apply it. That means skipping forward by a word rather than a fixed number of characters, sometimes doing fiddly operations around word and whitespace boundaries to make sure the cursor is in the expected position for the next step. When multiple cursors are used to emulate macros, you get a wysiwyg experience, rather than "programming" the cursor and finding out later during playback that it did the wrong thing.
Multiple cursors are also used as a replacement for text search and replace; sometimes the operation could be performed using a symbolic rename, sometimes it could be done by search and replace with live preview, but not when you want to skip some instances.
Probably 95% of my personal use of multiple cursors is for local refactoring, e.g. switching out a hash for an object or vice versa, where I want to change 'foo.bar' to 'foo[:bar]', but sometimes (electively) 'foo.fetch(:bar)'. Multiple cursors let me do both the selection and the editing in a wysiwyg fashion, where neither macros (typically with a 'find next' operation recorded last) nor a complex search and replace with capture group and interactive replacement are nearly as pleasant.
FWIW, for many years I used Borland IDEs and almost the only tool available for complex manipulation was keyboard macro record and playback (I spent probably 15 years only using keyboard macros). These days, though, the combination of synchronous editing (iedit mode in emacs) and multiple cursors have almost completely replaced my macro usage with much more usability due to the live feedback.
> Multiple cursors are also used as a replacement for text search and replace; sometimes the operation could be performed using a symbolic rename, sometimes it could be done by search and replace with live preview, but not when you want to skip some instances.
The Medium article about multiple cursors was from a Vim-centric perspective (in contrast to the linked article here, which was Emacs-focused). And in Vim, you'd do this with `n` and `.`. For example, `n.n.nn.` means, "change the second occurrence, too, and the third, but not the fourth, and do replace the fifth".
Multiple cursors is no faster, and since you mentioned the benefit of not needing to carefully plan ahead (which I also think is important[1), I'll leave you with the observation that multiple cursors requires more planning than `.`. With `.`, the following thought process is valid:
"Let's change this. Oh! And do these other ones, too."
Compare to multiple cursors, where you have to don't have to plan as carefully as a recorded macro, but you still have to do some planning, because you have to start out knowing that you're going to change multiple things and then marking them before you make any change.
So the spectrum looks like:
# Recorded macros—requires lots of careful planning
# Multiple cursors—requires little planning
# Replay (`.`)—requires no planning at all; can fit your stream of consciousness
That's true if your edit is a single vim command, but if you're executing a few different ones at each location, . will only repeat the last.
Hm, it strikes me that it might be a cool feature to interactively select as many of the last few commands you gave as you like, and copy them to a macro register. It seems like it wouldn't be too hard to implement, seeing as the commands you make are already stored in the undo tree.
Reading the "why you don't need more than one cursor" article reminds me a lot of people who say things like "why would you need anonymous functions in a language? If you're making a function, then define it, and call it." Where the author says:
> The ultimate feature that comes with vim is, that you can edit and save these macros for your next vim session and even add a key mapping.
They almost entirely miss the point of the feature. 99% of the time when you're editing with multiple cursors, you're doing a unique thing which would be meaningless outside the context of where you're doing it. The ability to save the macro misinterprets the flexibility to do exactly what is needed at the moment.
Your comparison to anonymous functions is not apt. A language that implements higher order concepts like anonymous functions adds more power to the language. But on the spectrum of power, multiple cursors are not a more powerful form of macros. Macros—Vim's, at least—are higher order than multiple cursors. (Note that when I say "macros" here, I'm going along with the premise of the Medium article where the ability to replay the last edit using `.` is also considered macro use.)
Second, the ability to save a macro doesn't make macros less flexible. It's not as if you have to pay for it whether you use it or not. If you don't want to save it, then don't; but it's there if you want the option.
The claim wasn't that it makes macros less flexible. Just that the "ultimate feature" isn't very important to many people, and thus no reason to weigh macros over the (to some people) more intuitive workflow using multiple cursors. It's great that macros are a thing and have their benefits, I wouldn't want to remove them from editors, but "you don't need intuitive feature X, just use Y which is even more powerful instead" isn't a great message to users.
(Something I've been missing in this discussion: are multi-cursors to slow for users in practice, or is this technically slower/"less efficient"?)
(and for the side-discussion about the function example: Doesn't the extra power in the function case comes from being able to pass and dynamically create functions, not from the fact that they are anonymous? E.g. in Python, lambda functions really just save a few characters over using local named functions? Am I missing something?)
> The ability to save the macro misinterprets the flexibility to do exactly what is needed at the moment.
This makes it sound like a +1 for multiple cursors and and a plus null for macros/replay. You could argue that the wording is just so and doesn't actually claim that macros are less flexible. But the reality of the situation is that macros are +1 and multiple cursors is plus null, and the gestalt of comment I responded to doesn't convey that. That is, in all the cases where multiple cursors shine, Vim's native features are, at worst, on equal footing, and there's a non-zero count of cases where the inverse is not true. However, someone who hears the argument in the message I responded to might come away feeling that the opposite is true.
> "you don't need intuitive feature X, just use Y which is even more powerful instead" isn't a great message to users.
This, too, sounds like a crafted message—that Vim's native approach is missing something, and that advocating for e.g. repeat instead multiple cursors is shortsighted (somewhat reminiscent of [1]). The implication tends to be that the alternative might be more powerful but less intuitive or require orthogonal thinking. And there are cases in computing like that. Plenty. But using repeat instead of multiple cursors is not one of them.
Fair enough, on re-reading I guess your interpretation of that line is just as likely as mine.
I still argue that macros are missing something UX wise. It's a matter of preference which style you like better for specific problems, and I haven't seen a good argument for why only one of the two should be present. I don't think the fact that macros can fulfill the same function is a good argument. Them being more powerful IMHO isn't either, it just means that when multi-cursor editing fails someone preferring it, they still have the option to use macros then.
I haven't actually tried multi-cursor editing in emacs - if it is unusably/annoyingly slow, then the article would be interesting as an explanation for why that's the case, but its failing to establish that context.
If it's not, it's still interesting from a theoretical perspective. I think it shouldn't argue against multi-cursor editing the way it does.
Presenting the option of using a macro is fine, explaining the benefits of it is great, dismissing multi-cursor editing as
> tacky and modern
is totally unnecessary. And unrelated to an article about implementation details. Write "Why you should consider learning about macros", make a case for them that's unrelated to "our datastructure doesn't like the alternative as much".
EDIT: to address the quoting: It wasn't my intention to look like I'm making up quotes, I need to think about a different way of marking these up it seems. I try to put actual quotes on new lines.
If emacs is so smart why is its macro recording that everyone loves totally invisible and thusly awkward to work with?
People like multi-cursors because their behavior is very stable and obvious. Macros have very unpredictable behavior except on lines that precisely conform to the shape of line you used to specify them.
And buffer narrowing/widening isn't a solution. You can specifically play the macro over cursor lines (it is a "good practice" to C-a at the start of a macro to help with this), but it's many more keystrokes.
It may be "all hat and no cattle" as the author says, but I have uses for hats and I've got no facilities to keep or slaughter cattle.
They're no more obscure than the rest of emacs (which isn't a great starting point!) but everything comes down to keybindings in any text editor, you can map them to any key you want.
It seems you've completely missed the point and in so doing have focused on the most trivial set of keybindings for macro usage. Why do you think this conversation is about keybindings? Who even mentioned them?
Cool, you can start and record a macro. What does the temp macro do on this line? On a different line? Does your undo stack flip over or through the macro? How do you run the macro on lines with a specific suffix?
Because macros inherently make a big blob of actions and turn them into a single action, they're inherently more obscure than multiple cursors.
The funny part is of course that macros are dictated in emacs, not programmed. So what the multi-line cursor is doing is essentially showing you the results of a macro and letting you interactively work with it visually rather than deny you that option.
Macros have uses, but Swift multi-line editing is by no means their strong suit.
The important part of multi-cursor editing is the visual feedback. It means that the user doesn't have to fully understand what is going on before using the feature. And more importantly, there is no need to plan 10 moves ahead.
I thought this article was going to be about mouse cursors. The story there is even worse. We've been stuck in a chicken-and-egg situation for a few decades now.
There isn't a single mainstream OS that supports having multiple mouse cursors that I know of, and even if it did, not a single program expects it either - most would break. The closest we have is on-line editors that can have multiple users like Google Docs, and that's not single screen.
And you may be thinking "yeah but why?" and I wouldn't blame you, but that's just because you're not aware of how how much our current input devices limit us and how they are based on a flawed model of handedness.
Yves Guiard proposed a model in 1988 that argues the dominant/recessive model of handedness is wrong: instead, we constantly perform complicated asymmetrical tasks, with one "coarse" reference-frame hand and a fine-tuned "zoomed-in" hand (the latter being considered the dominant one)[0]. Later research has only backed this up (note that the linked paper has over a thousand citations).
When keeping this asymmetrical model in mind designing our input, things tend to just "feel" right. I guarantee you that the best two-handed input methods you use all follow this principle: even if not applied consciously, any two-handed interfaces converges to it. Simple case-in-point: remember 3D shooters before WASD + mouse? WASD = reference frame hand, mouse = fine-tuned input hand. Gamers just intuitively discovered this on their own. In fact, look at button placement on gamepads in general: movement ("frame of reference") on the left, action buttons on the right.
Bill Buxton[1][2][3] did really cool experiments with these ideas and then... well, nearly nothing. And I really believe the main reason is a lack of technical freedom to experiment: even if someone does manage come up with a wonderful intuitive, fluid bimanual interface that isn't limited to a keyboard, a mouse and maybe a touch-screen, who is going to be able to use it on their laptops or desktops?
I'd like to experiment and the fundamental requirements to do even that are missing. Even multi-touch is barely going to help: you cannot tell which hand belongs to which touch-point.
Fascinating. Are you familiar with any other ongoing research?
I would imagine that a touch scroll pad like in the linked video would be a useful thing to have on the left hand side of a keyboard. I could use it to navigate through a document quickly and use the mouse to pick my target.
I haven't explicitly kept up after graduating from my interaction design masters, but in general the alternative inputs being researched for VR work around two-handed input. Leap Motion for example can distinguish both hands (although often it regresses to "one hand is the touch-menu, the other taps on it").
Games and input devices for games also always design around bimanual input, even if rarely consciously.
Side-track: something almost nobody noticed when the Wii came out is that it's wiimote/nunchuck setup works both for right- and left-handed people. I'm left-handed and I automatically switched to a left-handed input method for my games without even thinking, for the first time in my life! I didn't even realise this until a few months in myself!
And yes, I completely agree with you! Something I forgot to mention is that for certain types of tasks, this kind of input lowers the mental burden for the user (something that Buxton showed in his papers).
If we turn your idea around: laptops come with a trackpad by default. If only OSes would allow for distinguishing between it and and external mouse (for example), then we could already cheaply and easily experiment with this on our laptops!
If you really want to solve the problem, use a rope. The advantage of gap buffers is simplicity (accounting for the gap is a simple compare with a couple of numbers). Ropes are definitely more complicated, but they have massive advantages in worst-case complexity (most edit and query operations have O(log n) cost).
The simplicity argument is absurd to me. Text editors are some of the most important programs to get right. The complex but high performance data structure is worth the effort. It's like arguing that a GIS program shouldn't use a quadtree.
The first part of the article is true; gap buffers are not a data structure particularly optimized for multiple cursor edits. The conclusion is ridiculous. Of course you can provoke noticeable slowdown by doing an edit with thousands of cursors, but most people are doing small edits to small files, so the cost of the memmove operations is probably in the microseconds per cursor range. If multiple cursors feel intuitive to use and gives immediate visual feedback, why shouldn't people use them?
I say this as someone who has chosen a more sophisticated data structure (ropes) in the editor I'm working on.
I took it as a joke. Obviously one shouldn't concern themselves with how their editors store the text while editing. Furthermore macros or rectangular editing (which the author argues are superior to multiple cursors) have exactly the same performance issues on big files. If multiple cursors are really useful then one should use them.
But I think the author makes a good case about why it's a rather pointless feature in the end. Macros and rectangular edition are strictly more powerful than multiple cursors. That's a good reason to prefer them over multiple cursors.
I'd say multiple cursors are strictly more powerful than rectangular edits, since every rectangle can be outlined using multiple cursors, but they can also cover non-rectangular areas. Macros are of course even more powerful.
What I like about multiple cursors is the immediate feedback, although I have yet to see an implementation that can emulate search-and-replace with capture groups.
Beside data structure based on B+ tree (ropes), what do you think about Relaxed Radix Balanced Vector tree[0]? It is cache-friendly and immutable as well.
Looks pretty neat, thanks for the link. From a quick look, it seems like the performance characteristics will be pretty similar to a xi-style rope (it seems extremely unlikely to me that the time spent finding the child is significant, so the radix trick can't save much time), and it's a bit more complex. That said, I do expect it to perform nicely for read-only access to large documents, which is definitely an important use case.
It would make a fun project for somebody to implement it and compare the performance. I'd certainly take the PR for it if the performance was better :)
[edit: followup] The rope implementation in xi has an additional heuristic that tries not to split lines across leaf boundaries (ie most leaves should end in a newline). It also has a hard constraint of not splitting a unicode codepoint. Thus, leaves and subtrees would have an unpredictable number of elements (as opposed to being a clean power of two when full) and I think that pretty much invalidates using the radix to select the child.
My solution is to put the buffer implementation into a module that is used as a dependency for a standardized "buffer" functionality. That way, if I know a piece-buffer or rope will be more efficient, I can choose which implementation to fills the dependency.
The two main reasons I use and love multiple cursors aren't mentioned here:
1. I find it's easier to figure out what I want. If I use a command that doesn't generalize, I see it immediately. When I use vim macros I find I either have to redo my macro multiple times if I screw up, or spend a bunch of time thinking about how to correctly generalize my commands while writing the macro.
2. There are less concepts to learn and think about applying. You can replace multiple cursors with a combination of macros, rectangular selection and find/replace. But, I find all that functionality easier to think about and apply when it's all unified into one simple system.
Multiple cursors don't require me to switch my brain to an entirely different domain to figure out what to do. It feels like my fingers can happily handle multiple cursor edits - leaving my brain to continue focusing on whatever it was I was actually doing.
The way I've phrased your point 1 in the past is that multiple cursors are like interactive programming in a REPL and using macros is more like being on an edit-save-run cycle (not quite, because you do see the original run of the macro, the one you're recording, live).
Why multiple cursors don't work (for me, of course):
1) I'm limited to what I can see. I can't see that a command does not generalize unless it's on the screen. Most files I work on take up more than the one screen I'm on.
2) Multiple cursors tend to have really limited flexibility - if it can't be done easily with the available movement keys, often times it can't be done. Macros, on the other hand, can easily move non-contiguously.
Yeah, macros do require a bit of extra thought around "how do I program the text editor to do what I want", but they usually do the right thing. It helps that macros are easy to record and use in vim, and that a macro can call another macro.
Of course, I have used multiple cursors before, but usually only in data files which follow strict columnar formats.
I don't encounter either problem:
1) If I'm editing things that don't fit on one screen, I'll scroll and check them all after I'm done. This is no slower than the scrolling needed during the step of applying a macro everywhere and checking it. And I at least get feedback from one page while composing my edits, with macros I get none.
2) I use multiple cursors with Vintageous in Sublime, so I get most of the power of vim macros, but with multiple cursors instead.
> When I use vim macros I find I either have to redo my macro multiple times if I screw up, or spend a bunch of time thinking about how to correctly generalize my commands while writing the macro.
In Vim you can put the contents of a macro into a buffer, modify it like a file, then replace the macro with the modified one.
It's funny how you see these articles about fancy text editor buffer representation (gap buffer, ropes) but meanwhile, the editor with the best feature/performance ratio (including multiple cursors) I've found[1] "simply" represents a buffer as a vector of strings.
Come on now. The advantage of multiple cursors is instant feedback by cycling through the cursors and observing all the changes in real-time and by being able to undo changes and interactively adapt to the observed problems, without having to redefine the entire sequence of actions. Macros can achieve the same, but in many cases it just takes much more time.
Rectangle edits are equivalent to a tiny minority of what I use multiple cursors for (and are generally just rare overall), so this doesn't make much sense to me.
As an example, at the moment I'm juggling a large number of constants where I'm still learning how to classify and group them. I can use alt-d and alt-shift-d to select between local groups, either whole words or just suffixes, and rename them locally. A multiselection is normally, say, 3 to 10 selections of 3 to 10 characters, so the edits themselves are far too tiny and frequent for macros to meaningfully help, yet far too irregular for column selection to help. At the same time, multiple selections are acting as an incremental search and a way to jump between places.
Frequently I do want to do regular operations, but columns are way too restrictive. Say I had something like the anonymized code
and I wanted to subtract one from the middle argument to each call to `chance`. Column selections aren't impossible here, because there is some structure, but with multiple cursors I can just select all the relevant `chance`, ctrl-right to the end of the relevant number, write "-1", ctrl-shift-left so I select the expression, and press my evaluate key (ctrl-shift-e) to run the subtraction.
Or say I have some Markdown and I want to give a correct-width underline to a title. ctrl-d to duplicate and select the new line, shift-left to unselect the newline character, alt-c to break the selection into characters, and then just press "=" to replace them all.
Or say I want to reformat a function call so all the arguments are on new lines, I will naturally gravitate to selecting a separator (the comma in all likelihood) and just adding a newline there. I can keep some arguments together by just skipping those.
This isn't to say multiple selections is the only way to do this stuff; this is just the way I like doing it with my editor.
Editors without vim macros probably need multiple cursors, but the main argument in favor of macros is that (for things like the markdown underline macro), it's easy to save it for later, and you can see it happen to every location even if some are offscreen.
The main argument for multiple cursors over macros is that they give a tighter feedback loop. If the macro you record works for the section where you recorded it, but doesn't generalise, without thinking hard about it (undesirable) you won't know about it until you actually go and run the macro in an incompatible spot. Once that happens, you either have to re-record it, or dump it out and edit it manually. Neither of those options can be said to be particular friction free. By contrast, with multiple cursors, if you do something wrong (or right in some places, wrong in others) you know about it immediately, and you can fix it immediately in a friction free manner.
I don't think multiple cursors can replace macros in all situations, but it needs to be acknowledged that different tools have different strengths and weaknesses, and when choosing which to use in a given situation you should keep that in mind. Dismissing one because the other is more powerful is like always using a sledgehammer to knock in your nails. Sometimes the other is more convenient, or more user friendly, or less of a pain in the arse in some other relevant way.
Thank you for taking the time to explain. I don't use multiple cursors but now see how it might be more accessible than using regex based replace commands or macros.
The key point I got was one already knows how to edit with one cursor and multiple cursors extends the same behavior trivially. Anything else (e.g. macros) first requires learning a completely new model and behavior.
> Somewhere around 99% of my multiple cursors usage was adding a common prefix to a contiguous [series] of lines.
I would say that it's somewhere around 25% of my usage.
More common -- probably 50% or more -- is finding all occurrences of a string scattered throughout a file and making edits to that string that are more sophisticated than a simple find-replace can handle (e.g. edits that involve back-references). In many cases, I could probably write a regex, but using multiple cursors is so much easier.
Spend a day on writing a regex woah. Most editors have a find + replace feature which jumps to each location and allows it to be nicely reviewed before making the edit.
Maybe we'd all use macros if the UX for them we're no so atrociously bad? It's only recently having tried out some obscure but good packages in spacemacs that we start to see some great UX for macros and other bulk line editing operations.
What's more, macros are often only valid on lines of exactly the type you specified them on, and Emacs's best way to handle this (if they're contiguous) is narrowing and widening, an operation so famously confusing that the buttons are walled off with an apology in standard emacs.
I use multiple editors for non-trivial operations (instead of say, whitespace tuning) when I'm doing quick but high value non-contigous work (e.g., adding an exporting decl to several functions).
I didn't know emacs was using a gap buffer, but if so I have 0 sympathy. Vim sounds like it's using a clearly superior and modern solution. Maybe I should finally got over to that dark side?
Absolutely. In Vim, since every command is a keystroke you can save a string of keystrokes to a buffer, and "run" that buffer as a macro. You can even paste the buffer instead, edit it as plain text, and put the new version back into the buffer and run it.
Personally I don't see how that is ebttee. Why is it better? Macros would be better if they were less invisible.
Spacemacs/viper has this great copy of a vim feature where :/ and :s/ commands actually show a diff view interactively in the buffer. It turned an old useful-but-opaque feature into an equally useful but interactive and novice-friendly feature. We need more of that in code editing.
Honestly, I'm pretty sure that for most people's use any slowness with multiple cursors in Emacs is nothing to do with the data structure used to store the edits.
The noticable delay is due to highlighting closing parentheses.
Yeah, macros can do everything multiple cursors can do, but if multiple cursors is easier for people to use it's worth supporting.
Gap buffers are an implementation detail I don't care about as a user, I care about the features of my editor, so it is strange to suggest that I can't have a feature in order to preserve an implementation detail. A better argument would have been that speed is a more important feature, but the article didn't argue that multiple cursors are necesarily slower, just that a gap buffer would be slower with multiple cursors.
> Yeah, macros can do everything multiple cursors can do
Not everything. You can perform set operations on multiple selections, or filter them, eg. by keeping every nth or removing those on blank lines. You can save and restore selections, or use them as jump points. You can find their covering range, globally or on a line-by-line basis. You can count them or run scripts across them. Most importantly perhaps is you can copy them.
Similarly, macros can do things multiple selections struggle with, largely because macros apply sequentially so the start to one can depend on the end of another.
I think the author's conclusion is a little "throw out the baby with the bathwater".
I do want to plug a couple of my favorite kmacro-related emacs features though:
M-x kmacro-edit-macro "edit the last defined keyboard macro"
M-x kmacro-edit-lossage "edit the last 300 keystrokes as a keyboard macro"
Both bring up a buffer with a keyboard macro expressed as an s-expression, and you can edit it and then press C-c C-c to save it.
The first is useful when you need to tweak a keyboard macro but don't want to completely re-record it. The second is sometimes useful for deciding that that thing you just did, you want to do it N times instead of 1.
I took a bit of time learning how to use Vim macros a few years ago, and then never envied SublimeText programmers again. The fact that I could compose and store the macros meant that I can effectively augment the editor without having to muck about with Python, Vimscript, or Emacs Lisp.
Oh, I wasn't trying to say that you can't do that in Emacs, I just never learned how to use them. I wasn't trying to knock Emacs macros in this case, I was just saying that once I learned Vim macros, I realized that it eliminated a lot of my previous cases where I had to muck about with the editor's scripting language.
They were, but programming in TECO (although they were just strings of edit commands) was more complex than emacs lisp, believe me. I wrote a lot of MIT TECO back in the day and don't miss it!
Thinking back, its hard to believe that I spent a fair amount of time teaching students the ins and outs of TECO because that was a more effective way to do the coding required in my class. The alternative was punching cards. It was a second semester university course for CS students.
This might be a little off-topic, but one of the most common operations I use multiple cursors for (in Emacs) is refactoring. Specifically, renaming things, which is the only kind of refactoring it seems I can automate.
Are there any good refactoring packages out there? For Java, Kotlin, Python, Rust etc.
For every editor there are people negative on it, Emacs doesn't particularly stand out. This thread is remarkable in how little editor flamewar is going on.
I think the author actually just wanted to play with and show off the gap-buffer animations but for some reason only came up with this weak excuse to do so.
94 comments
[ 0.29 ms ] story [ 138 ms ] thread> get more comfortable with your editor’s macro feature. If your editor doesn’t have a good macro feature, get a new editor.
They also link to an essay[0] pointing out numerous ways in which multiple cursors don't play well with advanced editor features (using Vim for the demonstration but the point likely works just as well for Emacs).
Sure you can also take the inverse tack and switch to an editor implemented in such a way that multiple cursors is efficient, but… is multiple cursors really the feature you want to stop at?
[0] https://medium.com/@schtoeffel/you-don-t-need-more-than-one-...
When you record a macro, you need to be careful to encode commands that will work well wherever you apply it. That means skipping forward by a word rather than a fixed number of characters, sometimes doing fiddly operations around word and whitespace boundaries to make sure the cursor is in the expected position for the next step. When multiple cursors are used to emulate macros, you get a wysiwyg experience, rather than "programming" the cursor and finding out later during playback that it did the wrong thing.
Multiple cursors are also used as a replacement for text search and replace; sometimes the operation could be performed using a symbolic rename, sometimes it could be done by search and replace with live preview, but not when you want to skip some instances.
Probably 95% of my personal use of multiple cursors is for local refactoring, e.g. switching out a hash for an object or vice versa, where I want to change 'foo.bar' to 'foo[:bar]', but sometimes (electively) 'foo.fetch(:bar)'. Multiple cursors let me do both the selection and the editing in a wysiwyg fashion, where neither macros (typically with a 'find next' operation recorded last) nor a complex search and replace with capture group and interactive replacement are nearly as pleasant.
FWIW, for many years I used Borland IDEs and almost the only tool available for complex manipulation was keyboard macro record and playback (I spent probably 15 years only using keyboard macros). These days, though, the combination of synchronous editing (iedit mode in emacs) and multiple cursors have almost completely replaced my macro usage with much more usability due to the live feedback.
The Medium article about multiple cursors was from a Vim-centric perspective (in contrast to the linked article here, which was Emacs-focused). And in Vim, you'd do this with `n` and `.`. For example, `n.n.nn.` means, "change the second occurrence, too, and the third, but not the fourth, and do replace the fifth".
Multiple cursors is no faster, and since you mentioned the benefit of not needing to carefully plan ahead (which I also think is important[1), I'll leave you with the observation that multiple cursors requires more planning than `.`. With `.`, the following thought process is valid:
"Let's change this. Oh! And do these other ones, too."
Compare to multiple cursors, where you have to don't have to plan as carefully as a recorded macro, but you still have to do some planning, because you have to start out knowing that you're going to change multiple things and then marking them before you make any change.
So the spectrum looks like:
# Recorded macros—requires lots of careful planning
# Multiple cursors—requires little planning
# Replay (`.`)—requires no planning at all; can fit your stream of consciousness
1. https://news.ycombinator.com/item?id=13350487
Hm, it strikes me that it might be a cool feature to interactively select as many of the last few commands you gave as you like, and copy them to a macro register. It seems like it wouldn't be too hard to implement, seeing as the commands you make are already stored in the undo tree.
> The ultimate feature that comes with vim is, that you can edit and save these macros for your next vim session and even add a key mapping.
They almost entirely miss the point of the feature. 99% of the time when you're editing with multiple cursors, you're doing a unique thing which would be meaningless outside the context of where you're doing it. The ability to save the macro misinterprets the flexibility to do exactly what is needed at the moment.
Your comparison to anonymous functions is not apt. A language that implements higher order concepts like anonymous functions adds more power to the language. But on the spectrum of power, multiple cursors are not a more powerful form of macros. Macros—Vim's, at least—are higher order than multiple cursors. (Note that when I say "macros" here, I'm going along with the premise of the Medium article where the ability to replay the last edit using `.` is also considered macro use.)
Second, the ability to save a macro doesn't make macros less flexible. It's not as if you have to pay for it whether you use it or not. If you don't want to save it, then don't; but it's there if you want the option.
(Something I've been missing in this discussion: are multi-cursors to slow for users in practice, or is this technically slower/"less efficient"?)
(and for the side-discussion about the function example: Doesn't the extra power in the function case comes from being able to pass and dynamically create functions, not from the fact that they are anonymous? E.g. in Python, lambda functions really just save a few characters over using local named functions? Am I missing something?)
> The ability to save the macro misinterprets the flexibility to do exactly what is needed at the moment.
This makes it sound like a +1 for multiple cursors and and a plus null for macros/replay. You could argue that the wording is just so and doesn't actually claim that macros are less flexible. But the reality of the situation is that macros are +1 and multiple cursors is plus null, and the gestalt of comment I responded to doesn't convey that. That is, in all the cases where multiple cursors shine, Vim's native features are, at worst, on equal footing, and there's a non-zero count of cases where the inverse is not true. However, someone who hears the argument in the message I responded to might come away feeling that the opposite is true.
> "you don't need intuitive feature X, just use Y which is even more powerful instead" isn't a great message to users.
This, too, sounds like a crafted message—that Vim's native approach is missing something, and that advocating for e.g. repeat instead multiple cursors is shortsighted (somewhat reminiscent of [1]). The implication tends to be that the alternative might be more powerful but less intuitive or require orthogonal thinking. And there are cases in computing like that. Plenty. But using repeat instead of multiple cursors is not one of them.
1. https://xkcd.com/974/
I still argue that macros are missing something UX wise. It's a matter of preference which style you like better for specific problems, and I haven't seen a good argument for why only one of the two should be present. I don't think the fact that macros can fulfill the same function is a good argument. Them being more powerful IMHO isn't either, it just means that when multi-cursor editing fails someone preferring it, they still have the option to use macros then.
I haven't actually tried multi-cursor editing in emacs - if it is unusably/annoyingly slow, then the article would be interesting as an explanation for why that's the case, but its failing to establish that context.
If it's not, it's still interesting from a theoretical perspective. I think it shouldn't argue against multi-cursor editing the way it does.
Presenting the option of using a macro is fine, explaining the benefits of it is great, dismissing multi-cursor editing as
> tacky and modern
is totally unnecessary. And unrelated to an article about implementation details. Write "Why you should consider learning about macros", make a case for them that's unrelated to "our datastructure doesn't like the alternative as much".
EDIT: to address the quoting: It wasn't my intention to look like I'm making up quotes, I need to think about a different way of marking these up it seems. I try to put actual quotes on new lines.
IMO, the features you advocate instead of multiple cursors don't play well with a fairly large fraction of users.
So, do you get rid of those users, or do you adjust your program to them, so they get a subset of the power of macros that they can happily use?
People like multi-cursors because their behavior is very stable and obvious. Macros have very unpredictable behavior except on lines that precisely conform to the shape of line you used to specify them.
And buffer narrowing/widening isn't a solution. You can specifically play the macro over cursor lines (it is a "good practice" to C-a at the start of a macro to help with this), but it's many more keystrokes.
It may be "all hat and no cattle" as the author says, but I have uses for hats and I've got no facilities to keep or slaughter cattle.
Control-x ) stops recording a macro
Control-x e replays the macro
They're no more obscure than the rest of emacs (which isn't a great starting point!) but everything comes down to keybindings in any text editor, you can map them to any key you want.
Cool, you can start and record a macro. What does the temp macro do on this line? On a different line? Does your undo stack flip over or through the macro? How do you run the macro on lines with a specific suffix?
Because macros inherently make a big blob of actions and turn them into a single action, they're inherently more obscure than multiple cursors.
The funny part is of course that macros are dictated in emacs, not programmed. So what the multi-line cursor is doing is essentially showing you the results of a macro and letting you interactively work with it visually rather than deny you that option.
Macros have uses, but Swift multi-line editing is by no means their strong suit.
There isn't a single mainstream OS that supports having multiple mouse cursors that I know of, and even if it did, not a single program expects it either - most would break. The closest we have is on-line editors that can have multiple users like Google Docs, and that's not single screen.
And you may be thinking "yeah but why?" and I wouldn't blame you, but that's just because you're not aware of how how much our current input devices limit us and how they are based on a flawed model of handedness.
Yves Guiard proposed a model in 1988 that argues the dominant/recessive model of handedness is wrong: instead, we constantly perform complicated asymmetrical tasks, with one "coarse" reference-frame hand and a fine-tuned "zoomed-in" hand (the latter being considered the dominant one)[0]. Later research has only backed this up (note that the linked paper has over a thousand citations).
When keeping this asymmetrical model in mind designing our input, things tend to just "feel" right. I guarantee you that the best two-handed input methods you use all follow this principle: even if not applied consciously, any two-handed interfaces converges to it. Simple case-in-point: remember 3D shooters before WASD + mouse? WASD = reference frame hand, mouse = fine-tuned input hand. Gamers just intuitively discovered this on their own. In fact, look at button placement on gamepads in general: movement ("frame of reference") on the left, action buttons on the right.
Bill Buxton[1][2][3] did really cool experiments with these ideas and then... well, nearly nothing. And I really believe the main reason is a lack of technical freedom to experiment: even if someone does manage come up with a wonderful intuitive, fluid bimanual interface that isn't limited to a keyboard, a mouse and maybe a touch-screen, who is going to be able to use it on their laptops or desktops?
I'd like to experiment and the fundamental requirements to do even that are missing. Even multi-touch is barely going to help: you cannot tell which hand belongs to which touch-point.
[0] https://www.ncbi.nlm.nih.gov/pubmed/15136274
[1] https://www.billbuxton.com/2hands.html, video: https://www.youtube.com/watch?v=w0c1Xg9lERY
[2] https://www.billbuxton.com/ToCHI2H.html
[3] https://www.billbuxton.com/input11.2H.pdf
I would imagine that a touch scroll pad like in the linked video would be a useful thing to have on the left hand side of a keyboard. I could use it to navigate through a document quickly and use the mouse to pick my target.
Games and input devices for games also always design around bimanual input, even if rarely consciously.
Side-track: something almost nobody noticed when the Wii came out is that it's wiimote/nunchuck setup works both for right- and left-handed people. I'm left-handed and I automatically switched to a left-handed input method for my games without even thinking, for the first time in my life! I didn't even realise this until a few months in myself!
And yes, I completely agree with you! Something I forgot to mention is that for certain types of tasks, this kind of input lowers the mental burden for the user (something that Buxton showed in his papers).
If we turn your idea around: laptops come with a trackpad by default. If only OSes would allow for distinguishing between it and and external mouse (for example), then we could already cheaply and easily experiment with this on our laptops!
I don't have a lot of experience with GIS, but you're telling me that a linear scan through all the features on a map isn't good enough? :)
[0] https://news.ycombinator.com/item?id=14129543
I say this as someone who has chosen a more sophisticated data structure (ropes) in the editor I'm working on.
But I think the author makes a good case about why it's a rather pointless feature in the end. Macros and rectangular edition are strictly more powerful than multiple cursors. That's a good reason to prefer them over multiple cursors.
What I like about multiple cursors is the immediate feedback, although I have yet to see an implementation that can emulate search-and-replace with capture groups.
[0](https://icfp17.sigplan.org/event/icfp-2017-papers-persistenc...)
It would make a fun project for somebody to implement it and compare the performance. I'd certainly take the PR for it if the performance was better :)
[edit: followup] The rope implementation in xi has an additional heuristic that tries not to split lines across leaf boundaries (ie most leaves should end in a newline). It also has a hard constraint of not splitting a unicode codepoint. Thus, leaves and subtrees would have an unpredictable number of elements (as opposed to being a clean power of two when full) and I think that pretty much invalidates using the radix to select the child.
Why are you working on an editor? Serious question.
1. I find it's easier to figure out what I want. If I use a command that doesn't generalize, I see it immediately. When I use vim macros I find I either have to redo my macro multiple times if I screw up, or spend a bunch of time thinking about how to correctly generalize my commands while writing the macro.
2. There are less concepts to learn and think about applying. You can replace multiple cursors with a combination of macros, rectangular selection and find/replace. But, I find all that functionality easier to think about and apply when it's all unified into one simple system.
1) I'm limited to what I can see. I can't see that a command does not generalize unless it's on the screen. Most files I work on take up more than the one screen I'm on.
2) Multiple cursors tend to have really limited flexibility - if it can't be done easily with the available movement keys, often times it can't be done. Macros, on the other hand, can easily move non-contiguously.
Yeah, macros do require a bit of extra thought around "how do I program the text editor to do what I want", but they usually do the right thing. It helps that macros are easy to record and use in vim, and that a macro can call another macro.
Of course, I have used multiple cursors before, but usually only in data files which follow strict columnar formats.
Conceptually, multiple cursors are nothing but a partial visualisation of a macro functionality.
In Vim you can put the contents of a macro into a buffer, modify it like a file, then replace the macro with the modified one.
[1]: https://github.com/mawww/kakoune
Okay, now THAT is interesting. Can you comment on some of the other uses you have for multiple cursors? Perhaps give some examples?
Suppose you wrote some silly code like this:
Replace "cond" by "case x". Select first "eq x", mark the other two (you have 3 cursors now), forward to the keywoard, M-<up> (with paredit):Frequently I do want to do regular operations, but columns are way too restrictive. Say I had something like the anonymized code
and I wanted to subtract one from the middle argument to each call to `chance`. Column selections aren't impossible here, because there is some structure, but with multiple cursors I can just select all the relevant `chance`, ctrl-right to the end of the relevant number, write "-1", ctrl-shift-left so I select the expression, and press my evaluate key (ctrl-shift-e) to run the subtraction.Or say I have some Markdown and I want to give a correct-width underline to a title. ctrl-d to duplicate and select the new line, shift-left to unselect the newline character, alt-c to break the selection into characters, and then just press "=" to replace them all.
Or say I want to reformat a function call so all the arguments are on new lines, I will naturally gravitate to selecting a separator (the comma in all likelihood) and just adding a newline there. I can keep some arguments together by just skipping those.
This isn't to say multiple selections is the only way to do this stuff; this is just the way I like doing it with my editor.
https://medium.com/@schtoeffel/you-don-t-need-more-than-one-...
Editors without vim macros probably need multiple cursors, but the main argument in favor of macros is that (for things like the markdown underline macro), it's easy to save it for later, and you can see it happen to every location even if some are offscreen.
I don't think multiple cursors can replace macros in all situations, but it needs to be acknowledged that different tools have different strengths and weaknesses, and when choosing which to use in a given situation you should keep that in mind. Dismissing one because the other is more powerful is like always using a sledgehammer to knock in your nails. Sometimes the other is more convenient, or more user friendly, or less of a pain in the arse in some other relevant way.
The key point I got was one already knows how to edit with one cursor and multiple cursors extends the same behavior trivially. Anything else (e.g. macros) first requires learning a completely new model and behavior.
> Somewhere around 99% of my multiple cursors usage was adding a common prefix to a contiguous [series] of lines.
I would say that it's somewhere around 25% of my usage.
More common -- probably 50% or more -- is finding all occurrences of a string scattered throughout a file and making edits to that string that are more sophisticated than a simple find-replace can handle (e.g. edits that involve back-references). In many cases, I could probably write a regex, but using multiple cursors is so much easier.
Maybe we'd all use macros if the UX for them we're no so atrociously bad? It's only recently having tried out some obscure but good packages in spacemacs that we start to see some great UX for macros and other bulk line editing operations.
What's more, macros are often only valid on lines of exactly the type you specified them on, and Emacs's best way to handle this (if they're contiguous) is narrowing and widening, an operation so famously confusing that the buttons are walled off with an apology in standard emacs.
I use multiple editors for non-trivial operations (instead of say, whitespace tuning) when I'm doing quick but high value non-contigous work (e.g., adding an exporting decl to several functions).
I didn't know emacs was using a gap buffer, but if so I have 0 sympathy. Vim sounds like it's using a clearly superior and modern solution. Maybe I should finally got over to that dark side?
Spacemacs/viper has this great copy of a vim feature where :/ and :s/ commands actually show a diff view interactively in the buffer. It turned an old useful-but-opaque feature into an equally useful but interactive and novice-friendly feature. We need more of that in code editing.
The noticable delay is due to highlighting closing parentheses.
> set inccommand=nosplit
To do search and replaces interactively.
A saner conclusion would be: If you want multi-cursor editing in your editor, don't use a gap buffer.
Gap buffers are an implementation detail I don't care about as a user, I care about the features of my editor, so it is strange to suggest that I can't have a feature in order to preserve an implementation detail. A better argument would have been that speed is a more important feature, but the article didn't argue that multiple cursors are necesarily slower, just that a gap buffer would be slower with multiple cursors.
Not everything. You can perform set operations on multiple selections, or filter them, eg. by keeping every nth or removing those on blank lines. You can save and restore selections, or use them as jump points. You can find their covering range, globally or on a line-by-line basis. You can count them or run scripts across them. Most importantly perhaps is you can copy them.
Similarly, macros can do things multiple selections struggle with, largely because macros apply sequentially so the start to one can depend on the end of another.
I do want to plug a couple of my favorite kmacro-related emacs features though:
Both bring up a buffer with a keyboard macro expressed as an s-expression, and you can edit it and then press C-c C-c to save it.The first is useful when you need to tweak a keyboard macro but don't want to completely re-record it. The second is sometimes useful for deciding that that thing you just did, you want to do it N times instead of 1.
https://www.gnu.org/software/emacs/manual/html_node/emacs/Ed...
This feature has existed in Emacs since before GNU Emacs.
It started out as bunch of TECO macros.
Are there any good refactoring packages out there? For Java, Kotlin, Python, Rust etc.
You can also manipulate the point stack explicitly though I got out of this habit over the last decade or so.
> take a dig at Emacs and people that like it
I think the author actually just wanted to play with and show off the gap-buffer animations but for some reason only came up with this weak excuse to do so.
I do quite like the gap buffer animations.