It is my experience that 99% of code editing involves selections of full lines or stretches of characters within a line. The other 1% is character selections spanning multiple lines.
Most code editors do not optimize their selection functions for full line mode and are stuck in “Notepad” mode of character based selections, optimized for what developers need only 1% of the time.
Forcing me to constantly move the caret to column 1 (0 for those of you working on text editor code) and loose the position where I was just to select and paste full lines is not amusing, to put it diplomatically.
This has been a pet peeve of mine with all IDEs and code editors that I know of since the beginning of time. Yes, I was there at the beginning, when IDEs did not exist and a notepad equivalent was an amazing code editor, because it was the only editor.
It was the main reason I wrote and maintained my own editor for 30+ years. It started in 1985 when I came across IBM’s mostly internal and low key editor called PE, for Personal Editor. I was instantly in love. It was the best code editor I ever used.
It had block, character and line selections. Operations were tailored to selection type, so you could never copy/move a line selection into the middle of another line. Line selections always copied below the caret line. No more accidentally copying into the middle of a line by forgetting to move caret to left margin before. It had virtual spaces as the only mode. No more caret jumping to end of physical line as you moved up and down. Type anywhere and spaces are filled in where needed. It was code editing heaven. It also did not use the ENTER to split a line but to insert one. Splitting a line is an efficient use for a word processor. In a code editor you spend more time inserting blank lines to add code than adding paragraph breaks. Having to move to the beginning or or end of line, just to insert a blank line is a crime for code editors.
I loved it so much that when I started developing on the Commodore Amiga with a notepad like editor, I decided to implement a PE like editor first, then do the other stuff that I wanted. Little did I know at the time, but writing your own editor is a career decision.
I released it for the Amiga, PTE: Professional Text Engine, ported it to DOS, then Unix and eventually to Windows 3.1, 95, NT and finally Vista, named WinPTE and renamed to Beyond Edit in its last days. It grew in features but always stayed efficient. Coming from DOS roots of 512k system memory and an 8086, 4 MHz CPU, it knew how to be frugal with resources. Once the iron evolved past Intel 486 and 16MB of RAM, performance and resources were never an issue.
When I decided to change my development environment to Mac OS X, my world was turned upside down. Not only did I miss the familiar shortcuts that I used for decades and customized to my work style editor, I also had to give up:
- Tab-less, automatic editing of column aligned text without disturbing the column alignment. I haven’t used tab in column aligned code in over 20 years.
- Smart mouse select/drag/drop tuned to editing code which adjusted to dragged content and context of what it was dropped on.
- Super fast and powerful multi-caret mode in which I could edit a 100,000 line file with a caret on each line and so without having time to take a cigarette break between key strokes.
- And last but not least, I had to give up the line based selections and text manipulation.
When I realized the full impact of the loss, I was literally in shock. Could I even effectively code without my editor? Followed by a much more serious question: Did I want to?
I calmed myself down and decided that porting the old war horse to OS X was out of the question. Its original architecture was pushed to the limit. It needed a complete rewrite. I was also tired of maintaining it for an effective audience of one. I made the decision to find my new home in the form of an IDE with which I would become as efficient as I was with my editor.
My first project was PHP based. I tried many IDEs and editors finally settling on PhpStorm. I loved the intelligence of the IDE in working with in depth analysis of actual code. I thought that maybe “notepad” text editing would be compensated with refactoring and quick fixes it offered. It did, for the most part but I still jumped into Parallels Desktop for a quick multi-caret chop and dice when I could not bring myself to do it manually, notepad style. Overall, I started getting used to my new, powerful, eye-candy GUI environment, with less than optimum text editing capabilities.
As life twists and turns, I got into JetBrains plugin development with my Markdown Navigator plugin and hardly thought of my old work horse except at those times when “I could have done this in seconds with a few keystrokes in Beyond Edit”, if I did not have to wait for Windows 10 to update when I launched it under Parallels. So I just typed away like a peasant with an underwood. Calmly, feeling that I have the safety net of my old editor, should I really need it.
Then disaster struck in the form of one of many and numerous Windows 10 updates. Beyond Edit stopped launching. No errors, no dialog box, just quietly fails to open. This was another shock to my system but by this time I had only fired it up once in a few months so I thought I kicked the habit and was now content on intelligent, comfortable ground travel with the best of breed IDEs rather than flying an old war plane with idiosyncratic controls.
The brains and automation of IntelliJ IDEA and other JetBrains IDEs is fantastic and is an absolute must-have for me. I adapted my work style to take advantage of refactoring power. I spend a lot less time trying find the right names or break down of functions when creating new code, comfortable in my knowledge that it is painless to address later with refactoring. I still find that there are plenty of times when a fast chop and dice of text would be orders of magnitude faster. Over the years I learned to follow a coding style and naming conventions adapted to support efficient chopping and dicing of text for re-use.
IDEA has tons of automatic refactoring and code creation actions but if it does not or they won’t work because you are in the middle of source code upheaval, with more syntax errors than lines, then I would prefer to fall back to powerful multi-caret mode than RegEx debugging and macro recording. It was why I added multiple caret mode to my editor in 1997 in the first place. I was tired of writing and debugging macros to do mass editing.
I made a long list of text editing features I wanted in the IDE but never got beyond that because I felt the effort did not warrant the gain, especially when I already got used to getting by without them, or so I thought.
Serendipity struck when I was browsing YouTrack IntelliJ IDEA: Backlog, and came across an issue complaining that the IDE was missing “Move Caret to End of Word” making word selection awkward, especially for Mac users where next word with selection stops on ends of words. What struck me speechless was that the issue was from 2008, still unresolved and there were arguments similar to “Who needs this anyway, we have RegEx”.
Considering all the very hard to almost impossible things the IDE does, I felt that something this simple should have been addressed by a summer student long ago. I left a comment that I didn’t see why it could not be done in a plugin and volunteered to do it. Little did I know at the time, but this is when my editing enhancement plugin: Missing In Actions, Mia, was conceived.
Making a plugin for just move to next/previous end of word seemed a bit less than a challenge,
so I decided to improve on a few multi-caret friendly features that annoyed the S**T out of me
in the IDE and maybe give Line Selection mode a quick once over to see if it could be added. My
Markdown Navigator experience was no help here. I had no clue to what was involved since I did
not visit the
ActionManager planets of the
star system in the JetBrains API galaxy of the intellij-community source code universe.
I quickly discovered that for all the functional primitiveness of the editing API used by existing code, with some elbow grease and a bit of effort it could be done. The API is primitive but the underlying implementation superb, making me suspect different qualification of developers working on different parts of the code and in different epochs of the code base.
Adding the basic Line Selection mode and very few creature comforts to make use of it, I released Mia into the JetBrains plugin crowd. It was only five days since I got miffed about the end of word caret movement issue. The code was young, and did not play nice with all the IDE features but I still preferred using line selection mode, as primitive and as buggy as it was. I made the decision to make it work right. It was as comfortable as I remembered it and well worth the effort.
This is when all hell broke loose in my human “sub-system” we call the subconscious. I was surprised to discover that all those old work horse features I learned to live without were still in my muscle memory when I started hitting shortcuts which I haven’t used or even remembered in years. It got worse, as the basic line selection operations were stabilizing I had an expectation that they would work like line selections should. I was frustrated that to the IDE they were character selections that happened to start and end on full lines.
It is now almost a month since my plunge into an editing plugin for JetBrains IDEs and Mia has come of age. It is an absolute productivity boost for code editing:
Move caret, with and without selection, to next/previous start/end of word, including a customizable set of actions where you can completely tune all the boundary stops these actions will make. This has several advantages one of which is that you can quickly and/or via shortcuts change the behaviour of word movement and selection keys without having to change the key mapping.
Automatic line selection mode that works with the rest of the IDE as if it was native. All vertical Move with Selection functions will switch to line mode and select full lines, horizontal move with selection switches to character based selections. You can mix these as the need arises. Multi-line character selections are more involved than before but these are rarely used if you have line selections and in trade you get fast line selections without needing to constantly move the caret to the left margin.
Automatic line selections when using the mouse. If you select text within the same line, it is a character selection. Select text spanning more than one line and it automatically switches to selecting full lines, regardless of the mouse pointer column. You can override this with a Ctrl key modifier, allowing old behaviour if you need it or through configuration to reverse the modifier function: when pressed line selections, when not pressed character selections.
Column position preservation when operating on line selections. This was an exercise in catching fleas and herding cats. You’d be surprised how many actions will move the caret to column 1 and the myriad of modalities of the IDE that must be taken into account.
Paste of full line selections now behaves like line selections should. These can be made to paste at:
- IDE default, where you left your caret last
- always above the caret line (my new favourite mode),
- above the caret line if caret is between left margin/indent position and below it otherwise,
- always below the caret line
Auto Line Indent on move line or selection up or down. With every other editing operation, the IDE seems to remember to adjust indentation automatically, at least as an option. This operation was left out of the club for some reason, leaving the code indentation messed up, needing a manual intervention. Mia adds an option to re-indent moved lines after a delay. Allowing you to rapidly make multiple moves up/down, and re-indent the code to its proper level when you pause.
Select pasted text to automatically select what you paste so you can apply other operations on it. Configuration options include minimum number of lines in the pasted text, below which no selection is made.
No more moving to left margin to select or paste full lines of code and loosing the column position. No more threading the needle in an effort to select full lines with the mouse, and many more no mores.
The no mores are a productivity boost because these operations get in the way, are complete editing fluff and are done often. But Mia has a few niceties added that make text editing, especially in multi-caret mode, a joy:
Line bound next/previous word with/without selection when in multi-caret mode. The carets will not fly off to other lines. It makes keeping track and controlling their location easy. This is key to being able to do extensive multi-caret editing. With IDE supplied functions, multiple carets become a jumbled mess after a few keystrokes because they have too much freedom of movement.
Delete to end of line action that will not delete the EOL at the end of line, ever. The IDE provided function will delete to end of line most of the time, but when a caret is already at the end of line will delete the EOL, making it useless for multi-caret mode because some carets will delete to end of line while others will join lines. If you want to join lines then use the join lines action.
Seamless switching between line selections and multiple carets on each line using the “Toggle Between Carets and Line Selection” action, allowing re-use of already selected text. To me selections and multiple carets are just manifestations of me telling the editor what I am focusing on. I should be able to switch between the two modes instead of having to re-select the lines, again and again.
Caret filtering based on the line content: keep code lines, keep comment lines, keep blank lines, remove code lines, remove comment lines, remove blank lines with their smart counterparts: “Smart Keep Line Carets” which will keep carets only on code lines, if none of those exist will keep only carets on comment lines, otherwise no change. To be used for quickly placing a caret on every line of code in a selection, ignoring comment lines and blank lines.
Smart Paste mode that adjusts the case and format of pasted text, if it looks like an identifier, to the format of where it is pasted including removal of user configurable prefixes such as “my” or “our”. A copied member variable name on the clipboard can now be pasted in many places without needing a follow up edit, not even a case change. It is like having a mind reading clipboard.
In all cases if you feel that Mia’s help was no help, hit undo and you will have results as the IDE provided. I don’t know if you do these case changes and prefix editing often but I found myself doing them ad nauseam. Copy once, use it everywhere is here.
Every time I use it feels like magic. I know it isn’t, I had to write debug the code, but it still feels that way.
Duplicate Line or Selection for Carets on Clipboard action is a multiple caret user’s dream. It makes modifying a line or lines for repeated variations an effortless joy. A live example from Mia’s own source code. I needed variations for several functions based on naming convention: camel case, pascal case, snake case and screaming snake case. I already have the case names throughout the code. I just need to create a new function with these variations. Easy, take existing lines with the case names and use multi-select, copy, select case name in destination line, dupe for clipboard, paste.
If you do decide to venture off the beaten path and give Mia a try, do expect to give yourself some time to adjust to the new reality. I used line selection mode for over 30 years and not used for two and it took me a week to stop sending the caret to the left margin to make a line selection or paste one. If you have never used line selections, it may seem weird at first but trust me, I will grow on you.
Constructive comments and suggestions are welcome. I can also be reached me at firstname.lastname@example.org
This work is licensed under a Creative Commons Attribution 4.0 International License.