From 133f9b1169e130497feee30301806a803b58b695 Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Sun, 31 May 2026 07:18:25 +0200 Subject: [PATCH] Neovim rework. Consolidated modules into a single file. Added syntax files over using treesitter. --- config/nvim/after/syntax/c.vim | 87 +++ config/nvim/after/syntax/go.vim | 825 ++++++++++++++++++++++++ config/nvim/after/syntax/godoc.vim | 47 ++ config/nvim/{ => after}/syntax/odin.vim | 46 +- config/nvim/init.lua | 158 ++++- config/nvim/lua/autocmds/init.lua | 40 -- config/nvim/lua/plugins/init.lua | 53 -- config/nvim/lua/terminal/init.lua | 58 -- 8 files changed, 1145 insertions(+), 169 deletions(-) create mode 100644 config/nvim/after/syntax/c.vim create mode 100644 config/nvim/after/syntax/go.vim create mode 100644 config/nvim/after/syntax/godoc.vim rename config/nvim/{ => after}/syntax/odin.vim (88%) delete mode 100644 config/nvim/lua/autocmds/init.lua delete mode 100644 config/nvim/lua/plugins/init.lua delete mode 100644 config/nvim/lua/terminal/init.lua diff --git a/config/nvim/after/syntax/c.vim b/config/nvim/after/syntax/c.vim new file mode 100644 index 0000000..80f17e2 --- /dev/null +++ b/config/nvim/after/syntax/c.vim @@ -0,0 +1,87 @@ +" ============================================================================== +" Vim syntax file +" Language: C Additions +" Original Author: Mikhail Wolfson, Jon Haggblad +" Maintainer: bfrg +" Website: https://github.com/bfrg/vim-c-cpp-modern +" Last Change: Dec 25, 2025 +" ============================================================================== + +" Highlight additional keywords in the comments +syn keyword cTodo contained BUG NOTE + +" Highlight function names +if get(g:, 'cpp_function_highlight', 1) + syn match cUserFunction "\<\h\w*\ze\_s\{-}(\%(\*\h\w*)\_s\{-}(\)\@!" + syn match cUserFunctionPointer "\%((\s*\*\s*\)\@6<=\h\w*\ze\s*)\_s\{-}(.*)" + hi def link cUserFunction Function + hi def link cUserFunctionPointer Function +endif + + +" Highlight C builtin types as Statement +if get(g:, 'cpp_builtin_types_as_statement', 1) + syntax keyword cBuiltinType int long short char void signed unsigned float double + hi def link cBuiltinType Statement +endif + + +" Highlight struct/class member variables +if get(g:, 'cpp_member_highlight', 1) + syn match cMemberAccess "\.\|->" nextgroup=cStructMember,cppTemplateKeyword + syn match cStructMember "\<\h\w*\>\%((\|<\)\@!" contained + syn cluster cParenGroup add=cStructMember + syn cluster cPreProcGroup add=cStructMember + syn cluster cMultiGroup add=cStructMember + hi def link cStructMember Identifier + + if &filetype ==# 'cpp' + syn keyword cppTemplateKeyword template + hi def link cppTemplateKeyword cppStructure + endif +endif + + +" Highlight names in struct, union and enum declarations +if get(g:, 'cpp_type_name_highlight', 1) + syn match cTypeName "\%(\<\%(struct\|union\|enum\)\s\+\)\@8<=\h\w*" + hi def link cTypeName Type + + if &filetype ==# 'cpp' + syn match cTypeName "\%(\<\%(class\|using\|concept\|requires\)\s\+\)\@10<=\h\w*" + endif +endif + + +" Highlight operators +if get(g:, 'cpp_operator_highlight', 1) + syn match cOperator "[?!~*&%<>^|=,+]" + syn match cOperator "[][]" + syn match cOperator "[^:]\@1<=:[^:]\@=" + syn match cOperator "-[^>]"me=e-1 + syn match cOperator "/[^/*]"me=e-1 +endif + + +" Common ANSI-standard Names +syn keyword cAnsiName + \ PRId8 PRIi16 PRIo32 PRIu64 PRId16 PRIi32 PRIo64 PRIuLEAST8 PRId32 PRIi64 PRIoLEAST8 PRIuLEAST16 PRId64 PRIiLEAST8 PRIoLEAST16 PRIuLEAST32 PRIdLEAST8 PRIiLEAST16 PRIoLEAST32 PRIuLEAST64 PRIdLEAST16 PRIiLEAST32 PRIoLEAST64 PRIuFAST8 PRIdLEAST32 PRIiLEAST64 PRIoFAST8 PRIuFAST16 PRIdLEAST64 PRIiFAST8 PRIoFAST16 PRIuFAST32 PRIdFAST8 PRIiFAST16 PRIoFAST32 PRIuFAST64 PRIdFAST16 PRIiFAST32 PRIoFAST64 PRIuMAX PRIdFAST32 PRIiFAST64 PRIoMAX PRIuPTR PRIdFAST64 PRIiMAX PRIoPTR PRIx8 PRIdMAX PRIiPTR PRIu8 PRIx16 PRIdPTR PRIo8 PRIu16 PRIx32 PRIi8 PRIo16 PRIu32 PRIx64 PRIxLEAST8 SCNd8 SCNiFAST32 SCNuLEAST32 PRIxLEAST16 SCNd16 SCNiFAST64 SCNuLEAST64 PRIxLEAST32 SCNd32 SCNiMAX SCNuFAST8 PRIxLEAST64 SCNd64 SCNiPTR SCNuFAST16 PRIxFAST8 SCNdLEAST8 SCNo8 SCNuFAST32 PRIxFAST16 SCNdLEAST16 SCNo16 SCNuFAST64 PRIxFAST32 SCNdLEAST32 SCNo32 SCNuMAX PRIxFAST64 SCNdLEAST64 SCNo64 SCNuPTR PRIxMAX SCNdFAST8 SCNoLEAST8 SCNx8 PRIxPTR SCNdFAST16 SCNoLEAST16 SCNx16 PRIX8 SCNdFAST32 SCNoLEAST32 SCNx32 PRIX16 SCNdFAST64 SCNoLEAST64 SCNx64 PRIX32 SCNdMAX SCNoFAST8 SCNxLEAST8 PRIX64 SCNdPTR SCNoFAST16 SCNxLEAST16 PRIXLEAST8 SCNi8 SCNoFAST32 SCNxLEAST32 PRIXLEAST16 SCNi16 SCNoFAST64 SCNxLEAST64 PRIXLEAST32 SCNi32 SCNoMAX SCNxFAST8 PRIXLEAST64 SCNi64 SCNoPTR SCNxFAST16 PRIXFAST8 SCNiLEAST8 SCNu8 SCNxFAST32 PRIXFAST16 SCNiLEAST16 SCNu16 SCNxFAST64 PRIXFAST32 SCNiLEAST32 SCNu32 SCNxMAX PRIXFAST64 SCNiLEAST64 SCNu64 SCNxPTR PRIXMAX SCNiFAST8 SCNuLEAST8 PRIXPTR SCNiFAST16 SCNuLEAST16 STDC CX_LIMITED_RANGE STDC FENV_ACCESS STDC FP_CONTRACT + \ errno environ and bitor not_eq xor and_eq compl or xor_eq bitand not or_eq + +" Booleans +syn keyword cBoolean true false TRUE FALSE + + +" Default highlighting +hi def link cBoolean Boolean +hi def link cAnsiName Identifier + + +" Highlight all standard C keywords as Statement +" This is very similar to what other IDEs and editors do +if get(g:, 'cpp_simple_highlight', 1) + hi! def link cStorageClass Statement + hi! def link cStructure Statement + hi! def link cTypedef Statement + hi! def link cLabel Statement +endif diff --git a/config/nvim/after/syntax/go.vim b/config/nvim/after/syntax/go.vim new file mode 100644 index 0000000..9b24128 --- /dev/null +++ b/config/nvim/after/syntax/go.vim @@ -0,0 +1,825 @@ +" Author: Charles Pascoe +" License: MIT (see LICENSE) +" Copyright: 2022 Charles Pascoe + +" Clear any existing syntax first +syntax clear + +if !exists('main_syntax') + if exists("b:current_syntax") && !get(g:, "go_highlight_override_existing_syntax", 1) + finish + endif + + let b:__vim_go_syntax = 1 +endif + +syntax clear +syntax case match +syntax sync fromstart + +" Define 'iskeyword' to include valid UTF-8 multibyte characters, some of which +" are technically supported for identifiers. +" TODO: Check UTF-16 +syntax iskeyword @,48-57,_,192-255 + +" TODO: Check performance of lookbehinds +" TODO: Check correct use of 'skipempty' + +" Struct and Interface need 'extend' so that simple matches (e.g. /struct {/) +" can contain complex nested types by extending the parent match. No other types +" should use extend + +" Some things use 'contains=TOP,@Spell' to allow them to behave predictably when +" they are nested within a region with special syntax elements (e.g. +" goVarDeclGroup and goConstDeclGroup) or when imported into other syntaxes. +" The '@Spell' is required to disable spelling in these items. Only a handful +" of things should use 'transparent'. + +" Config Utils {{{ + +let s:cleanup = [] + +com! -nargs=* GoDeferCleanup call add(s:cleanup, ) +GoDeferCleanup delcom GoDeferCleanup + +fun s:Cleanup() + for l:cmd in s:cleanup + exec l:cmd + endfor +endfun + +fun s:getconfig(keys, default) + if len(a:keys) == 0 + return a:default + else + return get(g:, a:keys[0], s:getconfig(a:keys[1:], a:default)) + endif +endfun + +fun s:HiConfig(group, option_names, opts={}) + " Most syntax is highlighted by default, unless turned off by the user + let l:opt = s:getconfig(a:option_names, get(a:opts, 'default', 1)) + let l:cmd = '' + + if type(l:opt) == v:t_string + if l:opt =~ '^[[:alnum:]]\+$' + exec 'hi link '.a:group.' '.l:opt + else + exec 'hi '.a:group.' '.l:opt + endif + + return 1 + elseif !l:opt + exec 'hi link '.a:group.' '.get(a:opts, 'offgroup', 'NONE') + endif + + return l:opt +endfun + +if get(g:, 'go_highlight_string_spellcheck', 1) + syntax cluster goStringSpell contains=@Spell +endif + +if get(g:, 'go_highlight_comment_spellcheck', 1) + syntax cluster goCommentSpell contains=@Spell +endif + + +" TODO: Rethink this approach (use string/array approach) +if s:getconfig(['go_fold_function_blocks', 'go_syntax_fold'], 1) + com! -nargs=* GoFoldFunc fold +else + com! -nargs=* GoFoldFunc +endif + +GoDeferCleanup delcom GoFoldFunc + + +if s:getconfig(['go_fold_struct_blocks', 'go_syntax_fold'], 1) + com! -nargs=* GoFoldStruct fold +else + com! -nargs=* GoFoldStruct +endif + +GoDeferCleanup delcom GoFoldStruct + + +if s:getconfig(['go_fold_interface_blocks', 'go_syntax_fold'], 1) + com! -nargs=* GoFoldInterface fold +else + com! -nargs=* GoFoldInterface +endif + +GoDeferCleanup delcom GoFoldInterface + + +if s:getconfig(['go_fold_decl_blocks', 'go_syntax_fold'], 1) + com! -nargs=* GoFoldDecl fold +else + com! -nargs=* GoFoldDecl +endif + +GoDeferCleanup delcom GoFoldDecl + +" }}} Config Utils + + +" Misc {{{ + +" Two top-level clusters to allow regions to specify what syntax they can +" contain +" NOTE: goIota technically shouldn't be here (it should only be a part of a +" const declaration group), but trying to get it to appear only in +" goConstDeclGroup would require compromising the performance of the current +" implementation or duplicating goExpr just for goConstDeclGroup. +syntax cluster goExpr contains=@goLiteral,goForRange,goDotExpr,goFuncLiteral,goCommaExpr,goOperator,goWordStart,goParenBlock,goBracketBlock,goComment,goIota +syntax cluster goStatement contains=@goExpr,@goFlowControl,goReturn,goSemicolon,goBraceBlock,goStatementStart,goConstDecl,goVarDecl,goTypeDecl,goKeywords + +" 'goWordStart' reduces the number of times each of the 'nextgroups' is checked, +" but also prevents 'goImportedPackages' (a keyword syntax element) from +" overriding matches (e.g. in 'goStructLiteralField'). +syntax match goWordStart /\<\ze\K/ contained nextgroup=goStructLiteral,goFuncCall,goBuiltins,goMakeBuiltin,goNewBuiltin,goImportedPackages + +" 'goDotExpr' matches a dot that is found as a part of an expression, whereas +" 'goDot' is used to highlight a dot in non-expression contexts (e.g. the dot +" between a package and a type). 'goDotExpr' significantly improves the +" performance of searching for fields and type assertions. +syntax match goDot /\./ contained +syntax match goDotExpr /\./ nextgroup=@goDotExpr skipwhite skipnl + +" The cluster of items that could follow a dot in an expression +syntax cluster goDotExpr contains=goFuncCall,goStructLiteral,goTypeAssertion,goField,goDotComment + +" goDotComment is identical to goComment, except it doesn't break field +" highlighting across multiple lines, e.g.: +" +" foo.bar. +" baz. +" // This is goDotComment instead of a goComment +" blah +" +" Both 'baz' and 'blah' are correctly highlighted as fields +syntax region goDotComment start=+//+ end=+$+ contained contains=@goCommentSpell,goCommentTodo keepend skipwhite skipnl nextgroup=@goDotExpr +syntax region goDotComment start=+/\*+ end=+\*/+ contained contains=@goCommentSpell,goCommentTodo keepend skipwhite skipnl nextgroup=@goDotExpr + +syntax match goField /\K\k*/ contained + +" TODO: Only valid operators? +syntax match goAssign /=/ skipwhite nextgroup=@goExpr +syntax match goOperator /[-+*/!:=%&^<>|~]\+/ skipwhite nextgroup=@goExpr +syntax match goCommaExpr /,/ skipwhite skipnl nextgroup=@goExpr +syntax match goComma /,/ contained +syntax match goSemicolon /;/ +syntax keyword goUnderscore _ + +hi link goField Identifier +hi link goLabel Label +hi link goOperator Operator +hi link goAssign goOperator +hi link goDot goOperator +hi link goComma Delimiter +hi link goCommaExpr goComma +hi link goSemicolon Delimiter +hi link goUnderscore Special +hi link goDotExpr goDot +hi link goDotComment goComment + +call s:HiConfig('goField', ['go_highlight_fields'], #{default: 1}) +call s:HiConfig('goLabel', ['go_highlight_labels']) +call s:HiConfig('goOperator', ['go_highlight_operators']) +call s:HiConfig('goDot', ['go_highlight_dot']) +call s:HiConfig('goComma', ['go_highlight_comma'], #{default: 1}) +call s:HiConfig('goSemicolon', ['go_highlight_semicolon'], #{default: 1}) + +" }}} Misc + + +" Comments {{{ + +syntax region goComment start=+//+ end=+$+ contains=@goCommentSpell,goCommentTodo,goDirectiveComment keepend +syntax region goComment start=+/\*+ end=+\*/+ contains=@goCommentSpell,goCommentTodo keepend + +syntax keyword goCommentTodo contained TODO FIXME XXX TBD NOTE +syntax region goDirectiveComment start=+//\(line \|extern \| export\|[a-z0-9]\+:[a-z0-9]\+\)+ end=+$+ contained + +hi link goComment Comment +hi link goCommentTodo Todo +hi link goDirectiveComment PreProc + +call s:HiConfig('goGenerateComment', ['go_highlight_generate_tags'], #{offgroup: 'goComment'}) + +" }}} Comments + + +" Literals {{{ + +syntax cluster goLiteral contains=goString,goRawString,goInvalidRuneLiteral,goNumberLeader,goBooleanTrue,goBooleanFalse,goNil,goSliceOrArrayLiteral,goPrimitiveTypes,goStructType,goInterfaceType,goMapLiteral,goSliceOrArrayLiteral + +" Strings + +syntax region goString matchgroup=goStringEnds start='"' skip=/\\\\\|\\"/ end='"\|$' oneline contains=@goStringSpell,goStringEscape,goDoubleQuoteEscape,goStringFormat +syntax match goStringEscape /\v\\%(\o{3}|x\x{2}|u\x{4}|U\x{8}|[abfnrtv\\"])/ contained +syntax match goStringFormat /\v\%%(\%|[-+# 0]*%([1-9]\d*|%(\[\d+\])?\*)?%(\.%(\d+|%(\[\d+\])?\*)?)?%(\[\d+\])?[EFGOTUXbcdefgopqstwvxf])/ contained contains=goStringFormatInvalidIndex + +if s:getconfig(['go_highlight_format_string_errors'], 0) + syntax match goStringFormatInvalidIndex /\[0\]/ contained + hi link goStringFormatInvalidIndex Error +endif + +" 'goInvalidRuneLiteral' is a loose match for all single-quote sequences; they +" are highlighted as errors. If they contain a valid 'goRuneLiteral' or the +" cursor is present at the end, then the 'goRuneLiteral' highlighting will +" override the 'goInvalidRuneLiteral' highlighting and thus look like a string. +syntax region goInvalidRuneLiteral start=+'+ skip=+\\.+ end=+'+ keepend oneline contains=goRuneLiteral +syntax match goRuneLiteral /\v'%(.*%#|[^\\]|\\%(\o{3}|x\x{2}|u\x{4}|U\x{8}|[abfnrtv\\']))'/ contained contains=goRuneLiteralEscape +syntax match goRuneLiteralEscape /\v\\%(\o{3}|x\x{2}|u\x{4}|U\x{8}|[abfnrtv\\'])/ contained + +syntax region goRawString matchgroup=goRawStringEnds start='`' end='`' keepend + +" Numbers + +" 'goNumberZeroLeader' searches for a digit so that the various number patterns +" don't have to, improving match performance +syntax match goNumberLeader /\ze\<[0-9]/ nextgroup=goNumber,goNumberTypeBinary,goNumberTypeOctal,goNumberTypeHex +syntax match goNumberLeader /\ze\.[0-9]/ nextgroup=goNumber + +" TODO: Highlight all forms of invalid number formatting? E.g. underscores in +" certain places +" TODO: Highlight floats differently +syntax match goNumber /\v<[0-9][0-9_]*%(\.[0-9_]*)?%([eE][-+]?[0-9][0-9_]*)?i?/ contained contains=goNumberDecimalExp +syntax match goNumber /\v\.[0-9][0-9_]*%([eE][-+]?[0-9][0-9_]*)?i?/ contained contains=goNumberDecimalExp + +syntax match goNumberTypeBinary /\c0b/ contained nextgroup=goNumberBinary +syntax match goNumberBinary /[01_]\+i\?/ contained + +syntax match goNumberTypeOctal /\c0o/ contained nextgroup=goNumberOctal +syntax match goNumberOctal /[0-7_]\+i\?/ contained + +syntax match goNumberTypeHex /\c0x/ contained nextgroup=goNumberHex +syntax match goNumberHex /\v\c[0-9a-f_]*%(\.[0-9a-f_]*)?%([pP][-+]?[0-9a-f][0-9a-f_]*)?i?/ contained contains=goNumberHexExp + +syntax match goNumberSpecialChar /[_i]/ contained containedin=goNumber,goNumberBinary,goNumberOctal,goNumberHex +syntax match goNumberError /_\{2,\}/ contained containedin=goNumber,goNumberBinary,goNumberOctal,goNumberHex + +" Exponent markers +syntax match goNumberDecimalExp /\ce/ contained +syntax match goNumberHexExp /\cp/ contained + +" Other + +syntax keyword goBooleanTrue true +syntax keyword goBooleanFalse false + +syntax keyword goNil nil + +" Highlighting + +hi link goString String +hi link goStringEnds goString +hi link goStringEscape SpecialChar +hi link goStringFormat SpecialChar + +hi link goInvalidRuneLiteral Error +hi link goRuneLiteral Character +hi link goRuneLiteralEscape goStringFormat + +hi link goRawString String +hi link goRawStringEnds goRawString + +hi link goNumber Number +hi link goNumberBinary goNumber +hi link goNumberOctal goNumber +hi link goNumberHex goNumber +hi link goNumberType SpecialChar +hi link goNumberTypeBinary goNumberType +hi link goNumberTypeOctal goNumberType +hi link goNumberTypeHex goNumberType +hi link goNumberError Error +hi link goNumberDecimalExp SpecialChar +hi link goNumberHexExp goNumberDecimalExp +hi link goNumberSpecialChar SpecialChar + +hi link goBooleanTrue Boolean +hi link goBooleanFalse Boolean + +hi link goNil Constant + +call s:HiConfig('goStringFormat', ['go_highlight_format_strings'], #{offgroup: 'goString'}) +call s:HiConfig('goInvalidRuneLiteral', ['go_highlight_rune_literal_error'], #{offgroup: 'goRuneLiteral'}) +" TODO: Config for highlighting special chars in numbers + +" }}} Literals + + +" Simple Blocks {{{ + +syntax region goBracketBlock matchgroup=goBrackets start='\[' end='\]' transparent extend +syntax region goParenBlock matchgroup=goParens start='(' end=')' transparent extend +syntax region goBraceBlock matchgroup=goBraces start='{' end='}' transparent extend + +hi link goBraces Delimiter +hi link goBrackets Delimiter +hi link goParens Delimiter + +call s:HiConfig('goBraces', ['go_highlight_braces']) +call s:HiConfig('goBrackets', ['go_highlight_brackets']) +call s:HiConfig('goParens', ['go_highlight_parens']) + +" }}} Simple Blocks + + +" Constants and Variables {{{ + +" TODO Slice/map assignment? +syntax match goVarAssign /\<\K\k*\%(\.\K\k*\)*\%(\s*,\s*\%(\K\k*\%(\.\K\k*\)*\)\?\)*\ze\s*\%(<<\|>>\|&^\|[-+*/%&|^]\)\?=[^=]/ contained contains=goComma,goUnderscore,goVarStructAssign skipwhite nextgroup=goOperator +syntax match goShortVarDecl /\<\K\k*\%(\s*,\s*\%(\K\k*\)\?\)*\ze\s*:=/ contained contains=goComma,goUnderscore skipwhite nextgroup=goOperator +syntax match goVarStructAssign /\<\K\k*\%(\.\K\k*\)\+/ contained contains=goDotExpr + +" TODO: Should these be skipempty instead of skipnl? +syntax keyword goConstDecl const skipwhite skipnl nextgroup=goVarIdentifier,goConstDeclGroup +syntax keyword goVarDecl var skipwhite skipnl nextgroup=goVarIdentifier,goVarDeclGroup + +" TODO: Remove these once you're certain goVarGroupIdentifier is not needed +" syntax region goVarDeclGroup matchgroup=goVarDeclParens start='(' end=')' contained contains=@goExpr,goComment,goSemicolon,goVarGroupIdentifier +" syntax region goConstDeclGroup matchgroup=goConstDeclParens start='(' end=')' contained contains=@goExpr,goComment,goSemicolon,goVarGroupIdentifier,goIota + +GoFoldDecl syntax region goVarDeclGroup matchgroup=goVarDeclParens start='(' end=')' contained contains=@goExpr,goSemicolon,goVarIdentifier +GoFoldDecl syntax region goConstDeclGroup matchgroup=goConstDeclParens start='(' end=')' contained contains=@goExpr,goSemicolon,goVarIdentifier + +" TODO: Is it worth supporting comments in goVarComma?? +syntax match goVarIdentifier /\<\K\k*/ contained skipwhite nextgroup=goVarComma,@goType +syntax match goVarComma /,/ contained skipwhite skipnl nextgroup=goVarIdentifier + +" TODO: Remove these once you're certain goVarGroupIdentifier is not needed +" " goVarGroupIdentifier finds positions inside a var/const declaration group +" " (e.g. 'const (...)') that may be followed by an identifier. Prevents +" " goVarIdentifier from matching in the wrong places. +" syntax match goVarGroupIdentifier /^\ze\s/ contained nextgroup=goVarIdentifier skipwhite +" syntax match goVarGroupIdentifier /[(;]\@1<=\ze\s/ contained nextgroup=goVarIdentifier skipwhite +" syntax match goVarGroupIdentifier /[(;]\@1<=\ze\<\K/ contained nextgroup=goVarIdentifier + +syntax keyword goIota iota contained + +hi link goConstDecl Statement +hi link goVarDecl Statement + +hi link goConstDeclParens goParens +hi link goVarDeclParens goParens + +hi link goVarIdentifier Identifier +hi link goVarComma goComma +hi link goVarGroupIdentifier goVarIdentifier +hi link goShortVarDecl Identifier + +hi link goVarAssign Special + +hi link goIota Special + +let s:assignOrShortDecl = 0 + +" goStatementStart ideally shouldn't contain goSwitchKeywords, but the without +" this, `default:` will be highlighted using `goLabel` instead of `goSwitchKeywords`. +syntax cluster goStatementStartGroup contains=goLabel,goSwitchKeywords + +call s:HiConfig('goVarIdentifier', ['go_highlight_variable_declarations']) + +if s:HiConfig('goVarAssign', ['go_highlight_variable_assignments'], #{default: 1}) + let s:assignOrShortDecl = 1 + syntax cluster goStatementStartGroup add=goVarAssign +endif + +if s:HiConfig('goShortVarDecl', ['go_highlight_short_variable_declarations','go_highlight_variable_declarations']) + let s:assignOrShortDecl = 1 + syntax cluster goStatementStartGroup add=goShortVarDecl +endif + +if s:assignOrShortDecl + " This lookbehind is checked for a lot of characters in the file, which is + " why goStatementStart is conditional and only added if needed. Splitting + " this into two makes it slightly faster overall. + " Note: the pattern /[{;]\@1<=/ seems to be equivalent to /[{;]\@1<=./ + " which is why it had such poor performance and conflict with other + " patterns; splitting it into two specific patterns works better + syntax match goStatementStart /[{;]\@1<=\ze\s/ contained skipwhite nextgroup=@goStatementStartGroup + syntax match goStatementStart /[{;]\@1<=\ze\<\K/ contained skipwhite nextgroup=@goStatementStartGroup +endif + +syntax match goStatementStart /^\ze\s/ contained skipwhite nextgroup=@goStatementStartGroup +syntax match goStatementStart /^\ze\<\K/ contained nextgroup=@goStatementStartGroup + +" }}} Constants and Variables + + +" Packages {{{ + +syntax keyword goPackage package +syntax keyword goImport import skipwhite nextgroup=goImportItem,goImports +syntax region goImports matchgroup=goImportParens start='(' end=')' contained contains=goImportItem,goComment +syntax match goImportItem /\(\([\._]\|\K\k*\)\s\+\)\?"[^"]*"/ contained contains=goImportString +syntax region goImportString start='"' end='"' keepend contained + +hi link goPackage Keyword +hi link goImport Keyword +hi link goImportItem Special +hi link goImportString goString +hi link goImportParens goParens + +" }}} Packages + + +" Types {{{ + +syntax cluster goType contains=goPrimitiveTypes,goFuncType,goStructType,goInterfaceType,goMapType,goSliceOrArrayType,goChannel,goNonPrimitiveType,goPointer,goTypeParens + +syntax match goPointer /*/ contained nextgroup=@goType + +" goTypeParens is used to ensure types within parens are highlighted correctly, +" e.g. the func type in the slice literal `[](func (a, b int) bool){ ... }` +syntax region goTypeParens start='(' end=')' contained contains=@goType,goComment + +syntax keyword goTypeDecl type skipwhite skipnl nextgroup=goTypeDeclName,goTypeDeclGroup +syntax match goTypeDeclName /\K\k*/ contained skipwhite skipnl nextgroup=goTypeDeclTypeParams,goTypeAssign,@goType +syntax match goTypeAssign /=/ contained skipwhite nextgroup=@goType + +syntax region goTypeDeclGroup matchgroup=goTypeDeclGroupParens start='(' end=')' contained contains=goTypeDeclName,goComment +syntax region goTypeDeclTypeParams matchgroup=goTypeParamBrackets start='\[' end='\]' contained contains=goTypeParam,goComma,goComment skipwhite skipnl nextgroup=@goType + +" goNonPrimitiveType is used for matching the names and packages of +" non-primitive types (i.e. types other than int, bool, string, etc.). Note the +" optional non-capturing group is later in the pattern to avoid backtracking. +syntax match goNonPrimitiveType /\<\K\k*\%(\.\K\k*\)\?\[\?/ contained contains=goPackageName,goTypeArgs +syntax match goPackageName /\<\K\k*\ze\./ contained nextgroup=goDot + +syntax region goTypeArgs matchgroup=goTypeParamBrackets start='\[' end='\]' contained contains=@goType,goUnderscore,goComma,goComment + +syntax keyword goPrimitiveTypes any bool byte complex128 complex64 error float32 float64 int int8 int16 int32 int64 rune string uint uint8 uint16 uint32 uint64 uintptr contained + +syntax match goFuncType /func\s*(/ contained contains=goFuncTypeParens skipwhite nextgroup=@goType,goFuncTypeMultiReturnType + +syntax region goFuncTypeParens matchgroup=goFuncParens start='(' end=')' contained contains=goFuncParam,goComma,goComment +syntax region goFuncTypeMultiReturnType matchgroup=goFuncMultiReturnParens start='(' end=')' contained contains=goNamedReturnValue,goComma,goComment + +syntax keyword goMapType map contained skipwhite skipempty nextgroup=goMapTypeKeyType +syntax region goMapTypeKeyType matchgroup=goMapBrackets start='\[' end='\]' contained contains=@goType skipwhite nextgroup=@goType + +syntax keyword goMapLiteral map contained skipwhite skipempty nextgroup=goMapLiteralKeyType +syntax region goMapLiteralKeyType matchgroup=goMapBrackets start='\[' end='\]' contained contains=@goType skipwhite nextgroup=goMapLiteralValueType +" See comment for goSliceOrArrayLiteralType, which serves the same function as goMapLiteralValueType +syntax region goMapLiteralValueType start='\S' end='\ze[{(]\|$' contained contains=goSliceMapLiteralTypeMatch skipwhite skipnl nextgroup=goMapLiteralItems +syntax region goMapLiteralItems matchgroup=goMapBraces start='{' end='}' contained contains=goStructLiteralBlock,@goExpr + +syntax match goSliceOrArrayType /\[\%(\d\+\|\.\.\.\)\?\]/ contained contains=goNumber,goDot skipwhite nextgroup=@goType + +" A lookbehind is used to distinguish a slice/array literal with slice indexing +syntax match goSliceOrArrayLiteral /\k\@1\)\@!\K\k*\s\+\)\?\ze[^,]/ contained contains=goComma skipwhite nextgroup=@goType,goVariadic +" syntax match goFuncParam /\%(^\|[(,]\)\@1<=\s*\zs\%(\%(\K\k*\s*,\%(\s\|\n\)*\)*\%(chan\>\)\@!\K\k*\)\%(\s*,\?\%(\s\|\n\)*\%#\|\s\+\ze[^,]\)/ contained contains=goComma,goUnderscore skipwhite nextgroup=@goType,goVariadic +" syntax match goFuncParam /\%(^\|[(,]\)\@1<=\s*\zs\%(\%(\K\k*\s*,\%(\s\|\n\)*\)*\%(chan\>\)\@!\K\k*\)\%(\s*,\?\%(\s\|\n\)*\%#\ze)\|\s\+\ze[^,]\)/ contained contains=goComma,goUnderscore skipwhite nextgroup=@goType,goVariadic + +" TODO: Peformance: Figure out how to eliminate at least the first \ze in +" '\ze)', because it more than doubles the time it takes to match this regex. +" ')\@1<=' didn't work for some reason (i.e. when typing a parameter name, it +" was highlighted as a type). +" +" goFuncParam: Assume the user is typing a parameter name (i.e. avoid +" highlighting parameter names as types until proven otherwise). +" conditional group allows skipping directly to type, e.g. func(SomeType) " +" ┌───────────────────────────────────────────────────────────────────────────────────────────────────┐ " +syntax match goFuncParam /\%(^\|[(,]\)\@1<=\s*\zs\%(\%(\%(\K\k*\s*,\%(\s\|\n\)*\)*\%(chan\>\)\@!\K\k*\)\%(\s*,\?\%(\s\|\n\)*\%#\ze)\|\s\+\ze[^,]\)\)\?/ contained contains=goComma,goUnderscore skipwhite nextgroup=@goType,goVariadic +" └──────────────────┘ │ └──────────────┘ │└────────────┘ │└────────────────┘ │ │ │ " +" Param must be preceded │ comma/ws/nl │ 'chan' a type, │ comma/ws/nl │ │ │ " +" by start of line, '(', │ │ not param name │ │ │ │ " +" or ',' followed by └────────────────────────────┘ └────────────────────────┘ └───────────┘ " +" whitespace zero or more previous params if this matches, then we otherwise if this " +" (e.g. 'a, b, ' in 'a, b, c') have one or more params, matches, we have " +" then cursor, then close params then type, " +" paren, e.g.: e.g.: " +" (a, b, c, |) (a, b foo) " +" The above diagrams can be found in the Monodraw file goFuncParam_Diagrams.monopic + +" goFuncParam: Assume the user is typing a type (i.e. avoid highlighting custom +" types as return value names until proven otherwise) +syntax match goNamedReturnValue /\%(^\|[(,]\)\@1<=\s*\zs\%(\%(\K\k*\s*,\%(\s\|\n\)*\)*\%(chan\>\)\@!\K\k*\s\+\)\?\ze[^,]/ contained contains=goComma skipwhite nextgroup=@goType + +syntax keyword goReturn return contained + +hi link goFuncName Function +hi link goFuncCall Function +hi link goFuncCallParens goParens +hi link goFuncDecl goFuncType +hi link goFuncLiteral goFuncDecl +hi link goFuncParens goParens +hi link goFuncBraces goBraces +hi link goFuncMultiReturnParens goParens + +hi link goReceiverParens goFuncParens + +hi link goVariadic goOperator +hi link goArgSpread goVariadic + +hi link goTypeParam Identifier +hi link goTypeParamComma goComma + +hi link goFuncParam Identifier +hi link goNamedReturnValue NONE + +hi link goReturn Statement + +call s:HiConfig('goFuncCall', ['go_highlight_function_calls']) +call s:HiConfig('goFuncName', ['go_highlight_functions']) +call s:HiConfig('goFuncParens', ['go_highlight_function_parens']) +call s:HiConfig('goFuncBraces', ['go_highlight_function_braces']) +call s:HiConfig('goFuncParam', ['go_highlight_function_parameters']) +call s:HiConfig('goTypeParam', ['go_highlight_type_parameters']) + +" }}} Functions + + +" Structs and Interfaces {{{ + +" Note: 'goStructTypeBlock' has 'nextgroup=goStructLiteralBlock' to handle +" anonymous struct type literals + +syntax keyword goStructType struct contained skipempty skipwhite nextgroup=goStructTypeBlock +syntax region goStructTypeBlock matchgroup=goStructTypeBraces start='{' end='}' extend contained contains=goEmbeddedType,goStructTypeField,goComment,goStructTypeTag,goDot,goSemicolon skipwhite nextgroup=goStructLiteralBlock +syntax region goStructTypeTag start='`' end='`' contained +syntax region goStructTypeTag start='"' skip='\\"' end='"' contained oneline +syntax match goStructTypeField /\%(_\|\K\k*\)\%(,\s*\%(_\|\K\k*\)\)*/ contained contains=goComma,goUnderscore skipwhite nextgroup=@goType +syntax match goEmbeddedType /\*\?\K\k*\%(\.\K\k*\)\?\%(\[.*\]\)\?\%#\@1" display " TODO: in [dynamic; asdf]int 'asdf' should be a Constant syn match odinConstant "_*[A-Z]\w*\ze\s*::" display @@ -109,6 +118,10 @@ syn region odinUnionDefinition start="\%(:\s*union.\{-}\)\@200<=\zs{" end="}"me= syn match odinParapolySpecType "\%(\$.\{-}/\)\@50<=[A-Z_]\w*" display syn match odinProcName "\h\w*\ze\s*::\s*proc" display +"JASON - proc params +syn match odinProcParam "\h\w*\ze\s*:" contained display +syn region odinProcParams matchgroup=NONE start="proc\s*(" end=")" contains=odinProcParam,odinType,odinPtrType,odinOperator,odinParapoly,odinCallingConvention + syn match odinDirective "#\s*\h\w\{-}\>" display syn region odinTernaryRegion matchgroup=odinTernary start="?" end=":" oneline contains=ALL display syn match odinTernary "[?:]" contained transparent display @@ -211,15 +224,6 @@ hi def link odinParapoly Constant hi def link odinComment Comment hi def link odinCommentBlock Comment -"JASON -"hi def link odinTodo Todo -"hi def link odinProcCall Function -"hi def link odinBuiltinProc Function -hi odinTodo guifg=#FFD700 guibg=NONE gui=bold ctermfg=Yellow cterm=bold -hi odinProcCall guifg=#8fa3b3 gui=NONE ctermfg=Blue -hi odinBuiltinProc guifg=#6ac6f2 gui=italic ctermfg=Cyan -hi odinProcName guifg=#8fa3b3 gui=bold ctermfg=Blue cterm=bold - hi def link odinLabel Special hi def link odinAttribute Macro hi def link odinBuildTag Macro @@ -229,5 +233,19 @@ hi def link odinCallingConventionError Error syn sync ccomment odinCommentBlock -let b:current_syntax = "odin" +"JASON - colors +"hi def link odinTodo Todo +"hi def link odinProcCall Function +"hi def link odinBuiltinProc Function +hi odinTodo guifg=#ebcb8b guibg=NONE gui=bold ctermfg=Yellow cterm=bold +hi odinFix guifg=#d9a6a6 guibg=NONE gui=bold ctermfg=Red cterm=bold +hi odinWarn guifg=#fbe4a8 guibg=NONE gui=bold ctermfg=Yellow cterm=bold +hi odinInfo guifg=#a3be8c guibg=NONE gui=bold ctermfg=Green cterm=bold +hi odinProcCall guifg=#8fa3b3 gui=NONE ctermfg=Blue +hi odinBuiltinProc guifg=#8fa3b3 gui=italic ctermfg=Cyan +hi odinBuiltinProc guifg=#8fa3b3 gui=NONE ctermfg=Blue +hi odinProcName guifg=#8fa3b3 gui=bold ctermfg=Blue cterm=bold +hi odinProcParam guifg=#b3a3d3 gui=NONE ctermfg=Magenta +hi def link odinImportPath String +let b:current_syntax = "odin" diff --git a/config/nvim/init.lua b/config/nvim/init.lua index 0b04c96..2adaed5 100644 --- a/config/nvim/init.lua +++ b/config/nvim/init.lua @@ -2,6 +2,7 @@ require("vim._core.ui2").enable({}) map = vim.keymap.set vim.g.mapleader = " " vim.g.termguicolors = true + -- mini.basics sets defaults see plugin folder for more vim.o.swapfile = false vim.o.winborder = "single" @@ -15,11 +16,12 @@ vim.o.path = "**" vim.o.clipboard = "unnamedplus" vim.o.foldmethod = "expr" vim.o.foldlevel = 99 -vim.o.foldexpr = "v:lua.vim.treesitter.foldexpr()" vim.o.completeopt = "menuone,noselect,fuzzy,nosort" vim.opt.shortmess:append("c") vim.o.undodir = os.getenv("HOME") .. "/.cache/nvim/undodir" +-- @BINDS +-- ----------------------------- map("t", "", "") map({"t", "n"}, "", "") map({"t", "n"}, "", "") @@ -35,6 +37,154 @@ map("n", "l", ":b#") map("n", "e", ":Ex") map("n", "x", ":bd") -require("autocmds") -require("terminal") -require("plugins") +-- @AUTOCMDS +-- ----------------------------- +-- Terminals should open with insert mode +vim.api.nvim_create_autocmd({ "BufEnter", "TermEnter", "WinEnter" }, { + pattern = "term://*", + callback = function() + if vim.bo.buftype == "terminal" then + vim.schedule(function() + vim.cmd("startinsert") + end) + end + end +}) + +-- highlights yanked text +vim.api.nvim_create_autocmd("TextYankPost", { + callback = function() + vim.highlight.on_yank({ + higroup = "IncSearch", + timeout = 200, + }) + end, +}) + +-- removes trailing whitespace on save +vim.api.nvim_create_autocmd("BufWritePre", { + callback = function() + local save_cursor = vim.fn.getpos(".") + vim.cmd([[%s/\s\+$//e]]) + vim.fn.setpos(".", save_cursor) + end, +}) + +-- @TERMINAL +-- ----------------------------- +local term_buf = nil + +local function open_term_split() + vim.cmd('botright vsplit') + local win = vim.api.nvim_get_current_win() + if term_buf and vim.api.nvim_buf_is_valid(term_buf) then + vim.api.nvim_win_set_buf(win, term_buf) + else + vim.cmd('terminal') + term_buf = vim.api.nvim_get_current_buf() + end + vim.api.nvim_win_set_width(win, math.floor(vim.o.columns * 0.37)) + vim.cmd('startinsert') +end + +local function toggle_term() + -- Check if terminal is already visible in a window + for _, win in ipairs(vim.api.nvim_list_wins()) do + if vim.api.nvim_win_get_buf(win) == term_buf then + vim.api.nvim_win_close(win, false) + return + end + end + open_term_split() +end + +local function open_term_fullscreen() + if term_buf and vim.api.nvim_buf_is_valid(term_buf) then + vim.api.nvim_set_current_buf(term_buf) + else + vim.cmd('terminal') + term_buf = vim.api.nvim_get_current_buf() + end + vim.cmd('startinsert') +end + +local function prev_non_term_buf() + local cur = vim.api.nvim_get_current_buf() + local bufs = vim.fn.getbufinfo({ buflisted = 1 }) + local candidates = {} + for _, info in ipairs(bufs) do + if info.bufnr ~= cur and vim.bo[info.bufnr].buftype ~= 'terminal' then + table.insert(candidates, info) + end + end + if #candidates == 0 then + print('No previous non-terminal buffer') + return + end + table.sort(candidates, function(a, b) return a.lastused > b.lastused end) + vim.api.nvim_set_current_buf(candidates[1].bufnr) +end + +map('n', 'l', prev_non_term_buf, { desc = 'Go to previous non-terminal buffer' }) +map('n', '', toggle_term, { desc = 'Toggle terminal split' }) +map('n', '', open_term_fullscreen, { desc = 'Open terminal fullscreen' }) +map('t', '', toggle_term, { desc = 'Toggle terminal split' }) +map('t', '', prev_non_term_buf, { desc = 'Exit terminal mode' }) + +-- @PLUGINS +-- ----------------------------- +vim.pack.add({ + { src = 'https://github.com/nvim-mini/mini.nvim' }, + { src = 'https://github.com/neovim/nvim-lspconfig' }, + { src = 'https://github.com/metalelf0/kintsugi-nvim' }, + { src = 'https://github.com/xiyaowong/transparent.nvim' }, + { src = 'https://github.com/brenoprata10/nvim-highlight-colors' } +}) + +-- { src = 'https://github.com/romus204/tree-sitter-manager.nvim' }, +-- require('tree-sitter-manager').setup() +require('nvim-highlight-colors').setup() +-- Mini setups +require('mini.extra').setup() +require('mini.pairs').setup() +require('mini.files').setup() +require('mini.surround').setup() +require('mini.sessions').setup() +require('mini.statusline').setup() +require('mini.basics').setup({options = { extra_ui = true }}) +require('mini.completion').setup({lsp_completion = { auto_setup = true }}) +require('mini.pick').setup({ + window = { + config = function() + local height = math.floor(0.65 * vim.o.lines) + local width = math.floor(0.80 * vim.o.columns) + return { + anchor = 'NW', height = height, width = width, + row = math.floor(0.5 * (vim.o.lines - height)), + col = math.floor(0.5 * (vim.o.columns - width)), + } + end + } +}) + +vim.cmd(":HighlightColors Off") +vim.cmd(":colorscheme kintsugi-dark") + +-- Lsp specific, uses nvim-lspconfigs with the below +vim.lsp.enable({ "gopls", "ols" }) +map("n", "L", ":lua vim.diagnostic.open_float()") +map("n", "gd", ":lua vim.lsp.buf.definition()") +map("n", "r", ":lua vim.lsp.buf.rename()") +map("n", "a", ":lua vim.lsp.buf.code_action()") +-- Mini Keybinds +map("n", "e", function() MiniFiles.open(vim.fn.getcwd()) end) +map("n", "f", function() MiniPick.builtin.files(nil, { source = { cwd = vim.fn.getcwd() } }) end) +map("n", "o", ":lua MiniPick.builtin.buffers()") +map("n", "h", ":lua MiniPick.builtin.help()") +map("n", "d", ":lua MiniExtra.pickers.diagnostic()") +map("n", "pp", ":lua MiniSessions.select()") +map("n", "ss", ":Pick buf_lines scope='current'") +map("n", "sp", function() MiniPick.builtin.grep_live(nil, { source = { cwd = vim.fn.getcwd() } }) end) +map('n', 'sw', function() MiniPick.builtin.grep({ pattern = vim.fn.expand('') }) end) +-- Others +map("n", "tc", ":HighlightColors Toggle") diff --git a/config/nvim/lua/autocmds/init.lua b/config/nvim/lua/autocmds/init.lua deleted file mode 100644 index a76899a..0000000 --- a/config/nvim/lua/autocmds/init.lua +++ /dev/null @@ -1,40 +0,0 @@ --- Terminals should open with insert mode -vim.api.nvim_create_autocmd({ "BufEnter", "TermEnter", "WinEnter" }, { - pattern = "term://*", - callback = function() - if vim.bo.buftype == "terminal" then - vim.schedule(function() - vim.cmd("startinsert") - end) - end - end -}) - --- Start treesitter -vim.api.nvim_create_autocmd('FileType', { - pattern = '*', - callback = function(ev) - if ev.match ~= "odin" then - pcall(vim.treesitter.start) - end - end, -}) - --- highlights yanked text -vim.api.nvim_create_autocmd("TextYankPost", { - callback = function() - vim.highlight.on_yank({ - higroup = "IncSearch", - timeout = 200, - }) - end, -}) - --- removes trailing whitespace on save -vim.api.nvim_create_autocmd("BufWritePre", { - callback = function() - local save_cursor = vim.fn.getpos(".") - vim.cmd([[%s/\s\+$//e]]) - vim.fn.setpos(".", save_cursor) - end, -}) diff --git a/config/nvim/lua/plugins/init.lua b/config/nvim/lua/plugins/init.lua deleted file mode 100644 index ff2b058..0000000 --- a/config/nvim/lua/plugins/init.lua +++ /dev/null @@ -1,53 +0,0 @@ -vim.pack.add({ - { src = 'https://github.com/nvim-mini/mini.nvim' }, - { src = 'https://github.com/neovim/nvim-lspconfig' }, - { src = 'https://github.com/metalelf0/kintsugi-nvim' }, - { src = 'https://github.com/xiyaowong/transparent.nvim' }, - { src = 'https://github.com/brenoprata10/nvim-highlight-colors' } -}) - - --- { src = 'https://github.com/romus204/tree-sitter-manager.nvim' }, --- require('tree-sitter-manager').setup() -require('nvim-highlight-colors').setup() --- Mini setups -require('mini.extra').setup() -require('mini.pairs').setup() -require('mini.files').setup() -require('mini.surround').setup() -require('mini.sessions').setup() -require('mini.statusline').setup() -require('mini.basics').setup({options = { extra_ui = true }}) -require('mini.completion').setup({lsp_completion = { auto_setup = true }}) -require('mini.pick').setup({ - window = { - config = function() - local height = math.floor(0.50 * vim.o.lines) - local width = math.floor(0.50 * vim.o.columns) - return { - anchor = 'NW', height = height, width = width, - row = math.floor(0.5 * (vim.o.lines - height)), - col = math.floor(0.5 * (vim.o.columns - width)), - } - end - } -}) - -vim.cmd(":HighlightColors Off") -vim.cmd(":colorscheme kintsugi-dark") - --- Lsp specific, uses nvim-lspconfigs with the below -vim.lsp.enable({ "gopls", "ols" }) -map("n", "L", ":lua vim.diagnostic.open_float()") -map("n", "gd", ":lua vim.lsp.buf.definition()") -map("n", "r", ":lua vim.lsp.buf.rename()") -map("n", "a", ":lua vim.lsp.buf.code_action()") --- Mini Keybinds -map("n", "e", function() MiniFiles.open(vim.fn.getcwd()) end) -map("n", "f", function() MiniPick.builtin.files(nil, { source = { cwd = vim.fn.getcwd() } }) end) -map("n", "o", ":lua MiniPick.builtin.buffers()") -map("n", "h", ":lua MiniPick.builtin.help()") -map("n", "d", ":lua MiniExtra.pickers.diagnostic()") -map("n", "ss", function() MiniPick.builtin.grep_live(nil, { source = { cwd = vim.fn.getcwd() } }) end) -map("n", "pp", ":lua MiniSessions.select()") -map("n", "tc", ":HighlightColors Toggle") diff --git a/config/nvim/lua/terminal/init.lua b/config/nvim/lua/terminal/init.lua deleted file mode 100644 index 9bedac9..0000000 --- a/config/nvim/lua/terminal/init.lua +++ /dev/null @@ -1,58 +0,0 @@ -local term_buf = nil - -local function open_term_split() - vim.cmd('botright vsplit') - local win = vim.api.nvim_get_current_win() - if term_buf and vim.api.nvim_buf_is_valid(term_buf) then - vim.api.nvim_win_set_buf(win, term_buf) - else - vim.cmd('terminal') - term_buf = vim.api.nvim_get_current_buf() - end - vim.api.nvim_win_set_width(win, math.floor(vim.o.columns * 0.37)) - vim.cmd('startinsert') -end - -local function toggle_term() - -- Check if terminal is already visible in a window - for _, win in ipairs(vim.api.nvim_list_wins()) do - if vim.api.nvim_win_get_buf(win) == term_buf then - vim.api.nvim_win_close(win, false) - return - end - end - open_term_split() -end - -local function open_term_fullscreen() - if term_buf and vim.api.nvim_buf_is_valid(term_buf) then - vim.api.nvim_set_current_buf(term_buf) - else - vim.cmd('terminal') - term_buf = vim.api.nvim_get_current_buf() - end - vim.cmd('startinsert') -end - -local function prev_non_term_buf() - local cur = vim.api.nvim_get_current_buf() - local bufs = vim.fn.getbufinfo({ buflisted = 1 }) - local candidates = {} - for _, info in ipairs(bufs) do - if info.bufnr ~= cur and vim.bo[info.bufnr].buftype ~= 'terminal' then - table.insert(candidates, info) - end - end - if #candidates == 0 then - print('No previous non-terminal buffer') - return - end - table.sort(candidates, function(a, b) return a.lastused > b.lastused end) - vim.api.nvim_set_current_buf(candidates[1].bufnr) -end - -map('n', 'l', prev_non_term_buf, { desc = 'Go to previous non-terminal buffer' }) -map('n', '', toggle_term, { desc = 'Toggle terminal split' }) -map('n', '', open_term_fullscreen, { desc = 'Open terminal fullscreen' }) -map('t', '', toggle_term, { desc = 'Toggle terminal split' }) -map('t', '', prev_non_term_buf, { desc = 'Exit terminal mode' })