2

I'm trying to modify my filetype.vim such that it highlights a unified diff file with diff syntax, overriding whatever syntax is normally associated with the file's extension.

So far, I'm just trying to see if the first line in the file begins with ---. However, what I have will treat the file as a diff if any line begins with ---.

au BufRead,BufNewFile *
  \ if search('^---', "n") |
  \   set filetype=diff |
  \ endif
augroup END

I've tried various combinations of setting the cursor position, adding a stop parameter to search, but nothing I've tried works.

2
  • 1
    Your checks will need to be smarter, since YAML is supposed to start with this same marker.
    – D. Ben Knoble
    Mar 16, 2020 at 13:16
  • 1
    Yes, it was just a proof of concept. I'm going to be testing the first three lines, for ---, +++ and @@, respectively.
    – Len
    Mar 16, 2020 at 21:57

1 Answer 1

2

One simple tweak is to use \%^ which only matches at the start of the file.

You'll also want to pass search() a 'c' flag, to match at the current cursor position (which should be the start of the file.)

au BufRead,BufNewFile *
  \ if search('\%^---', "cn") |
  \   set filetype=diff |
  \ endif

Another option would be to use getline(1) to get the contents of the first line only and then use match() on it.

if match(getline(1), '^---') >= 0 | ...

You can also use the pattern matching operator =~# instead of match(). (The # at the end makes it case insensitive, which doesn't matter much in this example but it's a good practice to use it explicitly.)

if getline(1) =~# '^---' | ...

Either should be fine for your use case.

4
  • 1
    getline() is perfect, because I'm going to want to check the second and third lines too, and I can use the same technique. Excellent. Thank you!
    – Len
    Mar 16, 2020 at 7:36
  • 1
    Could you also use =~# with getline()? I’ve had some recent difficulty making the pattern-match operator work like I wanted (I don’t remember what exactly) and would be grateful for another set of eyes :)
    – D. Ben Knoble
    Mar 16, 2020 at 13:17
  • @D.BenKnoble Yes, good point! In fact all cases in the shipped filetype.vim use =~ or !~, for example: github.com/vim/vim/blob/v8.2.0/runtime/filetype.vim#L1853 Updated the answer to include a =~# solution. In my testing, worked right as expected.
    – filbranden
    Mar 16, 2020 at 13:38
  • 1
    Perfect! What I ended up going with is if getline(1) =~ '^--- ' && getline(2) =~ '^+++ ' && getline(3) =~ '^@@ '. Does the job beautifully. Thanks again.
    – Len
    Mar 19, 2020 at 1:17

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.