In vim, it is
%s/xxx/=printf(“xxx-%02d”, line(’.’))/
In kakoune, how do you do it?
In vim, it is
%s/xxx/=printf(“xxx-%02d”, line(’.’))/
In kakoune, how do you do it?
what exactly this commands does? I understand that this acts on a whole buffer replacing xxx with, I believe, xxx appended with line numbers after dash?
If so, you don’t need to do replacement. First select all you want to replace with %sxxx<ret>
, then you can do: :exec -itersel "a-%val{cursor_line}"
which will append number line after dash to each selection.
I usually use vim for renaming files. ranger uses vim for bulk-renaming.
I often type
%s/.*/\=printf("2019-12-05|cool cat|%02d.jpg", line('.'))/
The vim snippet didn’t work for me in vanilla vim, but I assume this is the kakoune equivelent:
%sxxx<ret>|printf "%s-%02d" $kak_selection $kak_cursor_line<ret>
That’s the key sequence you’d input from normal mode.
if I understand correctly, you want to assign an incrementing number to your cursors. You can use the #
register for this, which simply contains the index of each selection. For example if you do "#P
in normal mode with multiple cursors, it will paste the index before each selection.
How specifically can I replace each arbitrary line with “xxxxxx-%02d.jpg”?
I want to replace
sdfsdgsdg.jpg
sdfsd098729038749082734.jpg
lkhsadl;gkhas;dlkghasd23452345.jpg
with
2019-12-06|cool cat|01.jpg
2019-12-06|cool cat|02.jpg
2019-12-06|cool cat|03.jpg
2019-12-06|cool cat|04.jpg
In vim,
:%s/.*/\=printf("2019-12-06|cool cat|%02d.jpg", line('.'))/
does this.
%<a-s>|printf "2019-12-06|cool cat|%02d.jpg\n" $kak_cursor_line<ret>
where:
%
- select whole buffer<a-s>
(alt s) - split selection to individual lines|
- pipeprintf "2019-12-06|cool cat|%02d.jpg\n" $kak_cursor_line
- shell command printf
with arguments<ret>
- confirmor even better:
%<a-s>|printf "%s|cool cat|%02d.jpg\n" "$(date)" "$kak_cursor_line"<ret>
That works…
$(date)
is not correct in some shells.$kak_cursor_line
documented?Kakoune uses the system’s POSIX-compatible shell (the first sh
executable in the directories named in the confstr(CS_PATH)
path), or the executable named in $KAKOUNE_POSIX_SHELL
, not the user shell.
Environment variables named like $kak_*
are described in :doc expansions shell-expansions
. That expansion in particular is the shell version of %val{cursor_line}
, which is described in :doc expansions value-expansions
.
How do I use selection indices instead of %val{cursor_line}?
%<a-s>Hc2019-12-06|cool cat|0.jpg<esc><a-f>."#P
where:
%<a-s>
as beforeH
moves the end of each selection left by one character, so it doesn’t include the newline at the end of the line
c
deletes the contents of each selection, and puts you into insert mode.2019-12-06|cool cat|0.jpg<esc>
is just typing the skeleton filename that we want to modify, then leaving insert mode<a-f>.
moves the cursor backwards until it sits on a .
"#P
pastes the selection number before each cursor"#P
doesn’t make anything zero-padded, that’s why the above instructions manually type a 0 in insert mode - there’s only 4 items in your example, so they’re all going to have a 0. If you have more than 9 items (i.e. some lines will have 1 digit, others will have 2), you can reformat the numbers with printf
afterward:
%<a-s>Hc2019-12-06|cool cat|.jpg<esc><a-f>."#Pb|printf %02d $kak_selection
where:
%<a-s>Hc
as before2019-12-06|cool cat|.jpg<esc>
is just typing, but this time we don’t bother typing a 0.<a-f>."#P
as beforeb
moves the cursor back one word (i.e., selecting the numbers we just inserted)|printf %02d $kak_selection
replaces the contents of each selection with the output of the given shell command
printf
doesn’t read from stdin, so it’s provided as an environment variable too|awk '{ printf "%02d", $1 }'
insteadIn general, this is more verbose than the Vim “big ol’ search-and-replace”, but the advantage of Kakoune for me is that the whole thing above is an interactive process, not a complex one-shot command. Where I’ve written <a-f>.
what I would probably do in practice is just hit left-arrow a bunch of times until the cursor was in the right place, since I find it a lot easier to “tweak until it looks right” than memorise the relationships between f
, t
, <a-f>
and <a-t>
. Plus, if I make a mistake in one of those steps, I can just undo and try it again, I don’t have to go all the way back to the beginning of the process and start from scratch.
Why doesn’t
%s<a-s>|printf "%02d.jpg\n" $kak_(main_)reg_hash
work? It’s simpler.
I had a success with
%s<a-s>|echo<ret>i2019-12-06|cool cat|.jpg<esc><a-f>."#Pb|printf "%02d" $kak_selection
Note that you want %<a-s>
, not %s<a-s>
— there’s no “search within selection” step, you want all the selections.
The reason you can’t use $kak_reg_hash
inside a |
command is that the command receives the selection content on standard input. You might have seven lines selected, but you can’t have seven standard inputs, so instead Kakoune runs the command for each selection individually - and an individual selection is always selection number 1, because there’s only one selection.
It’s like the -itersel
flag for the :evaluate-commands
and :execute-keys
commands - see :doc execeval
.
It is
%<a-s>|echo<ret>i2019-12-06|cool cat|.jpg<esc><a-f>."#Pb|printf "%02d" $kak_selection
Can you think of a more concise way with hash register?
30 days late but I have figured out a pretty big brained alternative (if I do say so myself) which is a shorter, arguably a little more complicated but works for any line count.
%<a-s>|echo<ret>i2019-12-06|cool cat|.jpg<esc><a-f>.Z"#PGl&<a-z>us r0
How it works:
"#P
works as before, pasting selection countGl
(that’s a lower case L) selects to the end of the line&
aligns all of your cursors.<a-z>u
basically joins your saved cursor positions with your current ones so now all the <space> characters created by &
are selected. There might be a way to do this without using Z at all.s r0
select all spaces and replace with zeroes.optionally you can add a space in the filename cat| .jpg
if you always want the extra 0. then do an <a-f>
for space rather than .
Edit - Since this works for any line count you should be able to pretty easily define a function that takes one argument (the filename) and performs this operation. But I still haven’t gotten around to learning kak plugins.
Actually I was thinking about this backwards. It’s a lot simpler to do something like:
%<a-s>Z"#PX&<a-x>s r0zI2019-12-06|cool cat|<esc>A.jpg
where you handle the numbers first then prepend/append the rest
I added an arbitrary integer to cursor line number and selection index with
$(($kak_cursor_line + num))
$(($kak_selection + num))
It is POSIX shell syntax.
I finally found a versatile solution.
If I had
01 - product - .jpg
01 - product - .jpg
01 - product - .jpg
01 - product - .jpg
01 - product - .jpg
01 - product - .jpg
01 - product - .jpg
..
I could do
%<a-s><a-f>.hZ"#pe&zlEs <ret>r0
to get
01 - product - 001.jpg
01 - product - 002.jpg
01 - product - 003.jpg
01 - product - 004.jpg
01 - product - 005.jpg
01 - product - 006.jpg
01 - product - 007.jpg
01 - product - 008.jpg
01 - product - 009.jpg
01 - product - 010.jpg
01 - product - 011.jpg
01 - product - 012.jpg
01 - product - 013.jpg
01 - product - 014.jpg
01 - product - 015.jpg
01 - product - 016.jpg
01 - product - 017.jpg
01 - product - 018.jpg
01 - product - 019.jpg
01 - product - 020.jpg
01 - product - 021.jpg
01 - product - 022.jpg
01 - product - 023.jpg
01 - product - 024.jpg
01 - product - 025.jpg
01 - product - 026.jpg
01 - product - 027.jpg
01 - product - 028.jpg
01 - product - 029.jpg
01 - product - 030.jpg
01 - product - 031.jpg
01 - product - 032.jpg
01 - product - 033.jpg
01 - product - 034.jpg
01 - product - 035.jpg
01 - product - 036.jpg
01 - product - 037.jpg
01 - product - 038.jpg
01 - product - 039.jpg
01 - product - 040.jpg
01 - product - 041.jpg
01 - product - 042.jpg
01 - product - 043.jpg
01 - product - 044.jpg
01 - product - 045.jpg
01 - product - 046.jpg
01 - product - 047.jpg
01 - product - 048.jpg
01 - product - 049.jpg
01 - product - 050.jpg
01 - product - 051.jpg
01 - product - 052.jpg
01 - product - 053.jpg
01 - product - 054.jpg
01 - product - 055.jpg
01 - product - 056.jpg
01 - product - 057.jpg
01 - product - 058.jpg
01 - product - 059.jpg
01 - product - 060.jpg
01 - product - 061.jpg
01 - product - 062.jpg
01 - product - 063.jpg
01 - product - 064.jpg
01 - product - 065.jpg
01 - product - 066.jpg
01 - product - 067.jpg
01 - product - 068.jpg
01 - product - 069.jpg
01 - product - 070.jpg
01 - product - 071.jpg
01 - product - 072.jpg
01 - product - 073.jpg
01 - product - 074.jpg
01 - product - 075.jpg
01 - product - 076.jpg
01 - product - 077.jpg
01 - product - 078.jpg
01 - product - 079.jpg
01 - product - 080.jpg
01 - product - 081.jpg
01 - product - 082.jpg
01 - product - 083.jpg
01 - product - 084.jpg
01 - product - 085.jpg
01 - product - 086.jpg
01 - product - 087.jpg
01 - product - 088.jpg
01 - product - 089.jpg
01 - product - 090.jpg
01 - product - 091.jpg
01 - product - 092.jpg
01 - product - 093.jpg
01 - product - 094.jpg
01 - product - 095.jpg
01 - product - 096.jpg
01 - product - 097.jpg
01 - product - 098.jpg
01 - product - 099.jpg
01 - product - 100.jpg
01 - product - 101.jpg
01 - product - 102.jpg
01 - product - 103.jpg
01 - product - 104.jpg
01 - product - 105.jpg
01 - product - 106.jpg
01 - product - 107.jpg
01 - product - 108.jpg
01 - product - 109.jpg
01 - product - 110.jpg
Nice, although it fails if the number of items is less than 10 because s <ret>
selects nothing, fails, and you end up r0
everything.
If the number of items is less than 10, I would use a different key sequence.