From: Patrick Meiser-Knosowski Date: Fri, 29 May 2026 18:19:39 +0000 (+0000) Subject: runtime(karel): Add indent plugin for Karel X-Git-Tag: v9.2.0559~2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=f31407f9fa7e38ba63bc0c7abe532db98a21532b;p=thirdparty%2Fvim.git runtime(karel): Add indent plugin for Karel closes: #20357 Signed-off-by: Patrick Meiser-Knosowski Signed-off-by: Christian Brabandt --- diff --git a/.github/MAINTAINERS b/.github/MAINTAINERS index 4c4873507d..58a8f94562 100644 --- a/.github/MAINTAINERS +++ b/.github/MAINTAINERS @@ -405,6 +405,7 @@ runtime/indent/json.vim @elzr runtime/indent/jsonc.vim @izhakjakov runtime/indent/julia.vim @carlobaldassi runtime/indent/just.vim @pbnj +runtime/indent/karel.vim @KnoP-01 runtime/indent/kdl.vim @imsnif @jiangyinzuo runtime/indent/kotlin.vim @udalov runtime/indent/krl.vim @KnoP-01 diff --git a/runtime/indent/karel.vim b/runtime/indent/karel.vim new file mode 100644 index 0000000000..9913607570 --- /dev/null +++ b/runtime/indent/karel.vim @@ -0,0 +1,121 @@ +" Vim indent file +" Language: Fanuc Karel +" Maintainer: Patrick Meiser-Knosowski +" Version: 1.0.0 +" Last Change: 28. May 2026 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal nolisp +setlocal nocindent +setlocal nosmartindent +setlocal autoindent +setlocal indentexpr=GetKarelIndent() +setlocal indentkeys=!^F,o,O,=~end,0=~else,0=~case,0=~until,0=~const,0=~type,0=~var,0=~begin +let b:undo_indent = "setlocal lisp< cindent< smartindent< autoindent< indentexpr< indentkeys<" + +if get(g:,'karelSpaceIndent',1) + " Use spaces, not tabs, for indention, 2 is enough. + " More or even tabs would waste valuable space on the teach pendant. + setlocal softtabstop=2 + setlocal shiftwidth=2 + setlocal expandtab + setlocal shiftround + let b:undo_indent = b:undo_indent." softtabstop< shiftwidth< expandtab< shiftround<" +endif + +" Only define the function once. +if exists("*GetKarelIndent") + finish +endif +let s:keepcpo = &cpo +set cpo&vim + +function GetKarelIndent() abort + + let currentLine = getline(v:lnum) + if currentLine =~? '\v^--' && !get(g:, 'karelCommentIndent', 0) + " If current line has a -- in column 1, keep zero indent. + " This may be useful if code is commented out at the first column. + return 0 + endif + + " Find a non-blank line above the current line. + let preNoneBlankLineNum = s:karelPreNoneBlank(v:lnum - 1) + if preNoneBlankLineNum == 0 + " At the start of the file use zero indent. + return 0 + endif + + let preNoneBlankLine = getline(preNoneBlankLineNum) + let ind = indent(preNoneBlankLineNum) + + " Define add 'shiftwidth' pattern + let addShiftwidthPattern = '\v^\s*(' + let addShiftwidthPattern ..= 'if>|while>|for>|using>|condition>|.*' + let addShiftwidthPattern ..= '|else>' + let addShiftwidthPattern ..= '|case>' + let addShiftwidthPattern ..= '|repeat>' + let addShiftwidthPattern ..= '|const>' + let addShiftwidthPattern ..= '|type>' + let addShiftwidthPattern ..= '|var>' + let addShiftwidthPattern ..= '|begin>' + let addShiftwidthPattern ..= '|routine>' + if get(g:, 'karelIndentBetweenPrg', 1) + let addShiftwidthPattern ..= '|program>' + endif + let addShiftwidthPattern ..= ')' + + " Define Subtract 'shiftwidth' pattern + let subtractShiftwidthPattern = '\v^\s*(' + let subtractShiftwidthPattern ..= 'end(if|while|for|using|condition|structure)?>' + let subtractShiftwidthPattern ..= '|else>' + let subtractShiftwidthPattern ..= '|case>|endselect>' + let subtractShiftwidthPattern ..= '|until>' + let subtractShiftwidthPattern ..= '|const>' + let subtractShiftwidthPattern ..= '|type>' + let subtractShiftwidthPattern ..= '|var>' + let subtractShiftwidthPattern ..= '|begin>' + let subtractShiftwidthPattern ..= ')' + + " Add shiftwidth + if preNoneBlankLine =~? addShiftwidthPattern + let ind += &sw + endif + + " Subtract shiftwidth + if currentLine =~? subtractShiftwidthPattern + let ind = ind - &sw + endif + + " First case after a select gets the indent of the select. + if currentLine =~? '\v^\s*case>' + \&& preNoneBlankLine =~? '\v^\s*select>' + let ind = ind + &sw + endif + + return ind +endfunction + +" This function works almost like prevnonblank() but handles &-headers, +" comments and continue instructions like blank lines +function s:karelPreNoneBlank(lnum) abort + + let nPreNoneBlank = prevnonblank(a:lnum) + + while nPreNoneBlank > 0 && getline(nPreNoneBlank) =~? '\v^\s*(\&\w\+|--)' + " Previous none blank line irrelevant. Look further aback. + let nPreNoneBlank = prevnonblank(nPreNoneBlank - 1) + endwhile + + return nPreNoneBlank +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 sts=2 et diff --git a/runtime/indent/testdir/karel.in b/runtime/indent/testdir/karel.in new file mode 100644 index 0000000000..edee2bdbbd --- /dev/null +++ b/runtime/indent/testdir/karel.in @@ -0,0 +1,211 @@ +-- vim: set ft=karel sw=2 : + +-- START_INDENT +-- upper case +-- test karelIndentBetweenPrg not existing +-- test karelCommentIndent not existing +PROGRAM UcKarelPrg +%CMOSVARS +TYPE +Array4OfInt = ARRAY[4] OF integer +CONST +Success = 0 +TYPE +sub_struct = STRUCTURE +subs_field_1: INTEGER +subs_field_2: BOOLEAN +ENDSTRUCTURE +MyStruct = STRUCTURE +subs_field_1: INTEGER +subs_field_2: sub_struct +ENDSTRUCTURE +VAR +i1 :integer +b1 :boolean +fhCh :file +ROUTINE prg1() +VAR +i :integer +BEGIN + -- +END prg1 +ROUTINE fcnt1( s :string ) :string +VAR +i :integer +BEGIN +RETURN ' ' +END fcnt1 +BEGIN +IF b1 THEN + -- +ENDIF +IF b1 THEN + -- +ELSE + -- +ENDIF +WHILE b1 DO + -- +ENDWHILE +FOR i1 = 1 TO 10 DO + -- +ENDFOR +FOR i1 = 10 DOWNTO 1 DO + -- +ENDFOR +USING sub_struct, MyStruct DO + -- +ENDUSING +CONDITION[1]: +WHEN DIN[1] DO DOUT[1] = TRUE +ENDCONDITION +SELECT i1 OF +CASE (1): + -- +CASE (2,3): +-- +ELSE: + -- +ENDSELECT +END UcKarelPrg +-- END_INDENT + +-- START_INDENT +-- lower case +-- INDENT_EXE let g:karelIndentBetweenPrg = 0 +-- INDENT_EXE let g:karelCommentIndent = 0 +program LcKarelPrg +%CMOSVARS +type +Array4OfInt = ARRAY[4] OF integer +const +Success = 0 +type +sub_struct = structure +subs_field_1: INTEGER +subs_field_2: BOOLEAN +endstructure +MyStruct = structure +subs_field_1: INTEGER +subs_field_2: sub_struct +endstructure +var +i1 :integer +b1 :boolean +fhCh :file +routine prg1() +var +i :integer +begin + -- +end prg1 +routine fcnt1( s :string ) :string +var +i :integer +begin +return ' ' +end fcnt1 +begin +if b1 then + -- +endif +if b1 then + -- +else + -- +endif +while b1 do + -- +endwhile +for i1 = 1 to 10 do + -- +endfor +for i1 = 10 downto 1 do + -- +endfor +using sub_struct, MyStruct do + -- +endusing +condition[1]: +when DIN[1] do DOUT[1] = TRUE +endcondition +select i1 of +case (1): + -- +case (2,3): +-- +else: + -- +endselect +end LcKarelPrg +-- END_INDENT + +-- START_INDENT +-- mixed case +-- INDENT_EXE let g:karelIndentBetweenPrg = 1 +-- INDENT_EXE let g:karelCommentIndent = 1 +Program McKarelPrg +%CMOSVARS +Type +Array4OfInt = ARRAY[4] OF integer +Const +Success = 0 +Type +sub_struct = Structure +subs_field_1: INTEGER +subs_field_2: BOOLEAN +EndStructure +MyStruct = Structure +subs_field_1: INTEGER +subs_field_2: sub_struct +EndStructure +Var +i1 :integer +b1 :boolean +fhCh :file +Routine prg1() +Var +i :integer +Begin + -- +End prg1 +Routine fcnt1( s :string ) :string +Var +i :integer +Begin +Return ' ' +End fcnt1 +Begin +If b1 Then + -- +EndIf +If b1 Then + -- +Else + -- +EndIf +While b1 Do + -- +EndWhile +For i1 = 1 To 10 Do + -- +EndFor +For i1 = 10 DownTo 1 Do + -- +EndFor +Using sub_struct, MyStruct Do + -- +EndUsing +Condition[1]: +When DIN[1] Do DOUT[1] = TRUE +EndCondition +Select i1 Of +Case (1): + -- +Case (2,3): +-- +Else: + -- +EndSelect +End McKarelPrg +-- END_INDENT diff --git a/runtime/indent/testdir/karel.ok b/runtime/indent/testdir/karel.ok new file mode 100644 index 0000000000..a7b5e9fa6d --- /dev/null +++ b/runtime/indent/testdir/karel.ok @@ -0,0 +1,211 @@ +-- vim: set ft=karel sw=2 : + +-- START_INDENT +-- upper case +-- test karelIndentBetweenPrg not existing +-- test karelCommentIndent not existing +PROGRAM UcKarelPrg + %CMOSVARS +TYPE + Array4OfInt = ARRAY[4] OF integer +CONST + Success = 0 +TYPE + sub_struct = STRUCTURE + subs_field_1: INTEGER + subs_field_2: BOOLEAN + ENDSTRUCTURE + MyStruct = STRUCTURE + subs_field_1: INTEGER + subs_field_2: sub_struct + ENDSTRUCTURE +VAR + i1 :integer + b1 :boolean + fhCh :file + ROUTINE prg1() + VAR + i :integer + BEGIN + -- + END prg1 + ROUTINE fcnt1( s :string ) :string + VAR + i :integer + BEGIN + RETURN ' ' + END fcnt1 +BEGIN + IF b1 THEN + -- + ENDIF + IF b1 THEN + -- + ELSE + -- + ENDIF + WHILE b1 DO + -- + ENDWHILE + FOR i1 = 1 TO 10 DO + -- + ENDFOR + FOR i1 = 10 DOWNTO 1 DO + -- + ENDFOR + USING sub_struct, MyStruct DO + -- + ENDUSING + CONDITION[1]: + WHEN DIN[1] DO DOUT[1] = TRUE + ENDCONDITION + SELECT i1 OF + CASE (1): + -- + CASE (2,3): +-- + ELSE: + -- + ENDSELECT +END UcKarelPrg +-- END_INDENT + +-- START_INDENT +-- lower case +-- INDENT_EXE let g:karelIndentBetweenPrg = 0 +-- INDENT_EXE let g:karelCommentIndent = 0 +program LcKarelPrg +%CMOSVARS +type + Array4OfInt = ARRAY[4] OF integer +const + Success = 0 +type + sub_struct = structure + subs_field_1: INTEGER + subs_field_2: BOOLEAN + endstructure + MyStruct = structure + subs_field_1: INTEGER + subs_field_2: sub_struct + endstructure +var + i1 :integer + b1 :boolean + fhCh :file + routine prg1() + var + i :integer + begin + -- + end prg1 + routine fcnt1( s :string ) :string + var + i :integer + begin + return ' ' + end fcnt1 +begin + if b1 then + -- + endif + if b1 then + -- + else + -- + endif + while b1 do + -- + endwhile + for i1 = 1 to 10 do + -- + endfor + for i1 = 10 downto 1 do + -- + endfor + using sub_struct, MyStruct do + -- + endusing + condition[1]: + when DIN[1] do DOUT[1] = TRUE + endcondition + select i1 of + case (1): + -- + case (2,3): +-- + else: + -- + endselect +end LcKarelPrg +-- END_INDENT + +-- START_INDENT +-- mixed case +-- INDENT_EXE let g:karelIndentBetweenPrg = 1 +-- INDENT_EXE let g:karelCommentIndent = 1 +Program McKarelPrg + %CMOSVARS +Type + Array4OfInt = ARRAY[4] OF integer +Const + Success = 0 +Type + sub_struct = Structure + subs_field_1: INTEGER + subs_field_2: BOOLEAN + EndStructure + MyStruct = Structure + subs_field_1: INTEGER + subs_field_2: sub_struct + EndStructure +Var + i1 :integer + b1 :boolean + fhCh :file + Routine prg1() + Var + i :integer + Begin + -- + End prg1 + Routine fcnt1( s :string ) :string + Var + i :integer + Begin + Return ' ' + End fcnt1 +Begin + If b1 Then + -- + EndIf + If b1 Then + -- + Else + -- + EndIf + While b1 Do + -- + EndWhile + For i1 = 1 To 10 Do + -- + EndFor + For i1 = 10 DownTo 1 Do + -- + EndFor + Using sub_struct, MyStruct Do + -- + EndUsing + Condition[1]: + When DIN[1] Do DOUT[1] = TRUE + EndCondition + Select i1 Of + Case (1): + -- + Case (2,3): + -- + Else: + -- + EndSelect +End McKarelPrg +-- END_INDENT