Skip to content

Commit

Permalink
Add improved Modula-2 runtime support (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
dkearns committed Jan 3, 2024
1 parent 74512e0 commit fd0a6f1
Show file tree
Hide file tree
Showing 43 changed files with 2,300 additions and 105 deletions.
1 change: 1 addition & 0 deletions Filelist
Expand Up @@ -818,6 +818,7 @@ RT_SCRIPTS = \
runtime/plugin/README.txt \
runtime/syntax/*.vim \
runtime/syntax/README.txt \
runtime/syntax/modula2/opt/*.vim \
runtime/syntax/shared/*.vim \
runtime/syntax/shared/README.txt \
runtime/syntax/Makefile \
Expand Down
69 changes: 66 additions & 3 deletions runtime/autoload/dist/ft.vim
Expand Up @@ -279,6 +279,19 @@ export def DtraceCheck()
endif
enddef

export def FTdef()
if get(g:, "filetype_def", "") == "modula2" || IsModula2()
SetFiletypeModula2()
return
endif

if exists("g:filetype_def")
exe "setf " .. g:filetype_def
else
setf def
endif
enddef

export def FTe()
if exists('g:filetype_euphoria')
exe 'setf ' .. g:filetype_euphoria
Expand Down Expand Up @@ -517,16 +530,66 @@ def IsLProlog(): bool
return getline(lnum) =~ '\<module\s\+\w\+\s*\.\s*\(%\|$\)'
enddef

def IsModula2(): bool
return getline(nextnonblank(1)) =~ '\<MODULE\s\+\w\+\s*;\|^\s*(\*'
enddef

def SetFiletypeModula2()
const KNOWN_DIALECTS = ["iso", "pim", "r10"]
const KNOWN_EXTENSIONS = ["gm2"]
const LINE_COUNT = 200

var dialect = "pim"
var extension = ""

# TODO: allow g:modula2_force_dialect to override tags?
if exists("g:modula2_default_dialect")
dialect = g:modula2_default_dialect
endif
if exists("g:modula2_default_extension")
extension = g:modula2_default_extension
endif

const TAG = '(\*!m2\(\w\+\)\%(+\(\w\+\)\)\=\*)'

var matches = []

# ignore unknown dialects or badly formatted tags
for lnum in range(1, min([line("$"), LINE_COUNT]))
matches = matchlist(getline(lnum), TAG)
if !empty(matches)
if index(KNOWN_DIALECTS, matches[1]) >= 0
dialect = matches[1]
endif
if index(KNOWN_EXTENSIONS, matches[2]) >= 0
extension = matches[2]
endif
break
endif
endfor

if exists("b:modula2")
unlockvar! b:modula2
endif
b:modula2 = { dialect: dialect, extension: extension }
lockvar! b:modula2

setf modula2
enddef

# Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod
export def FTmod()
if get(g:, "filetype_mod", "") == "modula2" || IsModula2()
SetFiletypeModula2()
return
endif

if exists("g:filetype_mod")
exe "setf " .. g:filetype_mod
elseif expand("<afile>") =~ '\<go.mod$'
setf gomod
elseif IsLProlog()
setf lprolog
elseif getline(nextnonblank(1)) =~ '\%(\<MODULE\s\+\w\+\s*;\|^\s*(\*\)'
setf modula2
elseif IsRapid()
setf rapid
else
Expand Down Expand Up @@ -1223,4 +1286,4 @@ export def FTvba()
enddef

# Uncomment this line to check for compilation errors early
# defcompile
defcompile
22 changes: 22 additions & 0 deletions runtime/autoload/modula2.vim
@@ -0,0 +1,22 @@
" Vim filetype plugin file
" Language: Modula-2
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Last Change: 2022 Oct 18

" Dialect can be one of pim, iso, r10
function modula2#GetDialect() abort

if exists("b:modula2.dialect")
return b:modula2.dialect
endif

if exists("g:modula2_default_dialect")
let dialect = g:modula2_default_dialect
else
let dialect = "pim"
endif

return dialect
endfunction

" vim: nowrap sw=2 sts=2 ts=8 noet fdm=marker:
1 change: 1 addition & 0 deletions runtime/doc/filetype.txt
Expand Up @@ -148,6 +148,7 @@ variables can be used to overrule the filetype used for certain extensions:
*.cls g:filetype_cls
*.csh g:filetype_csh |ft-csh-syntax|
*.dat g:filetype_dat
*.def g:filetype_def
*.f g:filetype_f |ft-forth-syntax|
*.frm g:filetype_frm |ft-form-syntax|
*.fs g:filetype_fs |ft-forth-syntax|
Expand Down
36 changes: 36 additions & 0 deletions runtime/doc/syntax.txt
Expand Up @@ -2251,6 +2251,42 @@ have the following in your .vimrc: >
let filetype_m = "mma"
MODULA2 *modula2.vim* *ft-modula2-syntax*

Vim will recognise comments with dialect tags to automatically select a given
dialect.

The syntax for a dialect tag comment is: >
taggedComment :=
'(*!' dialectTag '*)'
;
dialectTag :=
m2pim | m2iso | m2r10
;
reserved words
m2pim = 'm2pim', m2iso = 'm2iso', m2r10 = 'm2r10'
A dialect tag comment is recognised by Vim if it occurs within the first 200
lines of the source file. Only the very first such comment is recognised, any
additional dialect tag comments are ignored.

Example: >
DEFINITION MODULE FooLib; (*!m2pim*)
...
Variable g:modula2_default_dialect sets the default Modula-2 dialect when the
dialect cannot be determined from the contents of the Modula-2 file: if
defined and set to 'm2pim', the default dialect is PIM.

Example: >
let g:modula2_default_dialect = 'm2pim'
MOO *moo.vim* *ft-moo-syntax*

If you use C-style comments inside expressions and find it mangles your
Expand Down
2 changes: 2 additions & 0 deletions runtime/doc/tags
Expand Up @@ -7267,6 +7267,7 @@ ft-metapost-intro ft_mp.txt /*ft-metapost-intro*
ft-metapost-mappings ft_mp.txt /*ft-metapost-mappings*
ft-metapost-settings ft_mp.txt /*ft-metapost-settings*
ft-mma-syntax syntax.txt /*ft-mma-syntax*
ft-modula2-syntax syntax.txt /*ft-modula2-syntax*
ft-moo-syntax syntax.txt /*ft-moo-syntax*
ft-msql-syntax syntax.txt /*ft-msql-syntax*
ft-n1ql-syntax syntax.txt /*ft-n1ql-syntax*
Expand Down Expand Up @@ -8653,6 +8654,7 @@ modeline options.txt /*modeline*
modeline-local options.txt /*modeline-local*
modeline-version options.txt /*modeline-version*
modifyOtherKeys map.txt /*modifyOtherKeys*
modula2.vim syntax.txt /*modula2.vim*
moo.vim syntax.txt /*moo.vim*
more-compatible version5.txt /*more-compatible*
more-prompt message.txt /*more-prompt*
Expand Down
16 changes: 12 additions & 4 deletions runtime/filetype.vim
Expand Up @@ -619,8 +619,8 @@ au BufNewFile,BufRead *.intr setf dylanintr
" Dylan
au BufNewFile,BufRead *.dylan setf dylan

" Microsoft Module Definition
au BufNewFile,BufRead *.def setf def
" Microsoft Module Definition or Modula-2
au BufNewFile,BufRead *.def call dist#ft#FTdef()

" Dracula
au BufNewFile,BufRead *.drac,*.drc,*lvs,*lpe setf dracula
Expand Down Expand Up @@ -1339,8 +1339,16 @@ au BufNewFile,BufRead *.mmp setf mmp
" ABB Rapid, Modula-2, Modsim III or LambdaProlog
au BufNewFile,BufRead *.mod\c call dist#ft#FTmod()

" Modula-2 (.md removed in favor of Markdown, see dist#ft#FTmod for *.MOD)
au BufNewFile,BufRead *.m2,*.DEF,*.mi setf modula2
" TODO: --djk
" " Classic Modula-2 (.DEF, .MOD)
if has("fname_case")
au BufNewFile,BufRead *.DEF,*.MOD setf modula2
endif

" TODO: *.m2, *.mi, *.mod are mentioned in the Wikipedia page and elsewhere as
" extensions. Do we need to continue to support them? --djk
" Modula-2 (.md removed in favor of Markdown)
au BufNewFile,BufRead *.m2,*.mi setf modula2

" Modula-3 (.m3, .i3, .mg, .ig)
au BufNewFile,BufRead *.[mi][3g] setf modula3
Expand Down
35 changes: 23 additions & 12 deletions runtime/ftplugin/modula2.vim
Expand Up @@ -11,28 +11,39 @@ let b:did_ftplugin = 1
let s:cpo_save = &cpo
set cpo&vim

setlocal comments=s0:(*,mb:\ ,ex:*)
setlocal commentstring=(*%s*)
let s:dialect = modula2#GetDialect()

if s:dialect ==# "r10"
setlocal comments=s:(*,m:\ ,e:*),:!
setlocal commentstring=!\ %s
else
setlocal commentstring=(*%s*)
setlocal comments=s:(*,m:\ ,e:*)
endif
setlocal formatoptions-=t formatoptions+=croql

let b:undo_ftplugin = "setl com< cms< fo<"

if exists("loaded_matchit") && !exists("b:match_words")
" The second branch of the middle pattern is intended to match CASE labels
let b:match_ignorecase = 0
" the second branch of the middle pattern is intended to match CASE labels
let b:match_words = '\<REPEAT\>:\<UNTIL\>,' ..
\ '\<\%(BEGIN\|CASE\|FOR\|IF\|LOOP\|WHILE\|WITH\)\>' ..
\ ':' ..
\ '\<\%(ELSIF\|ELSE\)\>\|\%(^\s*\)\@<=\w\+\%(\s*\,\s*\w\+\)\=\s*\:=\@!' ..
\ ':' ..
\ '\<END\>'
\ '\<\%(BEGIN\|CASE\|FOR\|IF\|LOOP\|WHILE\|WITH\|RECORD\)\>' ..
\ ':' ..
\ '\<\%(ELSIF\|ELSE\)\>\|\%(^\s*\)\@<=\w\+\%(\s*\,\s*\w\+\)\=\s*\:=\@!' ..
\ ':' ..
\ '\<END\>,' ..
\ '(\*:\*),<\*:\*>'
let b:match_skip = 's:Comment\|Pragma'
let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_skip b:match_words"
endif

if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Modula-2 Source Files (*.def *.mod)\t*.def;*.mod\n" ..
\ "All Files (*.*)\t*.*\n"
\ "All Files (*.*)\t*.*\n"
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif

let b:undo_ftplugin = "setl com< cms< fo< " ..
\ "| unlet! b:browsefilter b:match_words"

let &cpo = s:cpo_save
unlet s:cpo_save

Expand Down
6 changes: 4 additions & 2 deletions runtime/makemenu.vim
Expand Up @@ -384,8 +384,10 @@ SynMenu M.MMIX:mmix
SynMenu M.Modconf:modconf
SynMenu M.Model:model
SynMenu M.Modsim\ III:modsim3
SynMenu M.Modula\ 2:modula2
SynMenu M.Modula\ 3:modula3
SynMenu M.Modula-2.R10\ (2010):modula2r10
SynMenu M.Modula-2.ISO\ (1994):modula2iso
SynMenu M.Modula-2.PIM\ (1985):modula2pim
SynMenu M.Modula-3:modula3
SynMenu M.Monk:monk
SynMenu M.Motorola\ S-Record:srec
SynMenu M.Mplayer\ config:mplayerconf
Expand Down
40 changes: 21 additions & 19 deletions runtime/synmenu.vim
Expand Up @@ -359,25 +359,27 @@ an 50.70.340 &Syntax.M.MMIX :cal SetSyn("mmix")<CR>
an 50.70.350 &Syntax.M.Modconf :cal SetSyn("modconf")<CR>
an 50.70.360 &Syntax.M.Model :cal SetSyn("model")<CR>
an 50.70.370 &Syntax.M.Modsim\ III :cal SetSyn("modsim3")<CR>
an 50.70.380 &Syntax.M.Modula\ 2 :cal SetSyn("modula2")<CR>
an 50.70.390 &Syntax.M.Modula\ 3 :cal SetSyn("modula3")<CR>
an 50.70.400 &Syntax.M.Monk :cal SetSyn("monk")<CR>
an 50.70.410 &Syntax.M.Motorola\ S-Record :cal SetSyn("srec")<CR>
an 50.70.420 &Syntax.M.Mplayer\ config :cal SetSyn("mplayerconf")<CR>
an 50.70.430 &Syntax.M.MOO :cal SetSyn("moo")<CR>
an 50.70.440 &Syntax.M.Mrxvtrc :cal SetSyn("mrxvtrc")<CR>
an 50.70.450 &Syntax.M.MS-DOS/Windows.4DOS\ \.bat\ file :cal SetSyn("btm")<CR>
an 50.70.460 &Syntax.M.MS-DOS/Windows.\.bat\/\.cmd\ file :cal SetSyn("dosbatch")<CR>
an 50.70.470 &Syntax.M.MS-DOS/Windows.\.ini\ file :cal SetSyn("dosini")<CR>
an 50.70.480 &Syntax.M.MS-DOS/Windows.Message\ text :cal SetSyn("msmessages")<CR>
an 50.70.490 &Syntax.M.MS-DOS/Windows.Module\ Definition :cal SetSyn("def")<CR>
an 50.70.500 &Syntax.M.MS-DOS/Windows.Registry :cal SetSyn("registry")<CR>
an 50.70.510 &Syntax.M.MS-DOS/Windows.Resource\ file :cal SetSyn("rc")<CR>
an 50.70.520 &Syntax.M.Msql :cal SetSyn("msql")<CR>
an 50.70.530 &Syntax.M.MuPAD :cal SetSyn("mupad")<CR>
an 50.70.540 &Syntax.M.Murphi :cal SetSyn("murphi")<CR>
an 50.70.550 &Syntax.M.MUSHcode :cal SetSyn("mush")<CR>
an 50.70.560 &Syntax.M.Muttrc :cal SetSyn("muttrc")<CR>
an 50.70.380 &Syntax.M.Modula-2.PIM\ (1985) :cal SetSyn("modula2pim")<CR>
an 50.70.390 &Syntax.M.Modula-2.ISO\ (1994) :cal SetSyn("modula2iso")<CR>
an 50.70.400 &Syntax.M.Modula-2.R10\ (2010) :cal SetSyn("modula2r10")<CR>
an 50.70.410 &Syntax.M.Modula-3 :cal SetSyn("modula3")<CR>
an 50.70.420 &Syntax.M.Monk :cal SetSyn("monk")<CR>
an 50.70.430 &Syntax.M.Motorola\ S-Record :cal SetSyn("srec")<CR>
an 50.70.440 &Syntax.M.Mplayer\ config :cal SetSyn("mplayerconf")<CR>
an 50.70.450 &Syntax.M.MOO :cal SetSyn("moo")<CR>
an 50.70.460 &Syntax.M.Mrxvtrc :cal SetSyn("mrxvtrc")<CR>
an 50.70.470 &Syntax.M.MS-DOS/Windows.4DOS\ \.bat\ file :cal SetSyn("btm")<CR>
an 50.70.480 &Syntax.M.MS-DOS/Windows.\.bat\/\.cmd\ file :cal SetSyn("dosbatch")<CR>
an 50.70.490 &Syntax.M.MS-DOS/Windows.\.ini\ file :cal SetSyn("dosini")<CR>
an 50.70.500 &Syntax.M.MS-DOS/Windows.Message\ text :cal SetSyn("msmessages")<CR>
an 50.70.510 &Syntax.M.MS-DOS/Windows.Module\ Definition :cal SetSyn("def")<CR>
an 50.70.520 &Syntax.M.MS-DOS/Windows.Registry :cal SetSyn("registry")<CR>
an 50.70.530 &Syntax.M.MS-DOS/Windows.Resource\ file :cal SetSyn("rc")<CR>
an 50.70.540 &Syntax.M.Msql :cal SetSyn("msql")<CR>
an 50.70.550 &Syntax.M.MuPAD :cal SetSyn("mupad")<CR>
an 50.70.560 &Syntax.M.Murphi :cal SetSyn("murphi")<CR>
an 50.70.570 &Syntax.M.MUSHcode :cal SetSyn("mush")<CR>
an 50.70.580 &Syntax.M.Muttrc :cal SetSyn("muttrc")<CR>
an 50.80.100 &Syntax.NO.N1QL :cal SetSyn("n1ql")<CR>
an 50.80.110 &Syntax.NO.Nanorc :cal SetSyn("nanorc")<CR>
an 50.80.120 &Syntax.NO.Nastran\ input/DMAP :cal SetSyn("nastran")<CR>
Expand Down

0 comments on commit fd0a6f1

Please sign in to comment.