12

I use multiline strings for SQL queries inside Python programs.

Is there a way to tell Vim to apply different highlighting rules inside them, possibly by using a --SQL marker?

3 Answers 3

11

I copy-pasted-changed from here:

function! TextEnableCodeSnip(filetype,start,end,textSnipHl) abort
  let ft=toupper(a:filetype)
  let group='textGroup'.ft
  if exists('b:current_syntax')
    let s:current_syntax=b:current_syntax
    " Remove current syntax definition, as some syntax files (e.g. cpp.vim)
    " do nothing if b:current_syntax is defined.
    unlet b:current_syntax
  endif
  execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim'
  try
    execute 'syntax include @'.group.' after/syntax/'.a:filetype.'.vim'
  catch
  endtry
  if exists('s:current_syntax')
    let b:current_syntax=s:current_syntax
  else
    unlet b:current_syntax
  endif
  execute 'syntax region textSnip'.ft.'
  \ matchgroup='.a:textSnipHl.'
  \ start="'.a:start.'" end="'.a:end.'"
  \ contains=@'.group
endfunction

au FileType python call TextEnableCodeSnip('sqlpostgres', "'''", "'''", 'SpecialComment')

Now every multiline triple-single-quote string gets the sql syntax. Triple-double-quoted strings are still plain. I've changed sqlpostgres.vim to give SQL nuances of green to differentiate the two languages, and it looks sweet in the 256 colors inkpot scheme.

Also related: Embedded syntax highligting in Vim

Sign up to request clarification or add additional context in comments.

Comments

4

I know there's an accepted answer, but still, here is another way of doing it:

if exists("b:current_syntax")
  finish
endif

" Load Python syntax at the top level
runtime! syntax/python.vim

" Needed to make syntax/sql.vim do something
unlet b:current_syntax

" Load SQL syntax
syntax include @SQL syntax/sql.vim

" Need to add the keepend here
syn region pythonString matchgroup=pythonQuotes
      \ start=+[uU]\=\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
      \ contains=pythonEscape,@Spell keepend
syn region  pythonRawString matchgroup=pythonQuotes
      \ start=+[uU]\=[rR]\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
      \ contains=@Spell keepend

syn region SQLEmbedded contains=@SQL containedin=pythonString,pythonRawString contained
    \ start=+\v(ALTER|BEGIN|CALL|COMMENT|COMMIT|CONNECT|CREATE|DELETE|DROP|END|EXPLAIN|EXPORT|GRANT|IMPORT|INSERT|LOAD|LOCK|MERGE|REFRESH|RENAME|REPLACE|REVOKE|ROLLBACK|SELECT|SET|TRUNCATE|UNLOAD|UNSET|UPDATE|UPSERT)+
    \ end=+;+

let b:current_syntax = "pysql"

With that, highlighting starts at one of the given SQL keywords and stops either at the first ; and can restart on next SQL keyword, or stops at the end of the python string (see keepend).

Comments

0

You can try the following option on your file :
setfiletype=python.sql

It gives both file type to your file, and should apply both syntax highlighting.

If it works for you, you can add the following line to your .vimrc to apply it to every it python file you edit:

autocmd BufRead,BufNewFile *.py setfiletype=python.sql

However, it does not really deal with conflict between the two highlight groups...So it could or could not work in your case.

You could also create a function to quickly toggle the filetype of your open buffer :

function! ToggleFiletype()
  if &filetype=="sql"
    set filetype=python
  endif

  if &filetype=="python"
    set filetype=sql
  endif
endfunction

map <F11> <Esc>:call ToggleFiletype()<cr>

1 Comment

au contraire, it applies sql syntax to python code, and the strings are plain.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.