diff --git a/tools/ctags/pyret.ctags b/tools/ctags/pyret.ctags new file mode 100644 index 0000000000..df7d74286c --- /dev/null +++ b/tools/ctags/pyret.ctags @@ -0,0 +1,11 @@ +--langdef=pyret +--langmap=pyret:.arr + +--regex-pyret=/^[ \t]*fun[ \t]+([a-zA-Z0-9_-]+)/\1/f,function/ +--regex-pyret=/^[ \t]*data[ \t]+([a-zA-Z0-9_-]+)/\1/d,data/ +--regex-pyret=/^[ \t]*\|[ \t]*([a-zA-Z0-9_-]+)[^=]*$/\1/d,data/ +--regex-pyret=/^[ \t]*\|[ \t]*([a-zA-Z0-9_-]+)[^=]*$/is-\1/d,data/ +--regex-pyret=/^([a-zA-Z0-9_-]+)[ \t]*=/\1/v,value/ +--regex-pyret=/^([a-zA-Z0-9_-]+)[ \t]*::[ \t]*[a-zA-Z0-9_<>}{. -]+[ \t]*=/\1/v,value/ +--regex-pyret=/^[ \t]*import[ \t]+[a-zA-Z0-9_-]+[ \t]+as[ \t]+([a-zA-Z0-9_-]+)/\1/i,import/ +--regex-pyret=/^[ \t]*import[ \t]+file\([^)]+\)[ \t]+as[ \t]+([a-zA-Z0-9_-]+)/\1/i,import/ diff --git a/tools/vim/README.md b/tools/vim/README.md new file mode 100644 index 0000000000..77a36132f4 --- /dev/null +++ b/tools/vim/README.md @@ -0,0 +1,12 @@ +# Pyret-lang.vim + +This is a copy of the repository [rachitnigam/pyret-lang.vim](https://github.com/rachitnigam/pyret-lang.vim) +as available on 08/31/2017. + +### Installation +For vim-plug, add the following: +``` +Plug '/tools/vim' +``` + +Install [UltiSnips](https://github.com/SirVer/ultisnips) for snippet support. diff --git a/tools/vim/UltiSnips/pyret.snippets b/tools/vim/UltiSnips/pyret.snippets new file mode 100644 index 0000000000..fc38fc2948 --- /dev/null +++ b/tools/vim/UltiSnips/pyret.snippets @@ -0,0 +1,52 @@ +snippet fun "fun ... end (fun)" +fun ${1:function_name}(${2:arguments}): + ${VISUAL}$0 +end +endsnippet + +snippet meth "method ... end (meth)" +meth ${1:method_name}(${2:arguments}): + ${VISUAL}$0 +end +endsnippet + +snippet lam "lam ... end (lam)" +lam(${2:arguments}): ${VISUAL}$0 end +endsnippet + +snippet (lam "(lam ... end ((lam)" +(lam(${2:arguments}): ${VISUAL}$0 end +endsnippet + +snippet ife "if ... else: ... end (ife)" +if ${1:condition}: + ${VISUAL}$0 +else: + ${3:else_branch} +end +endsnippet + +snippet cases "cases (type) ... end (cases)" +cases(${1:type}) ${2:v}: + | ${3:case1} +end +endsnippet + +snippet for "for ... end (for)" +for ${1:iterators}: + ${2:body} +end +endsnippet + +snippet block "block ... end (block)" +block: + ${VISUAL}$0 +end +endsnippet + +snippet data "data ... end (data)" +data ${1:Type}: + | ${2:Variant} +end +endsnippet + diff --git a/tools/vim/ftdetect/pyret.vim b/tools/vim/ftdetect/pyret.vim new file mode 100644 index 0000000000..d7de3d562c --- /dev/null +++ b/tools/vim/ftdetect/pyret.vim @@ -0,0 +1 @@ +au BufNewFile,BufRead *.arr set filetype=pyret diff --git a/tools/vim/ftplugin/pyret.vim b/tools/vim/ftplugin/pyret.vim new file mode 100644 index 0000000000..541d4f96d8 --- /dev/null +++ b/tools/vim/ftplugin/pyret.vim @@ -0,0 +1,8 @@ +if exists('b:did_ftplugin') + finish +endif + +let b:did_ftplugin = 1 + +" Set comment string +setlocal commentstring=#\ %s diff --git a/tools/vim/indent/pyret.vim b/tools/vim/indent/pyret.vim index 9108a2a9a1..96b8eb8aca 100644 --- a/tools/vim/indent/pyret.vim +++ b/tools/vim/indent/pyret.vim @@ -2,6 +2,8 @@ " Language: Pyret " Maintainer: Dorai Sitaram, ds26gte.github.io " Last Change: 2015-06-12 +" Originally from +" https://github.com/brownplt/pyret-lang/blob/master/tools/vim/indent/pyret.vim if exists("b:did_indent") finish diff --git a/tools/vim/syntax/pyret.vim b/tools/vim/syntax/pyret.vim index 60388f71ed..4c54a95b85 100644 --- a/tools/vim/syntax/pyret.vim +++ b/tools/vim/syntax/pyret.vim @@ -1,61 +1,191 @@ " Vim syntax file " Language: Pyret -" Maintainer: Joe Gibbs Politz (joe@cs.brown.edu) +" Maintainer: Rachit Nigam (rachit.nigam12@gmail.com) if exists("b:current_syntax") finish endif +syn case match +syn sync minlines=200 maxlines=1000 + set iskeyword+=- -set iskeyword+=: syn match delimeter '!' syn match delimeter '\.' -syn match delimeter '|' -syn match delimeter '(' -syn match delimeter ')' -syn match delimeter '->' syn match delimeter '=' -syn match delimeter '=>' syn match delimeter ':=' - -syn match delimeter '\[' -syn match delimeter '\]' -syn match delimeter '{' -syn match delimeter '}' syn match delimeter ':' -syn match delimeter '::' - -syn keyword basic var fun end with: sharing: data include import provide as try: except when -syn keyword basic for from check: where: doc: and or not else: if else cases -syn keyword basic is is== is=~ is<=> is-not is-not== is-not=~ is-not<=> raises -syn keyword basic deriving ref graph: m-graph: block: satisfies violates shadow lam type type-let provide-types newtype -syn keyword basic let rec letrec ask: table: extend using row: select extract order sieve by - -syn match op ' + ' -syn match op ' - ' -syn match op ' / ' -syn match op ' * ' -syn match op ' > ' -syn match op ' < ' -syn match op ' >= ' -syn match op ' <= ' -syn match op ' <> ' - -syn match comment '\#.*$' -syntax region comment start=/#|/ skip=/\./ end=/|#/ - -syntax region string start=/\v"/ skip=/\v\\./ end=/\v"/ -syntax region string start=/\v'/ skip=/\v\\./ end=/\v'/ -syntax region string start=/\v```/ skip=/\v\\./ end=/\v```/ - -syn match number "[0-9]+" - -hi def link comment Comment -hi def link basic Function -hi def link delimeter PreProc -hi def link op Label -hi def link string Constant -hi def link number Constant -hi def link literal Constant + +hi link delimeter PreProc + +" Keywords +syn keyword pyretKeyword var from shadow ref +hi link pyretKeyword Special + +" Imports and exports +syn keyword pyretImport include import provide provide-types as +hi link pyretImport PreProc + +" Block structures in pyret +syn keyword pyretBlock end for check examples +syn keyword pyretBlock except when +syn keyword pyretBlock if else +syn keyword pyretBlock deriving satisfies +syn keyword pyretBlock violates type-let +syn keyword pyretBlock let rec letrec extend using select +syn keyword pyretBlock extract order sieve by raises newtype +hi link pyretBlock Function + +" Built-in functions +syn keyword pyretBuiltin is is== is=~ is<=> is-not is-not== is-not=~ is-not<=> +syn keyword pyretBuiltin and or not +syn keyword pyretBuiltin torepr to-repr tostring to-string raise +syn keyword pyretBuiltin is-boolean is-number is-string is-raw-array is-nothing +syn keyword pyretBuiltin is-function is-object +hi link pyretBuiltin Constant + +" Operators +syn match pyretOperator '+' +syn match pyretOperator '-' +syn match pyretOperator '/' +syn match pyretOperator '*' +syn match pyretOperator '>' +syn match pyretOperator '<' +syn match pyretOperator '>=' +syn match pyretOperator '<=' +syn match pyretOperator '<>' +syn match pyretOperator '\^' +hi link pyretOperator Label + +" Comments +syn match pyretComment '\#.*$' contains=pyretTodo +syntax region pyretComment start=/#|/ skip=/\./ end=/|#/ contains=pyretTodo +hi link pyretComment Comment + +" Todo +syn match pyretTodo /\v<(TODO|FIXME|NOTE)>/ contained +hi link pyretTodo Todo + +" Strings +syn region pyretString start=/\v"/ skip=/\v\\./ end=/\v("|$)/ +syn region pyretString start=/\v'/ skip=/\v\\./ end=/\v('|$)/ +syn region pyretString start=/\v```/ skip=/\v\\./ end=/\v```/ +hi link pyretString String +syn match pyretEscapedChar '\v\\.' containedin=pyretString contained +hi link pyretEscapedChar Special + +" Numbers +syn match pyretConstant "\v(\-|\+)?[0-9]+(\.[0-9]+)?(e[0-9]+)?" +" Booleans +syn keyword pyretConstant true +syn keyword pyretConstant false +" nothing +syn keyword pyretConstant nothing + +hi link pyretConstant Constant + +" Template +syntax match pyretTemplate '\v\.\.\.' +hi link pyretTemplate ERROR + +" Variable names in pyret. Need to be higher priority than numbers +syn match pyretName '\v[_a-zA-Z]((\-+)?[_a-zA-Z0-9]+)*' + \ nextgroup=pyretColonColon skipwhite +syn match pyretColonColon '::' nextgroup=@pyretAnn skipwhite +hi link pyretColonColon Keyword + +" Keywords ending with :. Need to be after variables. +syn match pyretBlock 'with:' +syn match pyretBlock 'sharing:' +syn match pyretBlock 'try:' +syn match pyretBlock 'check:' +syn match pyretBlock 'where:' +syn match pyretBlock 'doc:' +syn match pyretBlock 'else:' +syn match pyretBlock 'graph:' +syn match pyretBlock 'block:' +syn match pyretBlock 'ask:' +syn match pyretBlock 'table:' +syn match pyretBlock 'row:' +syn match pyretBlock 'm-graph:' + +" Variables bound by `from` +syn match pyretFromName '\v[_a-zA-Z]((\-+)?[_a-zA-Z0-9]+)*\ze(\s+::\s+\S+)?\s+from' +hi link pyretFromName Identifier + +" Type Annotations +syn cluster pyretAnn + \ contains=pyretSimpleAnn,pyretComplexAnn,pyretRecordAnn,pyretParenAnn,pyretAnnDot + +syn region pyretComplexAnn matchgroup=Keyword start='\v\<' end='\v\>' + \ contained contains=@pyretAnn nextgroup=pyretAnnArrow,pyretRefineStart skipwhite +hi link pyretComplexAnn Type + +syn match pyretSimpleAnn '\v%((\w+-\w+)|\w+)' contained + \ nextgroup=pyretComplexAnn,pyretAnnArrow,pyretAnnDot,pyretRefineStart skipwhite +hi link pyretSimpleAnn Type + +syn match pyretRefineStart '\v\%' contained nextgroup=pyretRefineAnn +hi link pyretRefineStart Keyword + +syn region pyretRefineAnn matchgroup=Keyword start='\v\(' end='\v\)' contained + \ contains=pyretName nextgroup=pyretAnnArrow skipwhite + +syn match pyretAnnDot '\.' contained nextgroup=pyretSimpleAnn +hi link pyretAnnDot Keyword + +syn region pyretRecordAnn matchgroup=Keyword start='\v\{' end='\v\}' contained + \ contains=@pyretAnn,pyretSemicolon nextgroup=pyretAnnArrow skipwhite +hi link pyretRecordAnn Type + +syn match pyretSemicolon ';' contained +hi link pyretSemicolon Keyword + +syn region pyretParenAnn matchgroup=Keyword start='\v\(' end='\v\)' contained + \ contains=@pyretAnn skipwhite +hi link pyretParenAnn Type + +syn match pyretAnnArrow '\v-\>' contained nextgroup=@pyretAnn skipwhite +hi link pyretAnnArrow Keyword + +" `type` expressions +syn region pyretTypeDecl matchgroup=Keyword start='\v' end='\v$' + \ contains=@pyretAnn,pyretComment skipwhite keepend + +" fun defintions +syn keyword pyretBlock fun method nextgroup=pyretFunName skipwhite +syn keyword pyretBlock lam nextgroup=pyretArgs,pyretFunTypeParam skipwhite +syn match pyretFunComma ',' contained +hi link pyretFunComma Special + +syn match pyretFunName '\v[_a-zA-Z]((\-+)?[_a-zA-Z0-9]+)*' contained + \ nextgroup=pyretArgs,pyretFunTypeParam skipwhite +hi link pyretFunName Constant + +syn region pyretFunTypeParam matchgroup=Keyword start='\v\<' end='\v\>' + \ contained contains=@pyretAnn nextgroup=pyretArgs skipwhite +hi link pyretFunTypeParam Type + +syn region pyretArgs matchgroup=Keyword start='\v\(' end='\v\)' + \ contained contains=pyretArgName,pyretFunComma,pyretKeyword,pyretComment + \ nextgroup=pyretAnnArrow skipwhite +hi link pyretArgs Identifier + +syn match pyretArgName '\v[_a-zA-Z]((\-+)?[_a-zA-Z0-9]+)*' contained transparent + \ nextgroup=pyretColonColon skipwhite + +" cases using | +syn match pyretBar '\v\|' nextgroup=pyretFunName skipwhite +hi link pyretBar Keyword +syn match pyretCaseArrow '\v\=\>' +hi link pyretCaseArrow Keyword + +" Data defintions +syn keyword pyretBlock data nextgroup=pyretSimpleAnn skipwhite + +" cases keyword +syn keyword pyretBlock cases nextgroup=pyretCaseType skipwhite +syn region pyretCaseType matchgroup=Keyword start='\v\(' end='\v\)' + \ contained contains=@pyretAnn skipwhite diff --git a/tools/vim/test.arr b/tools/vim/test.arr new file mode 100644 index 0000000000..a6f50e327e --- /dev/null +++ b/tools/vim/test.arr @@ -0,0 +1,105 @@ +# Comments +# TODO FIXME NOTE Comment + +# Names (execute `hi link pyretName Question` to make sure this works) +ab123 +a-b1234 +a-----b +______ +_-_-_ + +# Numbers +1 ++1 +-1 +123.456 +1e10 +1.08e10 + +# Strings +"this is a string" +'this is also a string' +```this is +a multiline +string +``` + +"String with \n escaped char" +"\"String inside string\"" + +# Operators +1 + 2 +1 * 2 +1 / 2 +1 - 2 + +# Construction +[list: 1,2,3,4] +[set: 1,2,3,4] +[foobar: 1,2,3,4] + +# Annotated variables +a :: Number +a :: foo-bar +a :: foo-bar.foo-baz +a :: foo-bar.List +a :: A.Number +a :: List +a :: A.List> +a :: Number%(is-positive) -> String%(is-five) +a :: List%(is-positive) -> List%(is-five) +a :: {Number; Boolean} +a :: {{Number; Boolean}; {String; List}} +a :: Foo -> Bar +a :: List -> List +a :: { Number; Boolean; FooBar } -> { String; Boolean } +a :: (Foo -> Bar) + +# New `type` declaration +type Foo = Number +type Predicate = (a -> Boolean) # This is a comment +1 # This should be correctly highlighted + +# Functions +fun abc(a :: Number, b :: String): +end + +fun fun-name block: +end + +fun foo(x :: a, b :: a): +end + +method meth-name(a :: Number, b :: String) +end + +fun add(x :: Number, y :: Number) -> Number: +end + +fun foo( + x :: Number, # Param 1 + y :: Number # Param 2 +) + +lam(b :: Number, c :: Number) -> Number + +# Data declarations +data BinTree: + | Leaf(a :: Number) + | Branch(l :: BinTree, r :: BinTree) +end + +# cases +cases(A.Expr) exp: + | s-id(_, id) => id.toname() + | s-id-letrec(_, id, _) => id.toname() +end + +# for construct +for(acc from 0, e from [list: 1,2,3,4]): + acc + e +end + +for(acc :: Number from 0, e :: Number from [list: 1,2,3,4]): + acc + e +end