neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

graphql.vim (2901B)


      1 " Vim indent file
      2 " Language:	graphql
      3 " Maintainer:	Jon Parise <jon@indelible.org>
      4 " Filenames:	*.graphql *.graphqls *.gql
      5 " URL:		https://github.com/jparise/vim-graphql
      6 " License:	MIT <https://opensource.org/license/mit>
      7 " Last Change:	2024 Dec 21
      8 
      9 " Set our local options if indentation hasn't already been set up.
     10 " This generally means we've been detected as the primary filetype.
     11 if !exists('b:did_indent')
     12  setlocal autoindent
     13  setlocal nocindent
     14  setlocal nolisp
     15  setlocal nosmartindent
     16 
     17  setlocal indentexpr=GetGraphQLIndent()
     18  setlocal indentkeys=0{,0},0),0[,0],0#,!^F,o,O
     19 
     20  let b:did_indent = 1
     21 endif
     22 
     23 " If our indentation function already exists, we have nothing more to do.
     24 if exists('*GetGraphQLIndent')
     25  finish
     26 endif
     27 
     28 let s:cpo_save = &cpoptions
     29 set cpoptions&vim
     30 
     31 " searchpair() skip expression that matches in comments and strings.
     32 let s:pair_skip_expr =
     33  \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "comment\\|string"'
     34 
     35 " Check if the character at lnum:col is inside a string.
     36 function s:InString(lnum, col)
     37  return synIDattr(synID(a:lnum, a:col, 1), 'name') ==# 'graphqlString'
     38 endfunction
     39 
     40 function GetGraphQLIndent()
     41  " If this is the first non-blank line, we have nothing more to do because
     42  " all of our indentation rules are based on matching against earlier lines.
     43  let l:prevlnum = prevnonblank(v:lnum - 1)
     44  if l:prevlnum == 0
     45    return 0
     46  endif
     47 
     48  " If the previous line isn't GraphQL, assume we're part of a template
     49  " string and indent this new line within it.
     50  let l:stack = map(synstack(l:prevlnum, 1), "synIDattr(v:val, 'name')")
     51  if get(l:stack, -1) !~# '^graphql'
     52    return indent(l:prevlnum) + shiftwidth()
     53  endif
     54 
     55  let l:line = getline(v:lnum)
     56 
     57  " If this line contains just a closing bracket, find its matching opening
     58  " bracket and indent the closing bracket to match.
     59  let l:col = matchend(l:line, '^\s*[]})]')
     60  if l:col > 0 && !s:InString(v:lnum, l:col)
     61    call cursor(v:lnum, l:col)
     62 
     63    let l:bracket = l:line[l:col - 1]
     64    if l:bracket ==# '}'
     65      let l:matched = searchpair('{', '', '}', 'bW', s:pair_skip_expr)
     66    elseif l:bracket ==# ']'
     67      let l:matched = searchpair('\[', '', '\]', 'bW', s:pair_skip_expr)
     68    elseif l:bracket ==# ')'
     69      let l:matched = searchpair('(', '', ')', 'bW', s:pair_skip_expr)
     70    else
     71      let l:matched = -1
     72    endif
     73 
     74    return l:matched > 0 ? indent(l:matched) : virtcol('.') - 1
     75  endif
     76 
     77  " If we're inside of a multiline string, continue with the same indentation.
     78  if s:InString(v:lnum, matchend(l:line, '^\s*') + 1)
     79    return indent(v:lnum)
     80  endif
     81 
     82  " If the previous line ended with an opening bracket, indent this line.
     83  if getline(l:prevlnum) =~# '\%(#.*\)\@<![[{(]\s*$'
     84    return indent(l:prevlnum) + shiftwidth()
     85  endif
     86 
     87  " Default to the existing indentation level.
     88  return indent(l:prevlnum)
     89 endfunction
     90 
     91 let &cpoptions = s:cpo_save
     92 unlet s:cpo_save