Mercurial > vim
view runtime/indent/fortran.vim @ 33947:f4d88db48a63 v9.0.2168
patch 9.0.2168: Moving tabpages on :drop may cause an endless loop
Commit: https://github.com/vim/vim/commit/df12e39b8b9dd39056e22b452276622cb7b617fd
Author: Christian Brabandt <cb@256bit.org>
Date: Sat Dec 16 13:55:32 2023 +0100
patch 9.0.2168: Moving tabpages on :drop may cause an endless loop
Problem: Moving tabpages on :drop may cause an endless loop
Solution: Disallow moving tabpages on :drop when cleaning up the arglist
first
Moving tabpages during drop command may cause an endless loop
When executing a :tab drop command, Vim will close all windows not in
the argument list. This triggers various autocommands. If a user has
created an 'au Tabenter * :tabmove -' autocommand, this can cause Vim to
end up in an endless loop, when trying to iterate over all tabs (which
would trigger the tabmove autocommand, which will change the tpnext
pointer, etc).
So instead of blocking all autocommands before we actually try to edit
the given file, lets simply disallow to move tabpages around. Otherwise,
we may change the expected number of events triggered during a :drop
command, which users may rely on (there is actually a test, that expects
various TabLeave/TabEnter autocommands) and would therefore be a
backwards incompatible change.
Don't make this an error, as this could trigger several times during the
drop command, but silently ignore the :tabmove command in this case (and
it should in fact finally trigger successfully when loading the given
file in a new tab). So let's just be quiet here instead.
fixes: #13676
closes: #13686
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 16 Dec 2023 14:00:05 +0100 |
parents | cf2ae76cbbf7 |
children | 7bbae0fa2d7d |
line wrap: on
line source
" Vim indent file " Language: Fortran 2008 (and Fortran 2003, 95, 90, and 77) " Version: (v49) 2023 December 1 " Maintainers: Ajit J. Thakkar <ajit@unb.ca>; <https://ajit.ext.unb.ca/> " Joshua Hollett <j.hollett@uwinnipeg.ca> " Usage: For instructions, do :help fortran-indent from Vim " Credits: " Version 0.1 was created in September 2000 by Ajit Thakkar. " Since then, useful suggestions and contributions have been made, in order, by: " Albert Oliver Serra, Takuya Fujiwara, Philipp Edelmann, Eisuke Kawashima, " Louis Cochen, and Doug Kearns. " Only load this indent file when no other was loaded. if exists("b:did_indent") finish endif let b:did_indent = 1 let s:cposet=&cpoptions set cpoptions&vim let b:undo_indent = "setl inde< indk<" setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect,=~elseif setlocal indentkeys+==~type,=~interface,=~forall,=~associate,=~block,=~enum setlocal indentkeys+==~endforall,=~endassociate,=~endblock,=~endenum if exists("b:fortran_indent_more") || exists("g:fortran_indent_more") setlocal indentkeys+==~function,=~subroutine,=~module,=~contains,=~program setlocal indentkeys+==~endfunction,=~endsubroutine,=~endmodule setlocal indentkeys+==~endprogram endif " Determine whether this is a fixed or free format source file " if this hasn't been done yet using the priority: " buffer-local value " > global value " > file extension as in Intel ifort, gcc (gfortran), NAG, Pathscale, and Cray compilers if !exists("b:fortran_fixed_source") if exists("fortran_free_source") " User guarantees free source form let b:fortran_fixed_source = 0 elseif exists("fortran_fixed_source") " User guarantees fixed source form let b:fortran_fixed_source = 1 elseif expand("%:e") =~? '^f\%(90\|95\|03\|08\)$' " Free-form file extension defaults as in Intel ifort, gcc(gfortran), NAG, Pathscale, and Cray compilers let b:fortran_fixed_source = 0 elseif expand("%:e") =~? '^\%(f\|f77\|for\)$' " Fixed-form file extension defaults let b:fortran_fixed_source = 1 else " Modern fortran still allows both fixed and free source form " Assume fixed source form unless signs of free source form " are detected in the first five columns of the first s:lmax lines. " Detection becomes more accurate and time-consuming if more lines " are checked. Increase the limit below if you keep lots of comments at " the very top of each file and you have a fast computer. let s:lmax = 500 if ( s:lmax > line("$") ) let s:lmax = line("$") endif let b:fortran_fixed_source = 1 let s:ln=1 while s:ln <= s:lmax let s:test = strpart(getline(s:ln),0,5) if s:test !~ '^[Cc*]' && s:test !~ '^ *[!#]' && s:test =~ '[^ 0-9\t]' && s:test !~ '^[ 0-9]*\t' let b:fortran_fixed_source = 0 break endif let s:ln = s:ln + 1 endwhile endif endif " Define the appropriate indent function but only once if (b:fortran_fixed_source == 1) setlocal indentexpr=FortranGetFixedIndent() if exists("*FortranGetFixedIndent") let &cpoptions = s:cposet unlet s:cposet finish endif else setlocal indentexpr=FortranGetFreeIndent() if exists("*FortranGetFreeIndent") let &cpoptions = s:cposet unlet s:cposet finish endif endif function FortranGetIndent(lnum) let ind = indent(a:lnum) let prevline=getline(a:lnum) " Strip tail comment let prevstat=substitute(prevline, '!.*$', '', '') let prev2line=getline(a:lnum-1) let prev2stat=substitute(prev2line, '!.*$', '', '') "Indent do loops only if they are all guaranteed to be of do/end do type if exists("b:fortran_do_enddo") || exists("g:fortran_do_enddo") if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*do\>' let ind = ind + shiftwidth() endif if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*end\s*do\>' let ind = ind - shiftwidth() endif endif "Add a shiftwidth to statements following if, else, else if, case, class, "where, else where, forall, type, interface and associate statements if prevstat =~? '^\s*\(case\|class\|else\|else\s*if\|else\s*where\)\>' \ ||prevstat=~? '^\s*\(type\|interface\|associate\|enum\)\>' \ ||prevstat=~?'^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*\(forall\|where\|block\)\>' \ ||prevstat=~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>' let ind = ind + shiftwidth() " Remove unwanted indent after logical and arithmetic ifs if prevstat =~? '\<if\>' && prevstat !~? '\<then\>' let ind = ind - shiftwidth() endif " Remove unwanted indent after type( statements if prevstat =~? '^\s*type\s*(' let ind = ind - shiftwidth() endif endif "Indent program units unless instructed otherwise if !exists("b:fortran_indent_less") && !exists("g:fortran_indent_less") let prefix='\(\(pure\|impure\|elemental\|recursive\)\s\+\)\{,2}' let type='\(\(integer\|real\|double\s\+precision\|complex\|logical' \.'\|character\|type\|class\)\s*\S*\s\+\)\=' if prevstat =~? '^\s*\(contains\|submodule\|program\)\>' \ ||prevstat =~? '^\s*'.'module\>\(\s*\procedure\)\@!' \ ||prevstat =~? '^\s*'.prefix.'subroutine\>' \ ||prevstat =~? '^\s*'.prefix.type.'function\>' \ ||prevstat =~? '^\s*'.type.prefix.'function\>' let ind = ind + shiftwidth() endif if getline(v:lnum) =~? '^\s*contains\>' \ ||getline(v:lnum)=~? '^\s*end\s*' \ .'\(function\|subroutine\|module\|submodule\|program\)\>' let ind = ind - shiftwidth() endif endif "Subtract a shiftwidth from else, else if, elsewhere, case, class, end if, " end where, end select, end forall, end interface, end associate, " end enum, end type, end block and end type statements if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*' \. '\(else\|else\s*if\|else\s*where\|case\|class\|' \. 'end\s*\(if\|where\|select\|interface\|' \. 'type\|forall\|associate\|enum\|block\)\)\>' let ind = ind - shiftwidth() " Fix indent for case statement immediately after select if prevstat =~? '\<select\s*\(case\|type\)\>' let ind = ind + shiftwidth() endif endif "First continuation line if prevstat =~ '&\s*$' && prev2stat !~ '&\s*$' let ind = ind + shiftwidth() endif "Line after last continuation line if prevstat !~ '&\s*$' && prev2stat =~ '&\s*$' && prevstat !~? '\<then\>' let ind = ind - shiftwidth() endif return ind endfunction function FortranGetFreeIndent() "Find the previous non-blank line let lnum = prevnonblank(v:lnum - 1) "Use zero indent at the top of the file if lnum == 0 return 0 endif let ind=FortranGetIndent(lnum) return ind endfunction function FortranGetFixedIndent() let currline=getline(v:lnum) "Don't indent comments, continuation lines and labelled lines if strpart(currline,0,6) =~ '[^ \t]' let ind = indent(v:lnum) return ind endif "Find the previous line which is not blank, not a comment, "not a continuation line, and does not have a label let lnum = v:lnum - 1 while lnum > 0 let prevline=getline(lnum) if (prevline =~ "^[C*!]") || (prevline =~ "^\s*$") \ || (strpart(prevline,5,1) !~ "[ 0]") " Skip comments, blank lines and continuation lines let lnum = lnum - 1 else let test=strpart(prevline,0,5) if test =~ "[0-9]" " Skip lines with statement numbers let lnum = lnum - 1 else break endif endif endwhile "First line must begin at column 7 if lnum == 0 return 6 endif let ind=FortranGetIndent(lnum) return ind endfunction let &cpoptions = s:cposet unlet s:cposet " vim:sw=2 tw=130