I know that e.g. 50%
is a normal mode command to go halfway down a file, but [count]%
is line-wise.
How can I get to the halfway point of the line that my cursor is on?
Well, there is no built in way to do it as far as I know, but out of curiosity I have come up with the following:
nnoremap gl :exe 'normal ' . len(getline('.'))/2 . '\|'<CR>
With gl
you will be placed in the "middle" of the line (you know... those odd char counts :)
What it does:
77|
normal command which is "goto 77th char in current line". We have to count proper char count though.:exe
-- execute a command'normal '
-- we want to execute normal command and start to combine it from different strings. len(getline('.'))/2 .
-- calculate the half length of a current line and join it with other parts of a normal command with dots (.)'\|'
this normal command should move the cursor to the given char (we have to escape it though as this bar |
is also used in vimscript)<CR>
-- emits enter to execute :exe
we have constructedI think there might be an easier way but this one works :)
PS
More bulletproof solution with percentage prefix provided by @Jürgen Krämer
nnoremap gl :<c-u>exe 'normal! ' . (strchars(getline('.')) * v:count1 / 100) . '\|'<cr>
30gl
to go to 30% char of the current line.
<c-u>
-- removes range symbols that might be added by vim (just in case)normal!
-- executes normal mode command with default not remapped meanings (like if you have remapped |
command to do smth else and still want to execute default command)strchars
instead of len
-- to properly count length of a unicode line. len
gives you byte count.v:count1
is the built-in variable, count number that you have entered just before pressing normal command itself -- in 50l
it would be 50
that is passed to l
as v:count1
(strchars(getline('.')) * v:count1 / 100)
-- percentage to real char count calculation. So you have a line with 150 length and you have provided 50gl
to go to 50% of the line. 150*50/100
will give you half of the line...........éééééééééé
).
%
, you can use the predefined variable v:count1
: nnoremap gl :<c-u>exe 'normal ' . (len(substitute(getline('.'), '.', 'x', 'g')) * v:count1 / 100) . '\|'<cr>
. With this mapping 50gl
will put the cursor at half of the line, 25gl
will put it at roughly a quarter of the line. Characters with more than one byte are taken care of by reducing all characters to (single byte sized) x
s.
Commented
Jul 10, 2019 at 12:00
nnoremap <leader>% :<c-u>exe 'normal ' . (strchars(getline('.')) * v:count1 / 100) . '\|'<cr>
Commented
Jul 10, 2019 at 12:20
strchars
is better then len
and v:count1
is the way to go too. And normal!
should be used. Sorry, I have just made quick and dirty solution :). But thanks for comments!
Commented
Jul 10, 2019 at 12:38
As of version 8.1.2231 Vim has the gM
command which puts your cursor at the middle of a text line. If you supply a count the count is interpreted as the percentage of the line width, e.g., 33gM
will put the cursor at roughly one third of the text width.
Assume halfway is center of line screen columns.
:h gm moves to window center or as far as possible.
To move to center of a line:
nnoremap <expr> gc virtcol('$')/2 . '<bar>'
:h virtcol() with '$'
return 1 + screen columns of current line
. :h bar move to count
screen column.
IMO, this kind of command is useless most of the time, :h f is the practical way.