commit 2dba6368a5f06c41e6fd99e4c472ca1e4de1bd74 Author: Erik Mertens Date: Mon Jul 31 09:22:36 2023 +0200 - created plugin diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..f25861f --- /dev/null +++ b/README.md @@ -0,0 +1,151 @@ +rpgle.vim +========= + +What does it contain? +--------------------- + +Free-Form ILE RPG bundle for vim, which contains syntax highlighting, syntax +folds, auto indent, more match words and a few sensible keys is remapped. + +### Indent + +One should modify `g:rpgle_indentStart` to adjust initial indentation level, +see `:help g:rpgle_indentStart` for more information. + +There is support for automatic indentation. An example is: + + dcl-proc myProc; + _ + +The cursor is located at `_` and the indent was inserted automatic when +pressing enter after `dcl-proc`. When typing `end-proc;` the indentation will +be decreased. + +With procedure interfaces indentation will only happen if the procedure takes +an argument: + + dcl-pi myProc; + _ + +If one type `end-pi;` the result will automatic become: + + dcl-pi myProc; + end-pi; + +`select`-`when`-`other`-`endsl` will be indented like this: + + select; + when; + a(); + when; + b(); + other; + c(); + _ + +As soon as `endsl` is typed it will be aligned with the initial `select;`. + +`if`-`elseif`-`else`-`endif` will be indented like this: + + if a = 1; + a(); + elseif b = 1; + b(); + else; + c(); + _ + +When typing `endif` the indentation will be decreased. + +Currently proper SQL indentation is missing: + + exec sql + select * + from a + order by 1 desc; + +See `:help ft-rpgle-indent` + +### Syntax + +Keywords, procedures and built-in functions will all be highlighted. + +See `:help ft-rpgle-syntax` + +### Syntax Folds + +The following folds are supported: + + - if -> endif + - dow -> enddo + - dou -> enddo + - for -> endfor + - select -> endsl + - dcl-proc -> end-proc + - begsr -> endsr + +See `:help ft-rpgle-fold` + +### Match Words + +The following match words are supported: + + - select -> when -> other -> endsl + - if -> elseif -> else -> endif + - dow -> iter -> leave -> enddo + - dou -> iter -> leave -> enddo + - begsr -> endsr + - dcl-proc -> return -> endproc + - dcl-pi -> end-pi + - monitor -> on-error -> endmon + +See `:help ft-rpgle-match-words` + +### Movements + +rpgle.vim takes the liberty to bind `[[`, `]]`, `[]`, `][`, `gd`, `[{` and `]}` +and tried to make them useful for ILE RPG programming. + +`[[` and `]]` will jump to the previous or next `dcl-proc` while `][` and `[]` +will jump to the previous or next `end-proc`. + +`gd` will search for the word under the cursor from the previous `dcl-proc`. + +`[{` and `]}` will jump to the associated block opener, i.e. standing inside an +`if` statement and pressing `[{` will bring you to the `if`, pressing `]}` will +bring you to the `endif`. + +See `:help ft-rpgle-movements` + +### Omni Completion + +rpgle.vim provides a naive omni completion that will attempt to suggest +completion for compiler directives and header, declaration, calculation and +procedure specifications. + +Calculation specification completion requires generated generated tags. + +See `:h ft-rpgle-omni` + +Contributing +------------ + +Make a [pull request](https://github.com/andlrc/rpgle.vim/pulls) or +[issue](https://github.com/andlrc/rpgle.vim/issues) + +Self-Promotion +-------------- + +Like rpgle.vim? Then you might also like: + +- [rpglectags](https://github.com/andlrc/rpglectags) which creates tags files + from ILE RPG, +- [rpgleman](https://github.com/andlrc/rpgleman) which provides man pages for + built-in functions keywords and more, +- and [rpglefmt](https://github.com/andlrc/rpglefmt) which will format Free Form ILE + RPG programs. + +License +------- + +Distributed under the same terms as Vim itself. See `:help license` diff --git a/autoload/rpgle/movement.vim b/autoload/rpgle/movement.vim new file mode 100644 index 0000000..5b7dd06 --- /dev/null +++ b/autoload/rpgle/movement.vim @@ -0,0 +1,98 @@ +" Vim autoload file +" Language: Free-Form ILE RPG +" Maintainer: Andreas Louv +" Last Change: Dec 04, 2018 +" Version: 10 +" URL: https://github.com/andlrc/rpgle.vim + +function! rpgle#movement#NextSection(motion, flags, mode) range abort + + let cnt = v:count1 + let old_pos = line('.') + + if a:mode ==# 'x' + normal! gv + endif + + normal! 0 + + mark ' + while cnt > 0 + call search(a:motion, a:flags . 'W') + if old_pos == line('.') + execute 'norm!' a:flags =~# 'b' ? 'gg' : 'G' + endif + let old_pos = line('.') + let cnt = cnt - 1 + endwhile + + normal! ^ +endfunction + +function! rpgle#movement#NextNest(flags) abort + let flags = a:flags + let fn = a:flags ==# 'b' ? 'max' : 'min' + + " We can get the list from ``b:match_words'' and just use first and last of + " each group + let poss = filter(map(split(b:match_words, ','), + \ { key, val -> + \ s:nextNestSearch(split(val, ':'), flags) }), + \ { key, val -> val > 0 }) + + let new_pos = call(fn, [poss]) + + if new_pos > 0 + execute 'normal! ' . new_pos . 'G^' + endif +endfunction + +function! s:nextNestSearch(kw, flags) abort + if a:kw[0] =~? 'if' + let middle = '\<\(else\|elseif\)\>' + elseif a:kw[0] =~? 'select' + let middle = '\<\(when\|other\)\>' + else + let middle = '' + endif + + return s:findpair(a:kw[0], middle, a:kw[-1], a:flags) +endfunction + +function! s:findpair(start, middle, end, flags) abort + " Find a pair which isn't inside a string nor comment + return searchpair(a:start, a:middle, a:end, a:flags . 'nW', + \ 'synIDattr(synID(line("."), col("."), 1), "name") =~? "string\\|comment"') +endfunction + +function! rpgle#movement#Operator(ai) abort + let pairs = map(split(b:match_words, ','), { key, val -> + \ [split(val, ':')[0], split(val, ':')[-1]] }) + + " Find a pair which isn't inside a string nor comment + + let poss = filter(map(pairs, + \ { key, val -> {"pair": val, "pos": s:findpair(val[0], '', val[1], 'b')} }), + \ { key, val -> val.pos > 0 }) + + let closest = { "index": 0, "pos": -1 } + let index = 0 + for pos in poss + if pos.pos > closest.pos + let closest.pos = pos.pos + let closest.index = index + let closest.pair = pos.pair + endif + let index = index + 1 + endfor + + let match_words = b:match_words + let b:match_words = join(closest.pair, ':') + execute 'normal! ' . closest.pos . 'G^V' + normal % + let b:match_words = match_words + + if a:ai == 'i' + normal! koj + endif +endfunction diff --git a/autoload/rpgle/omni.vim b/autoload/rpgle/omni.vim new file mode 100644 index 0000000..dc792f5 --- /dev/null +++ b/autoload/rpgle/omni.vim @@ -0,0 +1,428 @@ +" Vim completion script +" Language: Free-Form ILE RPG +" Maintainer: Andreas Louv +" Last Change: Jul 24, 2019 +" Version: 10 +" URL: https://github.com/andlrc/rpgle.vim +" +" Complete via tag files, this code is experimental + +let s:keywords = [ + \ ['alias', ['ds']], + \ ['align', ['ds']], + \ ['alt(', ['s', 'ds']], + \ ['altseq(', ['s', 'ds', 'subf', 'pi', 'pr', 'prp']], + \ ['ascend', ['s', 'ds', 'prp']], + \ ['based(', ['s', 'ds', 'pr']], + \ ['bindec(', ['s', 'subf', 'pip', 'prp']], + \ ['ccsid(', ['s', 'subf', 'pip', 'prp']], + \ ['char(', ['s', 'subf', 'pip', 'prp']], + \ ['class(', ['s', 'subf', 'pip', 'prp']], + \ ['const(', ['c']], + \ ['ctdata', ['s', 'subf']], + \ ['date', ['s', 'subf', 'pip', 'prp']], + \ ['date(', ['s', 'subf', 'pip', 'prp']], + \ ['descend', ['s', 'ds', 'prp']], + \ ['dim(', ['s', 'ds', 'pi', 'pip', 'pr', 'prp']], + \ ['dtaara', ['s', 'ds', 'subf']], + \ ['dtaara(', ['s', 'ds', 'subf']], + \ ['export', ['s', 'ds', 'proc']], + \ ['export(', ['s', 'ds', 'proc']], + \ ['ext', ['ds']], + \ ['extfld', ['subf']], + \ ['extfld(', ['subf']], + \ ['extname(', ['ds']], + \ ['extpgm', ['pr']], + \ ['extpgm(', ['pr']], + \ ['extproc', ['pr']], + \ ['extproc(', ['pr']], + \ ['extproc(', ['pr']], + \ ['float(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['graph(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['import', ['s', 'ds', 'proc']], + \ ['import(', ['s', 'ds', 'proc']], + \ ['int(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['ind', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['inz', ['s', 'ds', 'subf']], + \ ['inz(', ['s', 'subf']], + \ ['len(', ['s', 'ds', 'subf', 'pr', 'prp']], + \ ['like(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['likeds(', ['ds']], + \ ['likefile(', ['prp']], + \ ['likerec(', ['ds', 'subf', 'pr', 'prp']], + \ ['noopt', ['s', 'ds']], + \ ['nullind', ['s', 'ds']], + \ ['nullind(', ['s', 'ds']], + \ ['object', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['object(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['occurs(', ['ds']], + \ ['opdesc', ['pr']], + \ ['options(', ['pip', 'prp']], + \ ['overlay(', ['subf']], + \ ['packed(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['packeven', ['subf']], + \ ['perrcd(', ['s']], + \ ['pointer', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['pointer(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['pos(', ['subf']], + \ ['prefix(', ['subf']], + \ ['psds', ['ds']], + \ ['qualified', ['ds']], + \ ['static', ['s', 'ds']], + \ ['static(', ['s', 'ds']], + \ ['template', ['s', 'ds']], + \ ['time', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['time(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['timestamp', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['timestamp(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['ucs2(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['uns(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['value', ['pip', 'prp']], + \ ['varchar(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['vargraph(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['varucs2(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], + \ ['zoned(', ['s', 'subf', 'pi', 'pip', 'pr', 'prp']], +\ ] + +let s:bifs = [ + \ ['%abs', 'Absolute Value of Expression'], + \ ['%addr', 'Get Address of Variable'], + \ ['%alloc', 'Allocate Storage'], + \ ['%bitand', 'Bitwise AND Operation'], + \ ['%bitnot', 'Invert Bits'], + \ ['%bitor', 'Bitwise OR Operation'], + \ ['%bitxor', 'Bitwise Exclusive-OR Operation'], + \ ['%char', 'Convert to Character Data'], + \ ['%check', 'Check Characters'], + \ ['%checkr', 'Check Reverse'], + \ ['%data', 'document {:options}'], + \ ['%date', 'Convert to Date'], + \ ['%days', 'Number of Days'], + \ ['%dec', 'Convert to Packed Decimal Format'], + \ ['%dech', 'Convert to Packed Decimal Format with Half Adjust'], + \ ['%decpos', 'Get Number of Decimal Positions'], + \ ['%diff', 'Difference Between Two Date, Time, or Timestamp Values'], + \ ['%div', 'Return Integer Portion of Quotient'], + \ ['%editc', 'Edit Value Using an Editcode'], + \ ['%editflt', 'Convert to Float External Representation'], + \ ['%editw', 'Edit Value Using an Editword'], + \ ['%elem', 'Get Number of Elements'], + \ ['%eof', 'Return End or Beginning of File Condition'], + \ ['%equal', 'Return Exact Match Condition'], + \ ['%error', 'Return Error Condition'], + \ ['%fields', 'Fields to update'], + \ ['%float', 'Convert to Floating Format'], + \ ['%found', 'Return Found Condition'], + \ ['%graph', 'Convert to Graphic Value'], + \ ['%handler', 'handlingProcedure : communicationArea '], + \ ['%hours', 'Number of Hours'], + \ ['%int', 'Convert to Integer Format'], + \ ['%inth', 'Convert to Integer Format with Half Adjust'], + \ ['%kds', 'Search Arguments in Data Structure'], + \ ['%len', 'Get or Set Length'], + \ ['%lookupxx', 'Look Up an Array Element'], + \ ['%max', 'Maximum Value'], + \ ['%min', 'Minimum Value'], + \ ['%minutes', 'Number of Minutes'], + \ ['%months', 'Number of Months'], + \ ['%mseconds', 'Number of Microseconds'], + \ ['%nullind', 'Query or Set Null Indicator'], + \ ['%occur', 'Set/Get Occurrence of a Data Structure'], + \ ['%open', 'Return File Open Condition'], + \ ['%paddr', 'Get Procedure Address'], + \ ['%parms', 'Return Number of Parameters'], + \ ['%parmnum', 'Return Parameter Number'], + \ ['%parser', 'parser {: options}'], + \ ['%proc', 'Return Name of Current Procedure'], + \ ['%realloc', 'Reallocate Storage'], + \ ['%rem', 'Return Integer Remainder'], + \ ['%replace', 'Replace Character String'], + \ ['%scan', 'Scan for Characters'], + \ ['%scanr', 'Scan Reverse for Characters'], + \ ['%scanrpl', 'Scan and Replace Characters'], + \ ['%seconds', 'Number of Seconds'], + \ ['%shtdn', 'Shut Down'], + \ ['%size', 'Get Size in Bytes'], + \ ['%sqrt', 'Square Root of Expression'], + \ ['%status', 'Return File or Program Status'], + \ ['%str', 'Get or Store Null-Terminated String'], + \ ['%subarr', 'Set/Get Portion of an Array'], + \ ['%subdt', 'Extract a Portion of a Date, Time, or Timestamp'], + \ ['%subst', 'Get Substring'], + \ ['%this', 'Return Class Instance for Native Method'], + \ ['%time', 'Convert to Time'], + \ ['%timestamp', 'Convert to Timestamp'], + \ ['%tlookupxx', 'Look Up a Table Element'], + \ ['%trim', 'Trim Characters at Edges'], + \ ['%triml', 'Trim Leading Characters'], + \ ['%trimr', 'Trim Trailing Characters'], + \ ['%ucs2', 'Convert to UCS-2 Value'], + \ ['%uns', 'Convert to Unsigned Format'], + \ ['%unsh', 'Convert to Unsigned Format with Half Adjust'], + \ ['%xfoot', 'Sum Array Expression Elements'], + \ ['%xlate', 'Translate'], + \ ['%xml', 'xmlDocument {:options}'], + \ ['%years', 'Number of Years'] +\] + +function! rpgle#omni#Complete(findstart, base) abort + if a:findstart + " Locate the start of the item + let line = getline('.') + let start = col('.') - 1 + + if line =~? '^\s*/' + " Compiler directive + let s:type = 'compdir' + while start > 0 + if line[start - 1] =~? '\S' + let start -= 1 + else + break + endif + endwhile + elseif line =~? '^\s*ctl-opt\>' + " Header Specs + let s:type = 'hspec' + while start > 0 + if line[start - 1] =~? '\k' + let start -= 1 + else + break + endif + endwhile + elseif line =~? '^\s*dcl-' + " Declaration Specs + let s:type = 'dspec' + while start > 0 + if line[start - 1] =~? '\k' + let start -= 1 + else + break + endif + endwhile + else + " Assume Calculation Spec + let s:type = 'cspec' + let lastword = -1 + while start > 0 + if line[start - 1] =~# '\w' + let start -= 1 + elseif line[start - 1] ==# '.' + let s:type = 'cspec_struct' + let member_start = start + let start -= 1 + elseif line[start - 1] ==# '%' + let s:type = 'cspec_bif' + let start -= 1 + else + break + endif + endwhile + + if s:type ==# 'cspec_struct' + let s:struct = strpart(line, start, member_start - start - 1) + return member_start + endif + endif + let s:struct = '' + return start + endif + + " Return list of matches: + if s:type ==# 'compdir' + return s:Compdir(a:base) + elseif s:type ==# 'hspec' + return s:HSpec(a:base) + elseif s:type ==# 'dspec' + return s:DSpec(a:base) + elseif s:type ==# 'cspec_struct' + return s:CSpecStruct(a:base, s:struct) + elseif s:type ==# 'cspec_bif' + return s:CSpecBIF(a:base) + elseif s:type ==# 'cspec' + return s:CSpec(a:base) + endif +endfunction + +function! s:Compdir(base) abort + let line = getline('.') + echom a:base + " Filename completion + if line =~? '^\s*/\%(include\|copy\)\s\+' + let matches = globpath(&path, '*', 0, 1) + call filter(matches, { key, val -> val =~? '\.\%(rpgleinc\|mbr\)$' }) + call map(matches, 's:Path2Suggetion(v:val)') + call filter(matches, { key, val -> val =~? '\%(^\|,\)' . a:base }) + return map(matches, 's:Path2Item(v:val)') + else + return filter(['/copy', '/define', '/eject', '/else', '/elseif', + \ '/end-free', '/endif', '/eof', '/free', '/if', '/include', + \ '/restore', '/set', '/space', '/title', '/undefine'], + \ { key, val -> val =~? '^' . a:base }) + endif +endfunction + +function! s:HSpec(base) abort + return filter(['actgrp(', 'alloc(', 'altseq', 'alwnull(', 'aut(', + \ 'bnddir(', 'ccsid(', 'ccsidcvt(', 'copynest(', 'copyright(', + \ 'cursym(', 'cvtopt(', 'datedit(', 'datfmt(', 'dclopt(', + \ 'debug', 'decedit(', 'decprec(', 'dftactgrp(', 'dftname(', + \ 'enbpfrcol(', 'expropts(', 'extbinint', 'fixnbr(', 'fltdiv', + \ 'formsalign', 'ftrans', 'genlvl(', 'indent(', 'intprec(', + \ 'langid(', 'main(', 'nomain', 'openopt(', 'optimize(', + \ 'option(', 'pgminfo(', 'prfdta(', 'srtseq(', 'stgmdl(', + \ 'text(', 'thread(', 'timfmt(', 'truncnbr(', 'usrprf(', + \ 'validate('], + \ { key, val -> val =~? '^' . a:base }) +endfunction + +function! s:DSpec(base) abort + if a:base =~? 'dcl-' + let matches = filter(['dcl-s', 'dcl-c', 'dcl-ds', 'dcl-pr', 'dcl-proc', + \ 'dcl-pi'], + \ { key, val -> val =~? '^' . a:base }) + else + " Keyword completion + let line = getline('.') + let type = substitute(line, + \ '^\s*dcl-\(s\|c\|ds\|pr\|proc\|pi\)\s\+\w\+\s\+.*', + \ '\1', '') + if type != line + let matches = [] + for kw in s:keywords + if kw[0] =~? '^' . a:base && index(kw[1], type) > -1 + call add(matches, kw[0]) + endif + endfor + else + let matches = [] + endif + endif + + return map(matches, 's:Keyword2Item(v:val)') +endfunction + +" Member completion via tags +function! s:CSpecStruct(base, struct) abort + let matches = [] + let tags = taglist('^' . a:base) + let curbufnr = bufnr('%') + let struct = a:struct + + " Resolve referenced data structure (``likeds(...)'') + let struct_tags = taglist('^' . struct . '$') + for tag in struct_tags + if complete_check() + break + endif + + if tag['kind'] ==? 's' && has_key(tag, 'typeref') + let struct = substitute(tag['typeref'], 'struct:', '', '') + break + endif + endfor + + for tag in tags + if complete_check() + break + endif + + " Remove static matches in other files. + if tag['static'] && bufnr('%') != bufnr(tag['filename']) + continue + endif + + " Remove anything but members + if tag['kind'] !=? 'm' + continue + endif + + " Remove members from other data structures + if tag['struct'] !=? struct + continue + endif + + call add(matches, s:Tag2Item(tag)) + endfor + + return matches +endfunction + +function! s:CSpecBIF(base) abort + let matches = [] + for bif in s:bifs + if bif[0] =~? '^' . a:base + call add(matches, s:BIF2Item(bif)) + endif + endfor + return matches +endfunction + +" Keyword completion via tags +function! s:CSpec(base) abort + let matches = [] + let tags = taglist('^' . a:base) + let curbufnr = bufnr('%') + + for tag in tags + if complete_check() + break + endif + + " Remove static matches in other files. + if tag['static'] && curbufnr != bufnr(tag['filename']) + continue + endif + + " Remove members + if tag['kind'] ==? 'm' + continue + endif + + call add(matches, s:Tag2Item(tag)) + endfor + +return matches +endfunction + +function! s:Path2Suggetion(path) abort + let path = substitute(a:path, + \ '^.\{-}\ +License: Same terms as Vim itself (see |license|) + +INTRODUCTION *ft-rpgle* + +This bundle provides syntax highlighting, syntax folds, auto indent, more +match words as well as mapping a few sensible keys. + +VARIABLES *ft-rpgle-variables* + + *g:rpgle_indentStart* +`g:rpgle_indentStart` Set the number of leading spaces that should be used + when no previous line is to be accounted for. + + *g:rpgle_skipMapping* +`g:rpgle_skipMapping` Set to |v:true| to disable mappings defined in + |ft-rpgle-movements|, |ft-rpgle-operator-pending| + + *g:rpgle_spellString* +`g:rpgle_spellString` Set to |v:false| to disable spell checking in string + constants. + +FILETYPE DETECT *ft-rpgle-detect* + +File ending with ".rpgle" and ".rpgleinc" are detected as ILE RPG files. + +INDENT *ft-rpgle-indent* + +Enable by adding the following to your |vimrc| > + :filetype indent on +< +SYNTAX *ft-rpgle-syntax* + +Enable by adding the following to your |vimrc| > + :syntax enable +< +SYNTAX FOLDS *ft-rpgle-fold* + +Settings |foldmethod| to 'syntax' to enable the following folds: > + if -> endif + dow -> enddo + dou -> enddo + for -> endfor + select -> endsl + dcl-proc -> end-proc + begsr -> endsr +< +MATCH WORDS *ft-rpgle-match-words* + +Enable by adding the following to your |vimrc| > + :packadd! matchit +< +The following match words is supported: > + select -> when -> other -> endsl + if -> elseif -> else -> endif + dow -> iter -> leave -> enddo + dou -> iter -> leave -> enddo + for -> iter -> leave -> endfor + begsr -> endsr + dcl-proc -> return -> end-proc + dcl-pi -> end-pi + dcl-pr -> end-pr + monitor -> on-error -> endmon +< +MOVEMENTS *ft-rpgle-movements* + +Enable by adding the following to your |vimrc| > + :filetype on +< + *ft-rpgle-[[* +[[ Jump to previous dcl-proc keyword + *ft-rpgle-]]* +]] Jump to next dcl-proc keyword + *ft-rpgle-[]* +[] Jump to previous end-proc keyword + *ft-rpgle-][* +][ Jump to next end-proc keyword + *ft-rpgle-gd* +gd Goto local Declaration. When the cursor is on a local + variable, this command will jump to its declaration. + Use |gD| to goto global declaration. + *ft-rpgle-[{* +[{ Jump back to the block opener at the start of the + current code block, i.e. pressing |[{| inside an + if-statement will jump to the if keyword. + *ft-rpgle-]}* +]} Jump forward to the block closer at the end of the + current code block, i.e. pressing |]}| inside an + if-statement will jump to the endif keyword. + +OPERATOR PENDING *ft-rpgle-operator-pending* + +Enable by adding the following to your |vimrc| > + :filetype on +< +a} *ft-rpgle-a}* *ft-rpgle-a{* +a{ *ft-rpgle-aB* +aB See |aB| + +i} *ft-rpgle-i}* *ft-rpgle-i{* +i{ *ft-rpgle-iB* +iB See |iB| + +INCLUDE *ft-rpgle-include* + +'include' is set to match "/include" and "/copy". ".rpgle" and ".rpgleinc" is +added when following files with |gf|, or when searching included files with +|[I| and friends. + +'includeexpr' is set to replace a "," with ".file/" i.e. > + /include myfile,mymbr -> myfile.file/mymbr.rpgleinc +< +It can be beneficial to setup 'path' accordantly: > + setlocal path=~/.cache/rpgleinc/qrpglesrc.file,~/.cache/rpgleinc +< And then download all headers to the respective directories inside + "~/.cache/rpgleinc". + +I.e the header called "myhdr" located in "qrpglesrc" should be saved as +"~/.cache/rpgleinc/qrpglesrc.file/myhdr.rpgle". + +One can use dd to download the files, i.e: > + $ dd if=/mnt_dir/QSYS.LIB/MY_LIB.LIB/QRPGLESRC.FILE/MYHDR.MBR \ + of=~/.cache/rpgleinc/qrpglesrc.file/myhdr.rpgleinc \ + bs=120 \ + cbs=120 \ + conv=ascii +< +Where 120 is the width of the header. + +OMNI COMPLETION *ft-rpgle-omni* + +Omni completion for compiler directives and header, declaration, calculation +and procedure specifications. + +Omni completion can be called with |i_CTRL-X_CTRL-O| + +OMNI COMPILER DIRECTIVES *ft-rpgle-omni-compdir* + +A file found via 'path' will be suggested for "/copy" and "/include". + +Only files ending with ".rpgleinc" and ".mbr" will be suggested. +Directories ending in ".file" will be preserved, with the exception of a +directory called "qrpglesrc.file" which will be removed. > + directory.file/file.mbr -> directory,file + qrpglesrc.file/file.mbr -> file +< +See |ft-rpgle-inclue| for a solution to downloading ILE RPG header files. + +OMNI HEADER SPECIFICATION *ft-rpgle-omni-hspec* + +Keywords like "bnddir" and "copyright" will be suggested. + +An example would be: > + ctl-opt bnd -> ctl-opt bnddir( +< +OMNI DECLARATION SPECIFICATION *ft-rpgle-omni-dspec* + +Keywords like "static" and "dim" and types like "varchar" and "ind" will be +suggested for constants, standalone, data-structures, procedure-interfaces and +prototypes. + +An example would be: > + dcl-s name var -> dcl-s name varchar( + dcl-s name vargraph( + dcl-s name varucs2( + + dcl-ds name qual -> dcl-ds name qualified +< +OMNI PROCEDURE SPECIFICATION *ft-rpgle-omni-pspec* + +Keywords like "export" will be suggested. + +An example would be: > + dcl-proc name ex -> export + -> export( +< + vim:tw=78:ts=8:ft=help:norl: diff --git a/doc/tags b/doc/tags new file mode 100644 index 0000000..118c8af --- /dev/null +++ b/doc/tags @@ -0,0 +1,32 @@ +ft-rpgle rpgle.txt /*ft-rpgle* +ft-rpgle-[[ rpgle.txt /*ft-rpgle-[[* +ft-rpgle-[] rpgle.txt /*ft-rpgle-[]* +ft-rpgle-[{ rpgle.txt /*ft-rpgle-[{* +ft-rpgle-][ rpgle.txt /*ft-rpgle-][* +ft-rpgle-]] rpgle.txt /*ft-rpgle-]]* +ft-rpgle-]} rpgle.txt /*ft-rpgle-]}* +ft-rpgle-aB rpgle.txt /*ft-rpgle-aB* +ft-rpgle-a{ rpgle.txt /*ft-rpgle-a{* +ft-rpgle-a} rpgle.txt /*ft-rpgle-a}* +ft-rpgle-detect rpgle.txt /*ft-rpgle-detect* +ft-rpgle-fold rpgle.txt /*ft-rpgle-fold* +ft-rpgle-gd rpgle.txt /*ft-rpgle-gd* +ft-rpgle-iB rpgle.txt /*ft-rpgle-iB* +ft-rpgle-include rpgle.txt /*ft-rpgle-include* +ft-rpgle-indent rpgle.txt /*ft-rpgle-indent* +ft-rpgle-i{ rpgle.txt /*ft-rpgle-i{* +ft-rpgle-i} rpgle.txt /*ft-rpgle-i}* +ft-rpgle-match-words rpgle.txt /*ft-rpgle-match-words* +ft-rpgle-movements rpgle.txt /*ft-rpgle-movements* +ft-rpgle-omni rpgle.txt /*ft-rpgle-omni* +ft-rpgle-omni-compdir rpgle.txt /*ft-rpgle-omni-compdir* +ft-rpgle-omni-dspec rpgle.txt /*ft-rpgle-omni-dspec* +ft-rpgle-omni-hspec rpgle.txt /*ft-rpgle-omni-hspec* +ft-rpgle-omni-pspec rpgle.txt /*ft-rpgle-omni-pspec* +ft-rpgle-operator-pending rpgle.txt /*ft-rpgle-operator-pending* +ft-rpgle-syntax rpgle.txt /*ft-rpgle-syntax* +ft-rpgle-variables rpgle.txt /*ft-rpgle-variables* +g:rpgle_indentStart rpgle.txt /*g:rpgle_indentStart* +g:rpgle_skipMapping rpgle.txt /*g:rpgle_skipMapping* +g:rpgle_spellString rpgle.txt /*g:rpgle_spellString* +rpgle.txt rpgle.txt /*rpgle.txt* diff --git a/ftdetect/binder.vim b/ftdetect/binder.vim new file mode 100644 index 0000000..91bd446 --- /dev/null +++ b/ftdetect/binder.vim @@ -0,0 +1,9 @@ +" Vim ftdetect file +" Language: Binder Language +" Maintainer: Andreas Louv +" Last Change: Mar 20, 2019 +" Version: 2 +" URL: https://github.com/andlrc/rpgle.vim + +au BufNewFile,BufRead *.binder setlocal filetype=binder +au BufNewFile,BufRead *.BND setlocal filetype=binder diff --git a/ftdetect/clle.vim b/ftdetect/clle.vim new file mode 100644 index 0000000..c0d5b0b --- /dev/null +++ b/ftdetect/clle.vim @@ -0,0 +1,15 @@ + +if exists('b:current_syntax') + finish +endif + +let b:current_syntax = 'clle' + +" syntax case ignore +" syntax iskeyword @,48-57,192-255,-,%,*,/,_ + +" syntax keyword clleCommand CHGVAR + +" highlight link clleCommand Function + +au BufNewFile,BufRead *.clle setlocal filetype=clle diff --git a/ftdetect/rpgle.vim b/ftdetect/rpgle.vim new file mode 100644 index 0000000..eda8063 --- /dev/null +++ b/ftdetect/rpgle.vim @@ -0,0 +1,13 @@ +" Vim ftdetect file +" Language: Free-Form ILE RPG +" Maintainer: Andreas Louv +" Last Change: Mar 20, 2019 +" Version: 8 +" URL: https://github.com/andlrc/rpgle.vim + +au BufNewFile,BufRead *.rpgle setlocal filetype=rpgle +au BufNewFile,BufRead *.sqlrpgle setlocal filetype=rpgle +au BufNewFile,BufRead *.rpgleinc setlocal filetype=rpgle +au BufNewFile,BufRead *.RPGLE setlocal filetype=rpgle +au BufNewFile,BufRead *.SQLRPGLE setlocal filetype=rpgle +au BufNewFile,BufRead *.RPGLEINC setlocal filetype=rpgle diff --git a/ftplugin/binder.vim b/ftplugin/binder.vim new file mode 100644 index 0000000..47bf19c --- /dev/null +++ b/ftplugin/binder.vim @@ -0,0 +1,17 @@ +" Vim ftplugin file +" Language: Binder Language +" Maintainer: Andreas Louv +" Last Change: Mar 20, 2019 +" Version: 1 +" URL: https://github.com/andlrc/rpgle.vim + +if exists('b:did_ftplugin') + finish +endif + +let b:did_ftplugin = 1 + +setlocal suffixesadd=.binder + + +let b:match_words = '\:\' diff --git a/ftplugin/rpgle.vim b/ftplugin/rpgle.vim new file mode 100644 index 0000000..15aeb51 --- /dev/null +++ b/ftplugin/rpgle.vim @@ -0,0 +1,131 @@ +" Vim ftplugin file +" Language: Free-Form ILE RPG +" Maintainer: Andreas Louv +" Last Change: Dec 19, 2018 +" Version: 22 +" URL: https://github.com/andlrc/rpgle.vim + +if exists('b:did_ftplugin') + finish +endif + +let b:did_ftplugin = 1 + +setlocal iskeyword+=-,% +setlocal shiftwidth=2 + +setlocal suffixesadd=.rpgle,.rpgleinc +" setlocal include=^\\s*/\\%(include\\\|copy\\) +setlocal include=^\s*\/\%(include\|copy\) +setlocal includeexpr=../substitute(v:fname,',','.file/','') + +setlocal comments=s1:/*,mb:*,ex:*/,://,:* +setlocal commentstring=//%s + +setlocal conceallevel=3 +setlocal concealcursor=nvic +setlocal tabstop=2 +setlocal expandtab +setlocal textwidth=100 +setlocal colorcolumn=100 + +" ILE RPG is in case-sensitive +setlocal tagcase=ignore smartcase ignorecase + +let b:match_words = '\:\:\:\' + \ . ',\:\:\:\' + \ . ',\:\:\:\' + \ . ',\:\:\:\' + \ . ',\:\:\:\' + \ . ',\:\' + \ . ',\:\:\' + \ . ',\:\' + \ . ',\:\' + \ . ',\:\:\' + \ . ',\:\<\%(likeds\|extname\|end-ds\)\>' + +" section jumping {{{ + +nnoremap