0

I am trying to make a mapping that performs what f would normally do if there is a character match on the line, and to do something else if no such character exists. For example, suppose if I had the following line of text.

The dog _runs fast,

where the _ represents my cursor position. If I press fa, I would want my cursor to be on a as normal, but if I press fx, then I want to add additional functionality. I have looked into something like retrieving the number of occurrences of a character with search(), but I'm don't think there is a range option that only searches the current line past the cursor.

For context, my goal is to make a mapping like f, F, etc... that wraps around the current line. So that (in the case of f), if there is no matching character past my cursor, it will then search for the same character starting from the beginning of the line.

Thank you

1
  • search() does have stopline, though there may be easier ways
    – D. Ben Knoble
    Commented Feb 12, 2021 at 22:09

1 Answer 1

1

You could check if the cursor is in the same position after the forward jump, and, if not, carry out your alternative functionality.

Here's a replacement for f to wrap around lines. (It will jump to the start of the line if the character is not on the line. If you want to avoid that, you could include another comparison.)

function!Neweff()
        let character = nr2char(getchar())
        let beforejump = getpos('.')
        execute 'norm! f'.character.''
        let afterjump = getpos('.')
        if beforejump == afterjump
                execute 'norm! 0f'.character.''
        endif
endfunction
nnoremap f :call Neweff()<CR>

See :help getchar() (there are some nice examples here) and :help getpos().

This doesn't quite answer your question of how to check if there is a character match on the line (one could check if the cursor is in the same position after both a forward and backward match); there's probably a nicer method.

3
  • Thank you! That helped me with the map for wrapping f. One modification I made to make it more robust is by adding ``` if beforejump == afterjump let firstcharacter = getline(".")[0] execute 'norm! 0' if character !=# firstcharacter execute 'norm! f'.character.'' endif endif ``` to account for the case in which the searched for character is in column 0.
    – intz
    Commented Feb 13, 2021 at 2:28
  • I'm not sure how to format multi line code in comments. If someone knows how, it would be appreciated feedback.
    – intz
    Commented Feb 13, 2021 at 2:33
  • You check for a match in the line with getline('.') =~# character
    – D. Ben Knoble
    Commented Feb 13, 2021 at 14:23

Your Answer

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

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