Hot answers tagged

15

You could try the following command: :let c=0 | g/^* /let c+=1 | s//\=c.'. ' First it initializes the variable c (let c=0), then it executes the global command g which looks for the pattern ^* (a beginning of line, followed by an asterisk and a space). Whenever a line containing this pattern is found, the global command executes the command: let c+=1 | s//...


9

This only works with a recent Vim version (that has :h v_g_CTRL-A): Block-select the list bullets (*) and replace them with 0 (cursor is on first *): Ctrl-v j j r 0. Reselect previous block and increment with counter: gv g Ctrl-a ... and that's it :) (If you want to have a dot after each number, change 1st step to: Ctrl-v j j s 0 . Esc)


9

Visually select the lines and execute this substitution command: :'<,'>s/*/\=line('.') - line("'<") + 1 . '.' See :help sub-replace-expression, :help line(), and :help '<. To avoid having to select the lines, backward and forward searches with offsets can be used to specify the substitution range like this: :?^[^*]?+1,/^[^*]/-1s/*/\=line('.') ...


9

See this answer on stackoverflow. The example given is: function! PrintGivenRange() range echo "firstline ".a:firstline." lastline ".a:lastline " Do some more things endfunction command! -range PassRange <line1>,<line2>call PrintGivenRange() Thus you might want to create a function which would use the range and do the tmux call ...


7

In :<from>,<to>command, both <from> and <to> are relative to the current line. What you want is to make <to> relative to <from>. For this you need :help :;: :/foo/;,/bar/command where the cursor is moved to /foo/ first, which becomes the current line. :/<table class=.bar\_.\{-}\zs<tr/;,/table>/sort! n /.\{-}&...


7

A If you just want to quickly confirm the validity of the range (and it isn't too long), you can use the built-in :print or :number: :/<head/,/\/head>/print B Another idea would be (mis-)using the visual selection. The following custom command creates a linewise selection of the passed range: ":[range]SelectRange Create a linewise visual ...


7

You can use :write for this: :'<,'>w !copy_stuff For more details, see :help :write_c: Execute {cmd} with [range] lines as standard input (note the space in front of the '!').


6

The format for :m[ove] is :[range]m[ove] {address} Where the range is the line or lines you want to move and the address is the target. Note that the moved line(s) will actually be placed on the line below the address. So you're looking for a range of "mark a" and an address of "the current line". You can find all the special names for ...


5

To get the count given to <C-E>, you don't need to use the range to do it. There are two pre-defined variables you can use, v:count and v:count1, which contain the count given to the last normal mode command. The former should work for you, as it will be zero when no count has been given. The latter defaults to 1 in same situation. Here is a minimal ...


5

In the very general case, the :g command cannot be called recursively. There is one exception: Since Vim patch 8.0.0630, one can call a recursive :g command, if it operates only within a single line. So you can do something like (quoting the help): When the command is used recursively, it only works on one line. Giving a range is then not allowed. This ...


4

When using counts and calling functions a range will be inserted automatically by Vim. You can see this by doing simply doing 3:. A common solution is to use <c-u> to remove the range. See :h c_CTRL-U for more help. nmap YY :<c-u>call Clipboard()<CR> However there are a bunch of issues worth going over: You should generally avoid ...


4

As I said in the comments I strongly recommend a plugin like nerdcommenter or vim-commentary to do stuff like this because they are well tested and handle a lot of corner cases. Now if you want to do it by yourself a solution could be the following. First create a function which takes two numbers as arguments and uses these numbers as the lines on which it ...


4

I looked into this, and I could not find a direct way of doing it. However, one possibility is to create an auxiliary function, that is: function! Range() range abort return RangeAux(a:firstline, a:lastline) endfunction function! RangeAux(lnum1, lnum2) abort echo a:lnum1 echo a:lnum2 endfunction 1,3call Range() call RangeAux(1,3)


4

Using ex Ex is the command-line successor to the venerable ed, a line-oriented editor. You can access ex-mode from vim by typing Q (unless you have it mapped). gQ gives an improved ex-mode. See :help Ex-mode. You can also start ex from the command line, just like vim: ex {file} Then you type your commands, and ex does them. All the :-style commands ...


3

I could be wrong but I think the atom \ze does take effect, it just doesn't prevent Vim to find a match on the group3 line. It's an empty match since you write \ze just after the anchor ^ which excludes everything afterwards. But even if it's empty, it's still something, the beginning of the line. Maybe you could use an offset: :/group2\n\zs/;,/^\ze\S/- p ...


3

Use :execute and concatenation: let startline = 2 let endline = 56 let searchpattern = "foo" let replacepattern = "bar" execute startline . "," . endline . "s/" . searchpattern ."/" . replacepattern . "/g" Alternative: let cmd = startline . "," . endline . "s/" . searchpattern ."/" . replacepattern . "/g" execute cmd


3

You can express the penultimate line with $-1. So, in your case, to prepend X in front of all the lines from the fifth down to the second to last one, you could use the following substitution command: :5,$-1s/^/X You can find more information on how to write a range in :help :range.


3

Well actually you can use a litteral <ESC> character to chain commands like you would do normally: :'<,'>norm! A,^II+ This will insert a , at the end of each line, and a + at the start. To add the special ^I char, press C-v and ESC.


3

Here is a workaround: ex -sc '1,-10d|x' f.txt 1,-10 select all but last 10 lines d delete x save and close


3

Here is a solution which comes from here. Note that might not be exactly what you're looking for since it's implies to use a visual (or normal) mode mapping instead of just an ex command. The idea is to create the following mapping which will allow you to keep in your buffer only the visually selected lines: vnoremap <key> :<C-U>1,'<-1:...


3

You can use the :yank ex command: :/pattern1/;/pattern2/yank a a is the register you want to use and has a default value. Note: You used ;, in your command. It should be either ; or ,, not both.


3

Short answer: no. You can use the :global command to pick some lines to operate on, and then give a sequence of commands to operate on those selected lines: :3,4 g/^/ > | m1 We're only interested in the range, but :g also wants a pattern. So in this case we'll just use /^/ which will always match in a line. This however moves each line in sequence ...


3

@Karl's answer is pretty good but you can also use execute(): echo execute("1,2call Range()") You can even use variables for the range: let l1=1 let l2=2 echo execute(l1 . "," . l2 . "call Range()")


3

ex -s +'norm! gg"adiwdd' +'exec printf("%%s/^/%s : /", @a)' +'x' ex_txt norm! gg"adiwdd delete black in 1st line to register a, delete first line exec printf("%%s/^/%s : /", @a) add content of register a to start of every line. You can get content of register a via @a or getreg('a') in ex mode . check :h printf() if you have problem with %%. x save and exit ...


3

@D.BenKnoble has already given you a terrific answer explaining all the ins and outs of batch mode, but in case you were looking for a one liner similar to the one you already tried, here's one that I think is a bit simpler than the existing ones in the current answers: ex -sc 'norm!ggy$dd' -c '%norm!i^R0: ' -c 'x' file The first :normal command moves to ...


3

A range with commands is always about lines. It seems you want to work with line/column positions. Whether a range was given can be checked by using <range>: command! -range Test call TestFunc(<range>,<line1>,<line2>) function! TestFunc(r,l1,l2) abort if a:r == 0 echo "No range" elseif a:r == 1 echo "Single ...


3

Using the -range flag when defining a user-command usually allows the user to provide a range to the command: command -range Mine echo <range> <line1> ',' <line2> %Mine 1,/bar/Mine " the next one is equivalent to .Mine by default Mine However, sometimes you want to be able to do 0Mine Or else use the number provided as a <count>: ...


2

Per @statox comment... Using normal commands applied to ranges is the same as when they are used in scripts, requiring the normal function to be called. :?^[^\/][^\/]?+1,/^[^\/][^\/]/-1norm gq A very common example of this is applying a macro to each line in a visually selected area. Lets say you want to uppercase the last word on each line: qq$viwUq If ...


2

Another way: :let n = 1 | g/^* /s//\=printf('%d. ', n)/g | let n = n + 1


2

Here are two functions that you could use. Both takes as argument a pattern to search and a command to execute on the consecutive lines matching the pattern. You can call them with: call RangeFromPattern("^\s*-", "!sort -u") The first one goes to the first line of the buffer, searches for the first line matching the pattern, then goes to the last line of ...


Only top voted, non community-wiki answers of a minimum length are eligible