2

I have a file that looks something like this

\usepackage{tex/Forkurs-1p-2p-laererutdanning-2018-V}

\usepackage{../Sty/hyper}

\begin{document}

\input{tex/Forkurs-1p-2p-laererutdanning-2018-V-frontmatter.tex}

\input{tex/Forkurs-1p-2p-laererutdanning-2018-V-del-1.tex}

\input{tex/Forkurs-1p-2p-laererutdanning-2018-V-del-2.tex}

\end{document}

I am trying to create two commands

nmap <leader>en
nmap <leader>ep

To increase and decrease the year in the file and swap H with V and V with H. Invoking <leader>en should increase the year when the year is preceeded by an H. e.g YEAR-H. While the command should swap H with V and V with H.

2018-V
2018-H
2019-V
2019-H
2020-V
2020-H
.
.
.

Similarly <leader>ep should decrease the numbers when the number is preceeded by V. Always swap V with H and vice versa.

2018-V
2017-H
2017-V
2016-H
2016-V
2015-H
.
.
.

However I am not sure how to perform a conditional search replace from vim. Any suggestions?

EDIT: To clarify the increase function should work like this

IF H 
   Increase year
Toggle VH (Change H to V and V to H)

So only increase the year when the text contains YEAR-H. Always swap H and V.

The decrease function should work similarly

IF V
   Decrease year
Toggle VH (Change H to V and V to H)

So only decrease the year when the text contains YEAR-V. Always swap H with V and vice-versa.

1 Answer 1

1

The requirements, which were unclear originally, have been updated. Result: much of my original answer is out the window. Here's the new one...

We can't reasonably wedge logic into global commands and/or Normal mode commands so in this case it makes more sense to use a function...to be called from a sub-replace-expression

The function:

func! ProcessYHV(in, incr) 
    let l:year = strcharpart(a:in, 0, 4)
    let l:code = strcharpart(a:in, 5, 1)
    if l:code == "H"
        if a:incr
            let l:year = l:year + 1
        endif
        let l:code = "V"
    else
        if ! a:incr
            let l:year = l:year - 1
        endif
        let l:code = "H"
    endif
    return l:year . "-" . l:code
endfunc

First parameter is a string that matches the key pattern, \d\{4}-[HV], second parameter is "boolean" (0 or 1) that determines if it's an increment or decrement operation, and the function returns the proper replacement string based on the specified logic.

Then we just use this function in a substitution command by leveraging expression evaluation...

:%s/\d\{4}-[HV]/\=ProcessYHV(submatch(0), 1)/    " decrement
:%s/\d\{4}-[HV]/\=ProcessYHV(submatch(0), 0)/    " increment

This "sub-replace-expression" (help link at beginning of this answer) works like this: everything to the right of the \= is evaluated as an expression and the result becomes the replacement text. submatch(0) returns the entire pattern match and we're passing that as the first param to our function.

The mappings...

:nnoremap <Leader>en :%s/\d\{4}-[HV]/\=ProcessYHV(submatch(0), 1)/<cr>
:nnoremap <Leader>ep :%s/\d\{4}-[HV]/\=ProcessYHV(submatch(0), 0)/<cr>
1
  • 1
    You were on the right track with sub-replace-expression and submatch.
    – B Layer
    Jun 9, 2019 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.