Searching for the pattern /{{c\d
, I'd like to get the highest digit found and use it in a macro.
For context, I'm using Anki (flashcard tool) and its cloze card type, and recently started creating my cards within vim.
Example card:
## Front
reading:
{{c1::A::reading A}}
B
{{c2::C::reading C}}
{{c1::D::reading D}}
E
## Back
...
In that example, given I'm positioned above E, I'd like to execute a macro that'll figure out that the highest cloze digit is 2 (in {{c2::C::reading C}}
) and create a new cloze with highest digit incremented by one as {{c3::E::reading E}}
My macro currently looks like this:
:registers
"c ysiw}wysiw}wyiwic3::^OP::reading
ysiw}
uses vim-surround to wrap the word in braces.wysiw}
repeats that operationwyiw
yanks the wordic3::
adds c3::
in insert mode <= How do I calculate 3 from the highest cloze number in the file?^OP
paste the yanked word in insert mode::reading
adds the remaining text.You can use a :%s
command with the [/n
] flag, which doesn't execute the substitution but only counts the matches.
Use that together with a \=
expression on the replacement side, just for the side effects of the expression.
You can use that to append the cloze numbers to a list and then find the maximum after you've collected them all.
function! NextCloze()
let nums = [0]
let view = winsaveview()
silent %s/\m{{c\zs\d\+\ze::/\=add(nums, submatch(0))/egn
call winrestview(view)
return 1 + max(nums)
endfunction
The function is also saving and restoring the view around the %s
operation, since that operation will move the cursor and we want to keep it in place.
To insert it in the middle of a mapping you can use something like:
i{{c<C-R>=NextCloze()<CR>::
Though there are probably other ways you can put that result in your buffer. For instance, if you'd like a mapping that takes the current word under the cursor and replaces it with the {{cN::...::reading ...}}
block, consider these:
nnoremap <Leader>c ciW{{c<C-R>=NextCloze()<CR>::<C-R>"::reading <C-R>"}}<Esc>
xnoremap <Leader>c c{{c<C-R>=NextCloze()<CR>::<C-R>"::reading <C-R>"}}<Esc>
In Normal mode, it will act on the Word (sequence of non-white space symbols) under the cursor. In Visual mode, it will act on the visual selection. These are closer to your original @c
macro.