Sublime text: Home key not moving to the beginning of line - sublimetext3

I do the following in sublime text:
Ctrl + A (select all)
Ctrl + Shift + L (into column selection)
Home
i want all the cursors to go to the starting of each line. But in some lines the cursor not going to the beginning of the line
The below is how home key is defined in the Default
{ "keys": ["home"], "command": "move_to", "args": {"to": "bol", "extend": false} },

All of the key bindings that use the Home key to jump the cursor to the start of the line use the move_to command to move the cursor position and specify in the to argument the value of "bol". This includes not just the "bare" key, but also the shifted version that extends the selection, and so on.
The "bol" value of to tells move_to to move the cursor to the beginning of the line, but it toggles between two different beginning of line "states":
The location where the line text starts (for indented lines), which is the "soft" beginning of the line.
Column 1, which is the "hard" beginning of the line
Depending on where the cursor currently sits, you get one or the other, but pressing the key a second time flips the position to the other state.
For example, given a Python example like the following, where | is where a cursor is sitting:
def somefunc():|
print("Hello")|
The first time you press Home, the cursor will jump to the p in print, because that's the "soft" beginning of the line. While the cursor is there, if you press Home again the cursor will jump to the "hard" beginning of the line. Pressing Home again will put the cursor back on the p. For the def line, the cursor will jump to the first column when you press the key and stay there, because it's not indented at all.
The general idea is that in most cases when you want to jump to the start of the line, it's because you want to make edits to the text that starts there without taking the indent into account (in the above example, say you wanted to swap print for log, it's handier if when you press Home you don't have to arrow right a bunch to get back to the function).
In your particular case you can see this happening when you press the key; the lines containing just indent white space jump to the start, as do the lines that physically start in column 1. All of the other lines jump to the soft bol instead.
If you work in files or content where blank lines don't have any trailing white space and are truly "blank", then you could do what you want to do by pressing Home a second time. In that case all of the lines currently sitting at the soft bol would jump to the hard bol, and any lines already at the hard bol will stay there (because the line is empty).
In your case that won't work because all of the blank lines contain spaces, so pressing the key will swap those lines to the soft bol while the other ones go to the hard bol instead, and you end up with a weird flip-flip that never gets you where you want to be.
One way to fix this would be to use the trim_trailing_white_space command to remove all trailing white space from lines first, in which case you could press Home twice.
This command is the one that gets executed when you save a file and have trim_trailing_white_space_on_save turned on in your preferences, but it's not bound to any keys or menu items by default. So to do that you would first have to bind it to a key, add it to the command palette, turn on the setting and save the content first, etc.
Alternatively you can bind an alternate key (or re-bind the Home key) in your user bindings to specify a to of hardbol instead, which will make that key always jump to column 1 no matter what:
{
"keys": ["home"],
"command": "move_to",
"args": {"to": "hardbol", "extend": false},
}

Related

Deleting to beginning of line - d0 leaves extra space

I am trying to delete an indented line to the beginning of the line, with d0, but that leaves an extra space that I must delete with x.
The use case is that often I want to insert a blank line between two lines, and yes, I could use 'o' or 'O' and 'Esc' but often I enter insert mode out of habit and enter a line. The autoindent in vim adds a line with extra space (even with smartindent) so I am left with some dangling space that I have to delete with 'd0x'.
The extra 'x' seems awkward given that 'D' deletes to the end of the line leaving no extra space, and yes I could use '0D' to do the same with in one less stroke. But I would like your opinions as to the best approach for this situation. Thanks.
Addressing the very specific point of why d0 leaves an extra space: The 0 motion is an exclusive motion, which means the last character towards the end of the region is excluded from the operation.
You can use the v modifier to toggle the characterwise motion and make it inclusive:
dv0
This should remove all the characters from the beginning of the line, including the one under the cursor.
If there's some complicated thing you want to do in vim with minimal keystrokes, the usual approach is to just create a macro for it and bind that macro to a specific key sequence.
For example, for your use case of inserting a blank unindented line, you could just bind to O<ESC>0D (or whatever other key sequence you need). You can test this with the keystrokes (in normal mode, and <ESC> is a single press of the ESC key, not the five individual characters):
qdO<ESC>0Dq
Then just go to some line in your file, enter #d and, voila, an unindented blank line.
To make this permanent, just add it to your vimrc file:
let #d='O<ESC>0D'
where, if you're editing it with vim, ESC can be entered as CTRL-VESC.
Another possibility is to just not worry about indents until some point in the future. By all means, use whatever commands you desire to give yourself a blank line (possibly indented) but either fix that before final write by deleting all trailing tabs and spaces:
:g/[ <TAB>]\+$/s///
or run a script on all files to fix this in a batch operation (even better if this is done as part of automatic pre-checks before source code commit), for example:
find . -name *.cpp -exec sed -iE 's/[ \t]+$//' {} \;

Is it possible to shift lines without moving cursor?

I often move blocks of text around within a file by e.g. marking the top and bottom of a range and then doing :'t,'b>. I find that having completed the shift, the cursor always moves the the line marked by 'b.
When trying to fine tune the actual amount of the shift required I then have to move back to 't, check the indent with respect to the surrounding text and then repeat the shift.
Is there a way to achieve the same result without the cursor moving lines each shift?
I don't think just pressing
`t
to go back to mark t is big effort.
If you don't want to press any key after the cmd execution, you can execute:
:'t,'b>|norm! 't
Or you don't shift lines with command, you do it in normal mode. First go to the mark t , then:
>'b
The block will be shifted and the cursor will be still on mark t.

Difference between append and insert mode in Vim

I noticed this accidentally when playing around in vimtutor. What's the difference between append and insert mode in Vim? When I type a in normal mode (not A) I can insert text. When should I use one and not the other?
The append command will put the cursor after the current position, while the insert command will put the cursor before it.
Using the append command is like moving the cursor one character to the right, and using the insert command.
Using the insert command is like moving the cursor one character to the left, and using the append command.
You choose which depending on where you want to start typing.
Note that vimtutor doesn't initially make the case of the command obvious:
SHIFT+A (capital A, as opposed to a) the cursor moves to the end of the current line.
SHIFT+I (capital I, as opposed to i)moves to the start of the current line.
Another important aspect on Append is that if the position after the current position is a empty space followed by a word. After you are done writing it will concatenate both words.
E.g. A file with the following text:
Hi there.
With the cursor on i. After pressing the a button and then ESC you would have:
Hithere.

Can vim markers work with the repeat key?

I regularly use the . key to repeat my last vim command. I'm wondering if there's a way to use it with commands performed using markers. Here's a simple example:
Mark a line of text using m'a
Move down a few lines, e.g. 5j
Indent the lines using >'a -- indents 6 lines
Press . to repeat above command on the same 6 lines -- will only affect 1st line
Is there a way to get vim to apply the same marker range of the previous command when using the . command?
ps. I know the above example would have been easier with 6>>, which works with the ., I'm just using it as an example. I often use markers for more complex/longer commands.
The problem is that the command you're repeating is >'a, but because of the rule "After applying the operator the cursor is mostly left at the start of the text that was operated upon" (from :help operator), >'a leaves the cursor at mark a if that was above your starting position. Then when you repeat >'a you end up with a linewise motion from that line to itself, which only re-indents one line.
Since you're left at the beginning of the block of text, to affect the same block of text again you can use the '] (linewise) or `] (charwise) motions, which move to the end of the block of text just affected. So you can use >'] to indent the same block again, and since your cursor starts and ends at the same position this time, you can repeat it additional times with ..
A simpler choice, though, would be to just use V5j> instead of ma5j>'a. V starts visual mode (linewise) at your current position, 5j moves down 5 lines, and then > indents. And when you repeat using ., the same visual selection still pertains, so you get the desired result whether you moved up or down.

How do I get fine-grained undo in Vim

I find Vim's undo to be a bit too coarse. E.g. if I type something like this:
a // to go into edit mode
to be or not to ve
<esc> // to exit insert mode
Oops! I made a typo. I want to start undoing so I press u, but then it clears the whole line. Is there a way to undo word-by-word or character-by-character?
You can break undos via :help i_ctrl-g_u. You can map this if you want for every character, but that might a little bit complicated. Mapping this to space button is a way.
:inoremap <Space> <Space><C-g>u
After that every word can be undo via u
So as you see from the others what you are asking for doesn't exist in Vi (AFAIK).
Undo undoes what your last action was. If your last action was to enter insert mode and then add a line and then exit insert mode. That will be undone, however if from the default mode you hit the "x" key then you will delete 1 character or if in visual mode with text selected the text will be deleted. If you hit undo then you will restore that one character or the text that was selected.
...You should think of this as an action, and actions can be atomically undone or restored
As mentioned previously if you wish to delete the previous word then you should be able to hit Ctrl + w and delete the previous word while remaining in insert mode.
If you exit insert mode you can navigate (motion) back a word with "b" forward a word with "w" to the end of a word with "e", and can cut (which leaves you in insert mode) with "c" or delete with "d". Both actions cut and delete can accept a motion following them so you can delete the current word / up to the next word with "dw" or cut the previous word with "cb"
This concept becomes more useful when you remember to use the "." command (in normal mode). This command is to repeat the last action. I have used this many times to find and replace a small group of words in a file (It is especially useful if you are paranoid about changing too much). The scenario would be the following:
File:
This is my post
really it is a test
this is the middle
This is the end
if I wanted to replace "is" with "was" I could write:
%s/\<is\>/was/g
however if I wanted to change the first line and the third line "is" to "was" (and I didn't know their line numbers, and I wanted to see if there were any other places I wanted to change is to was I could type
"/is"
hit "n" until I reach the place I want substituted, and then hit "cw" and type "was"
I can now hit "n" until I reach another place I want substituted and hit ".", and that will replace "is" with "was" (Note: my search string didn't limit to the word "is", just the two characters "is" so "This" & "this" will match in this case)
No, it is not possible and is actually not necessary either. Vim has a million ways of dealing with that. Try cb for example. Or bC. Or brb. Or Tspace to jump back instead of b. Or ciw.
You can, of course use most of these solutions in insert mode (by pressing CTRLo first), or bind one to your favorite key combination (:help map and :help imap).
On Linux, using control-w while in input mode deletes the last 'word'.

Resources