├── .gitignore ├── ftdetect └── nestedtext.vim ├── ftplugin └── nestedtext.vim ├── README.md ├── indent └── nestedtext.vim └── syntax └── nestedtext.vim /.gitignore: -------------------------------------------------------------------------------- 1 | examples.nt 2 | tests 3 | -------------------------------------------------------------------------------- /ftdetect/nestedtext.vim: -------------------------------------------------------------------------------- 1 | autocmd BufNewFile,BufRead *.nt set filetype=nestedtext 2 | -------------------------------------------------------------------------------- /ftplugin/nestedtext.vim: -------------------------------------------------------------------------------- 1 | if exists("b:did_ftplugin") 2 | finish 3 | endif 4 | let b:did_ftplugin = 1 5 | 6 | setlocal expandtab 7 | if get(g:, 'nestedtext_recommended_style', 1) 8 | setlocal softtabstop=4 shiftwidth=4 9 | endif 10 | setlocal formatoptions+=r 11 | setlocal comments=:#,b:>,b:-,b:: 12 | " the comments option causes vim to add "# ", "> ", "- ", or ": " on lines 13 | " following a line with the same leading characters, which allows you easily 14 | " to continue comments, multiline strings, lists and multiline keys. 15 | setlocal commentstring=#\ %s 16 | let b:undo_ftplugin = 'setlocal et< sw< sts< fo< comments< cms<' 17 | if get(g:, 'nestedtext_folding', 0) 18 | setlocal foldmethod=indent 19 | let b:undo_ftplugin .= ' fdm<' 20 | endif 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NestedText plugin for Vim 2 | ========================= 3 | `vim-nestedtext` is a vim plugin that provides syntax highlighting and a handful 4 | of sensible settings for the [NestedText 3.0](https://nestedtext.org) file 5 | format. 6 | 7 | Installation 8 | ------------ 9 | This plugin is compatible with both vim and neovim, and can be installed 10 | using any of the plugin management systems out there: 11 | 12 | ### [pathogen](https://github.com/tpope/vim-pathogen) 13 | 14 | Clone this repository into your `.vim/bundle` directory: 15 | 16 | cd ~/.vim/bundle 17 | git clone git://github.com/kalekundert/vim-nestedtext.git 18 | 19 | ### [vim-plug](https://github.com/junegunn/vim-plug) 20 | 21 | Put the following line(s) in the `call plug#begin()` section of your `.vimrc` 22 | file: 23 | 24 | Plug 'kalekundert/vim-nestedtext' 25 | Plug 'Konfekt/FastFold' 26 | 27 | ### [Vim8 native plugins](https://vimhelp.org/repeat.txt.html#packages) 28 | 29 | Clone the repository into `.vim/pack/*/start`: 30 | 31 | mkdir -p ~/.vim/pack/git-plugins/start 32 | cd ~/.vim/pack/git-plugins/start 33 | git clone git://github.com/kalekundert/vim-nestedtext.git 34 | 35 | Note that you can name the directories in `.vim/pack/` whatever you like, so 36 | the `git-plugins` name in the snippet above is just an example. 37 | 38 | Features 39 | -------- 40 | - Syntax highlighting 41 | - Show trailing whitespace 42 | - Indent-based folding: enable with `let g:nestedtext_folding = 1` in your 43 | vimrc 44 | 45 | Feedback 46 | -------- 47 | Please feel free to create an 48 | [issue](https://github.com/kalekundert/vim-nestedtext/issues) or a [pull 49 | request](https://github.com/kalekundert/vim-nestedtext/pulls) if you have any 50 | trouble with this plugin. 51 | -------------------------------------------------------------------------------- /indent/nestedtext.vim: -------------------------------------------------------------------------------- 1 | if exists('b:did_indent') 2 | finish 3 | endif 4 | 5 | let b:did_indent = 1 6 | 7 | setlocal indentexpr=GetNestedTextIndent(v:lnum) 8 | setlocal indentkeys=0{,0[,0>,0-,<:>,0#,!^F,o,O 9 | setlocal nosmartindent 10 | let b:undo_indent = "setl inde< indk< si<" 11 | 12 | let s:list_item = '^ *-\%( \@=\|$\)' 13 | let s:key_tag = '^ *:\%( \@=\|$\)' 14 | let s:inline_key = '^ *[^[:space:]#>{[:-].\{-}:\%( \@=\|$\)' 15 | let s:dict_item = '\%(' . s:key_tag . '\|' . s:inline_key . '\)' 16 | 17 | function! s:MatchIndent(prevlnum, seek) abort 18 | let lnum = a:prevlnum 19 | let max_indent = indent(lnum) 20 | while lnum > 0 && getline(lnum) !~# s:list_item . '\|' . s:dict_item 21 | let lnum = prevnonblank(lnum-1) 22 | if max_indent > indent(lnum) 23 | let max_indent = indent(lnum) 24 | endif 25 | endwhile 26 | while lnum > 0 27 | if indent(lnum) <= max_indent && getline(lnum) =~# a:seek 28 | return indent(lnum) 29 | endif 30 | let lnum = prevnonblank(lnum-1) 31 | endwhile 32 | return -1 33 | endfunction 34 | 35 | function! GetNestedTextIndent(lnum) abort 36 | let prevlnum = prevnonblank(a:lnum-1) 37 | let prevline = getline(prevlnum) 38 | let line = getline(a:lnum) 39 | if !prevlnum 40 | return 0 41 | elseif prevline =~# s:key_tag 42 | if line =~# '^ *[^#: ]' || indent(a:lnum) > indent(prevlnum) 43 | return indent(prevlnum) + shiftwidth() 44 | endif 45 | elseif prevline =~# '\%(' . s:list_item . '\|' . s:inline_key . '\) *$' 46 | if line =~# '^ *\%([[{>]\|$\)' || indent(a:lnum) > indent(prevlnum) 47 | return indent(prevlnum) + shiftwidth() 48 | endif 49 | elseif line =~# s:dict_item 50 | return s:MatchIndent(prevlnum, s:dict_item) 51 | elseif line =~# s:list_item 52 | return s:MatchIndent(prevlnum, s:list_item) 53 | elseif line =~# '^ *>' && prevline =~# '^ *>' 54 | return indent(prevlnum) 55 | elseif indent(a:lnum) > indent(prevlnum) 56 | return indent(prevlnum) 57 | endif 58 | return -1 59 | endfunction 60 | -------------------------------------------------------------------------------- /syntax/nestedtext.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | syntax match nestedtextError "^\t\+" 6 | 7 | syntax match nestedtextDictKey "^ *\zs[^[:space:]{[].\{-}: "he=e-2 nextgroup=nestedtextString 8 | syntax match nestedtextDictKey "^ *\zs[^[:space:]{[].\{-}:$"he=e-1 9 | 10 | syntax match nestedtextListTag "^ *\zs- " nextgroup=nestedtextString 11 | syntax match nestedtextListTag "^ *\zs-$" 12 | 13 | syntax match nestedtextStringTag "^ *\zs> " nextgroup=nestedtextString 14 | syntax match nestedtextStringTag "^ *\zs>$" 15 | 16 | syntax match nestedtextKeyTag "^ *\zs: " nextgroup=nestedtextKey 17 | syntax match nestedtextKeyTag "^ *\zs:$" 18 | 19 | syntax match nestedtextKey ".*$" contained 20 | syntax match nestedtextString ".*$" contained 21 | 22 | syntax match nestedtextInline "\[.*\]" contains=nestedtextInlineList 23 | syntax region nestedtextInlineList start="\[" end="\]" contained oneline contains=@nestedtextInlineListValue 24 | syntax cluster nestedtextInlineListValue contains=nestedtextInlineListString,nestedtextInline 25 | syntax match nestedtextInlineListString "[^{}[\],]*" contained 26 | 27 | " commas are pretty much ignored in inline dictionaries 28 | syntax match nestedtextInline "{.*}" contains=,nestedtextInlineDict 29 | syntax region nestedtextInlineDict start="{" end="}" contained oneline contains=nestedtextInlineDictItem 30 | syntax match nestedtextInlineDictItem "[^{}[\],:]*:" contained nextgroup=@nestedtextInlineDictValue 31 | syntax cluster nestedtextInlineDictValue contains=nestedtextInlineDictString,nestedtextInline 32 | syntax match nestedtextInlineDictString "[^{}[\],:]*" contained 33 | 34 | syntax match nestedtextComment "^ *\zs#.*$" 35 | 36 | 37 | hi def link nestedtextError Error 38 | hi def link nestedtextComment Comment 39 | 40 | hi def link nestedtextListTag Normal 41 | hi def link nestedtextStringTag Normal 42 | hi def link nestedtextKeyTag Normal 43 | hi def link nestedtextDictKey Label 44 | hi def link nestedtextKey Label 45 | hi def link nestedtextString String 46 | 47 | hi def link nestedtextInline Normal 48 | hi def link nestedtextInlineList Normal 49 | hi def link nestedtextInlineDict Normal 50 | hi def link nestedtextInlineListString String 51 | hi def link nestedtextInlineDictString String 52 | hi def link nestedtextInlineDictItem Label 53 | 54 | let b:current_syntax = "nestedtext" 55 | --------------------------------------------------------------------------------