16

I'm struggling with learning vim regexps (I don't know any other regexp very well either), so the main problem is to define regexp that would match

some_function_call(simple_value, keyword=value)

keyword in this example.

So it should match a word if it's inside parens and have equal sign after it.

The next problem is how to define syntax files in vim. I would appreciate help with that, but It shouldn't be that hard to learn, so I can do that on my own probably.

EDIT based on the answer I've maid my own syntax script for python. Feel free to try it. enter link description here

  • There is an open issue on Github for keyword highlighting to be included in the most up-to-date Python syntax file I am aware of: github.com/hdima/python-syntax/issues/44 You might want to check there later. If you figure out how to do it, please let the people there know (or message me so I can create a pull request) for this feature to be available for everyone. – cbaumhardt Mar 1 '16 at 17:33
  • 1
    Yeah, I'm the one who have opened it. – user1685095 Mar 1 '16 at 17:37
12
+50

With these settings:

syn region FCall start='[[:alpha:]_]\i*\s*(' end=')' contains=FCall,FCallKeyword
syn match FCallKeyword /\i*\ze\s*=[^=]/ contained
hi FCallKeyword ctermfg=yellow

I get:

enter image description here

Here:

  1. I define a syntax region within which keyword arguments can be found, which would be the function call. The contains option lets me nest function calls.
  2. Within that region, I match any string made of valid identifier characters (\i*) followed by =, but not ==, so that equality tests are not matched.

By using regions, I get to nest the matches as much as I need, which would have be very complicated (impossible?) if I'd gone for just a match with regular expressions.

I believe the regular expressions used for matching the function call and the keyword can be refined, but considering what's valid in Python 3, that's not a task I'm willing to take on.

Optionally, I think you can use this to highlight function calls, using a matchgroup:

syn region FCall matchgroup=FName start='[[:alpha:]_]\i*\s*(' end=')' contains=FCall,FCallKeyword
syn match FCallKeyword /\i*\ze\s*=[^=]/ contained
hi FCallKeyword ctermfg=yellow
hi FName ctermfg=blue

enter image description here

  • I probably should create another question, but do you have ideas about how to highlight only builtin functions? – user1685095 Mar 23 '16 at 10:35
  • @user1685095 Builtin functions are listed out in the pythonBuiltin syntax group in the default syntax/python.vim. However, it doesn't distinguish between functions and builtin variables (True, False and None are also in pythonBuiltin). You could probably copy the definitions for your use. – muru Mar 23 '16 at 13:06
  • Well, I've used more refined syntax then vim default like hdima/python and vim-polyglot. They all define builtin functions like a keyword which have important consequence. Not only builtin functions are highlighted, but just variable with same names and functions in other modules with the same name are highlighted. Like query(...).***filter***() filter is highlighted while it doesn't have anything to do with builtin filter functions. – user1685095 Mar 23 '16 at 13:11
  • @user1685095 the default syntax.vim does make them keywords. See github.com/vim/vim/blob/master/runtime/syntax/python.vim#L184 – muru Mar 23 '16 at 13:22
  • 1
    @user1685095 Odd. I don't have additional syntax/python.vim files (only the default, and I don't see the behaviour you do: i.stack.imgur.com/LgF6F.png, and I agree with the keyword definition - that's the closest fit, and I don't think keywords are matched in cases like nonkeyword.keyword. As for variables, note that these builtins are variables, they're variables containing function objects, and can be assigned to just like any other variables. Nothing prevents you from doing sorted = filter and then using sorted like filter. – muru Mar 23 '16 at 14:08
8

Here is where you can start from:

/([^,]\+,\s\(\w\+\)=.*)

Decomposing:

/(       start matching a (
[^,]\+   match multiple characters that are not ,
,\s      match a , and a space
\(       start a matching group
\w\+     match word characters
\)       end the matching group
=.*)      match an = and anything until the closing )

This needs improvements but gives you an overview of how you can do it.

6

In addition to @Nobe4 answer you could do the following:

  • Create the file ~/.vim/after/syntax/python.vim
  • Put theses line in the file:

    syntax match PythonArg /(.*\,\s*\zs\w\+\ze\s*=.*)/
    hi PythonArg guibg=blue
    
  • Adapt the second one with your prefered values.

This will create a syntax file which will add a syntax match for your arguments followed by a = and set the style to use. This topic :h mysyntaxfile-add should be interesting for you.

Also I used a different regex than the other answer, here is the detail (I don't know which one works better so you'll probably have to try):

(      Begin the pattern with a bracket
.*,    Look for any number of any character before a ,
\s*    Zero or more white spaces after the ,
\zs    Start the matching group (what will be highlighted)
\w\+   Match one or more word characters
\ze    End the matching group
\s*    Zero or more white spaces between your argument and the = sign
=      A literal = sign after your argument
.*)    Any number of any characters between your = sign and the closing bracket
  • Thanks for you help. I didn't know that I can add my custom syntax without modifying existing rules. Your pattern doesn't match keyword argument if it's a first argument in function. I'll try to fix that myself (I'm learning regexps right now to do that). As soon as I will learn how to do that I will post a comment. – user1685095 Mar 4 '16 at 10:07
  • I'm trying this regexp via vim search and I think that it matches only one keyword in function call. I need it to match all of them' – user1685095 Mar 4 '16 at 10:16
  • @user1685095: Yep you're right my pattern isn't good. I'll try to improve it and edit my answer. – statox Mar 4 '16 at 10:23
2

The as-of-writing accepted answer broke highlighting for strings inside function argument lists for me (by what alchemy I do not know), so here's a hopefully more safe version, based on Statox' one.

syntax match PythonArg "\v[\(\,]\s{-}\zs\w+\ze\s{-}\=(\=)@!"
hi PythonArg ctermfg = 214 guifg = #ffaf00

ctermfg is for console terminal, guifg is for gui. Of course you're free to change the colors to whatever you find fancy. Here's a handy list.

As always, you do best putting this inside ~/.vim/after/syntax/python.vim

For a regex breakdown, here you go:

\v      set to very magic mode
[\(\,]  capture either a ( or a ,
\s{-}   capture whitespace, nongreedy
\zs     start of the match (what to actually highlight)
\w+     one or more alphanumeric character, underscore included
\ze     stop matching; anything after this is delimiting only
\s{-}   once again, capture whitespace.
\=      one single equal sign
(\=)@!  ...not followed by another equal sign

The final check stops the highlighting from coloring conditionals. You can remove if it you want.

  • Sorry, you're to late. I've maid syntax file for myself. – user1685095 Oct 15 '16 at 17:21
  • That's fine; if someone else runs into the same issue I did they can take a peek here hopefully. – Wolfie Oct 15 '16 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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