├── ftdetect └── agda.vim ├── agda-utf8.vim ├── LICENSE ├── syntax └── agda.vim ├── README.md ├── ftplugin └── agda.vim ├── autoload └── agda.vim └── agda.py /ftdetect/agda.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.agda,*.lagda setf agda 2 | 3 | -------------------------------------------------------------------------------- /agda-utf8.vim: -------------------------------------------------------------------------------- 1 | let s:cpo_save = &cpo 2 | set cpo&vim 3 | 4 | for [sequence, symbol] in items(g:agda#glyphs) 5 | execute printf('noremap! %s %s', sequence, symbol) 6 | endfor 7 | 8 | " The only mapping that was not prefixed by LocalLeader: 9 | noremap! → 10 | 11 | let &cpo = s:cpo_save -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Derek Elkins 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 15 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 17 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /syntax/agda.vim: -------------------------------------------------------------------------------- 1 | " File: ~/.vim/syntax/agda.vim 2 | 3 | " This is reproduced from 4 | " http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Main.VIMEditing 5 | " for convenience 6 | 7 | if !exists('main_syntax') 8 | if exists('b:current_syntax') 9 | finish 10 | endif 11 | let main_syntax = 'agda' 12 | elseif exists('b:current_syntax') && b:current_syntax == 'agda' 13 | finish 14 | endif 15 | 16 | let s:cpo_save = &cpo 17 | set cpo&vim 18 | 19 | " To tokenize, the best pattern I've found so far is this: 20 | " (^|\s|[.(){};])@<=token($|\s|[.(){};])@= 21 | " The patterns @<= and @= look behind and ahead, respectively, without matching. 22 | 23 | " `agda --vim` extends these groups: 24 | " agdaConstructor 25 | " agdaFunction 26 | " agdaInfixConstructor 27 | " agdaInfixFunction 28 | " 29 | syn iskeyword @,!-~,^\,,^\(,^\),^\",^\',192-255 30 | 31 | syn match agdaKeywords "\v(^|\s|[.(){};])@<=(abstract|data|hiding|import|as|infix|infixl|infixr|module|mutual|open|primitive|private|public|record|renaming|rewrite|using|where|with|field|constructor|instance|syntax|pattern|inductive|coinductive|variable)($|\s|[.(){};])@=" 32 | syn match agdaDubious "\v(^|\s|[.(){};])@<=(postulate|codata)($|\s|[.(){};])@=" 33 | syn match agdaOperator "\v(^|\s|[.(){};])@<=(let|in|forall|λ|→|-\>|:|∀|\=|\||\\)($|\s|[.(){};])@=" 34 | syn match agdaFunction "\v(^|\s|[.(){};])@<=((Set|Prop)[0-9₀-₉ω]*)($|\s|[.(){};])@=" 35 | syn match agdaNumber "\v(^|\s|[.(){};])@<=-?[0-9]+($|\s|[.(){};])@=" 36 | syn match agdaCharCode contained "\\\([0-9]\+\|o[0-7]\+\|x[0-9a-fA-F]\+\|[\"\\'&\\abfnrtv]\|^[A-Z^_\[\\\]]\)" 37 | syn match agdaCharCode contained "\v\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL)" 38 | syn match agdaCharCodeErr contained "\\&\|'''\+" 39 | syn region agdaString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=agdaCharCode 40 | syn match agdaHole "\v(^|\s|[.(){};])@<=(\?)($|\s|[.(){};])@=" 41 | syn region agdaX matchgroup=agdaHole start="{!" end="!}" contains=ALL 42 | syn match agdaLineComment "\v(^|\s|[.(){};])@<=--.*$" contains=@agdaInComment 43 | syn region agdaBlockComment start="{-" end="-}" contains=agdaBlockComment,@agdaInComment 44 | syn region agdaPragma start="{-#" end="#-}" 45 | syn cluster agdaInComment contains=agdaTODO,agdaFIXME,agdaXXX 46 | syn keyword agdaTODO contained TODO 47 | syn keyword agdaFIXME contained FIXME 48 | syn keyword agdaXXX contained XXX 49 | 50 | hi def link agdaNumber Number 51 | hi def link agdaString String 52 | hi def link agdaConstructor Constant 53 | hi def link agdaCharCode SpecialChar 54 | hi def link agdaCharCodeErr Error 55 | hi def link agdaHole WarningMsg 56 | hi def link agdaDubious WarningMsg 57 | hi def link agdaKeywords Structure 58 | hi def link agdaFunction Macro 59 | hi def link agdaOperator Operator 60 | hi def link agdaInfixConstructor Operator 61 | hi def link agdaInfixFunction Operator 62 | hi def link agdaLineComment Comment 63 | hi def link agdaBlockComment Comment 64 | hi def link agdaPragma Comment 65 | hi def agdaTODO cterm=bold,underline ctermfg=2 " green 66 | hi def agdaFIXME cterm=bold,underline ctermfg=3 " yellow 67 | hi def agdaXXX cterm=bold,underline ctermfg=1 " red 68 | 69 | 70 | let b:current_syntax = 'agda' 71 | if main_syntax == 'agda' 72 | unlet main_syntax 73 | endif 74 | let &cpo = s:cpo_save 75 | unlet s:cpo_save 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Version 0.12.0 2 | 3 | A vim mode for interactively editing Agda code with the features of the emacs mode. 4 | 5 | For a demonstration see: 6 | 7 | [![agda-vim Introduction on YouTube](http://img.youtube.com/vi/i7Btts-duZw/0.jpg)](https://www.youtube.com/watch?v=i7Btts-duZw) 8 | 9 | It incorporates the syntax and Unicode input files from 10 | but extends them with support for interacting with the Agda process in the same manner as the emacs mode. In addition, 11 | it sets Agda as the make program to automatically generate and load the local vim highlighting files and to jump 12 | to errors. The make program is currently just `agda --vim`, i.e. it does not compile the program. 13 | 14 | This requires syntax highlighting to be turned on and, for the interactivity, Python plugins to be supported. This 15 | interacts via the same interface emacs uses, though a lot of the logic is in the emacs mode. This is not an officially 16 | supported mode, so there's no guarantee it will work with different versions of Agda. I've currently used it with 17 | Agda 2.3.2.1 through 2.5.3.0. I have not tested Literate Agda files at all and would be a bit surprised if they worked. 18 | 19 | It should work as a Pathogen bundle and allegedly as a Vundle or NeoBundle and possibly others. (I can vouch for Pathogen.) 20 | With Pathogen (and presumably the others) you should be able to simply `git clone` this whole repository into `.vim/bundle/`. 21 | 22 | It should also work by just copying the file structure into your `.vim` folder and adding the following line to 23 | `.vim/filetypes.vim`: 24 | 25 | au BufNewFile,BufRead *.agda setf agda 26 | 27 | You can add paths to the paths Agda searches by setting `g:agda_extraincpaths` as demonstrated by the command below 28 | which could be added to your .vimrc. 29 | 30 | let g:agda_extraincpaths = ["/home/derek/haskell/agda-stdlib-0.8.1/src"] 31 | 32 | Support for go-to definition can be disabled which may speed up loads by putting the following in your `.vimrc`: 33 | 34 | let g:agdavim_enable_goto_definition = 0 35 | 36 | In the commands below, the `` is set by setting `maplocalleader` which needs to occur before the mappings 37 | are made, e.g. in your `.vimrc`: 38 | 39 | let maplocalleader = "," 40 | 41 | The commands and mappings as defined currently are below, as well as their Emacs counterparts: 42 | 43 | command! -buffer -nargs=0 AgdaLoad call AgdaLoad(v:false) 44 | command! -buffer -nargs=0 AgdaVersion call AgdaVersion(v:false) 45 | command! -buffer -nargs=0 AgdaReload silent! make!|redraw! 46 | command! -buffer -nargs=0 AgdaRestartAgda exec s:python_cmd 'AgdaRestart()' 47 | command! -buffer -nargs=0 AgdaShowImplicitArguments exec s:python_cmd "sendCommand('ShowImplicitArgs True')" 48 | command! -buffer -nargs=0 AgdaHideImplicitArguments exec s:python_cmd "sendCommand('ShowImplicitArgs False')" 49 | command! -buffer -nargs=0 AgdaToggleImplicitArguments exec s:python_cmd "sendCommand('ToggleImplicitArgs')" 50 | command! -buffer -nargs=0 AgdaConstraints exec s:python_cmd "sendCommand('Cmd_constraints')" 51 | command! -buffer -nargs=0 AgdaMetas exec s:python_cmd "sendCommand('Cmd_metas')" 52 | command! -buffer -nargs=0 AgdaSolveAll exec s:python_cmd "sendCommand('Cmd_solveAll')" 53 | command! -buffer -nargs=1 AgdaShowModule call AgdaShowModule() 54 | command! -buffer -nargs=1 AgdaWhyInScope call AgdaWhyInScope() 55 | command! -buffer -nargs=1 AgdaSetRewriteMode exec s:python_cmd "setRewriteMode('')" 56 | command! -buffer -nargs=0 AgdaSetRewriteModeAsIs exec s:python_cmd "setRewriteMode('AsIs')" 57 | command! -buffer -nargs=0 AgdaSetRewriteModeNormalised exec s:python_cmd "setRewriteMode('Normalised')" 58 | command! -buffer -nargs=0 AgdaSetRewriteModeSimplified exec s:python_cmd "setRewriteMode('Simplified')" 59 | command! -buffer -nargs=0 AgdaSetRewriteModeHeadNormal exec s:python_cmd "setRewriteMode('HeadNormal')" 60 | command! -buffer -nargs=0 AgdaSetRewriteModeInstantiated exec s:python_cmd "setRewriteMode('Instantiated')" 61 | 62 | " C-c C-l -> \l 63 | nnoremap l :AgdaReload 64 | 65 | " C-c C-d -> \t 66 | nnoremap t :call AgdaInfer() 67 | 68 | " C-c C-r -> \r 69 | nnoremap r :call AgdaRefine("False") 70 | nnoremap R :call AgdaRefine("True") 71 | 72 | " C-c C-space -> \g 73 | nnoremap g :call AgdaGive() 74 | 75 | " C-c C-g -> \c 76 | nnoremap c :call AgdaMakeCase() 77 | 78 | " C-c C-a -> \a 79 | nnoremap a :call AgdaAuto() 80 | 81 | " C-c C-, -> \e 82 | nnoremap e :call AgdaContext() 83 | 84 | " C-u C-c C-n -> \n 85 | nnoremap n :call AgdaNormalize("IgnoreAbstract") 86 | 87 | " C-c C-n -> \N 88 | nnoremap N :call AgdaNormalize("DefaultCompute") 89 | nnoremap M :call AgdaShowModule('') 90 | 91 | " C-c C-w -> \y 92 | nnoremap y :call AgdaWhyInScope('') 93 | nnoremap h :call AgdaHelperFunction() 94 | 95 | " M-. -> \d 96 | nnoremap d :call AgdaGotoAnnotation() 97 | 98 | " C-c C-? -> \m 99 | nnoremap m :AgdaMetas 100 | 101 | " Show/reload metas 102 | " C-c C-? -> C-e 103 | nnoremap :AgdaMetas 104 | inoremap :AgdaMetas 105 | 106 | " Go to next/previous meta 107 | " C-c C-f -> C-g 108 | nnoremap :let _s=@// {!\\| ?:let @/=_s2l 109 | inoremap :let _s=@// {!\\| ?:let @/=_s2l 110 | 111 | " C-c C-b -> C-y 112 | nnoremap 2h:let _s=@/? {!\\| \?:let @/=_s2l 113 | inoremap 2h:let _s=@/? {!\\| \?:let @/=_s2l 114 | 115 | Some commonly used utf8 bindings are listed below, together with their emacs counterparts. For an exhaustive list, 116 | look in `autoload/agda.vim`. 117 | 118 | | utf-8 | agda-vim | emacs | 119 | |:-----:| -------------- | ----------------- | 120 | | → | \to | \to | 121 | | ¬ | \neg | \lnot | 122 | | ∨ | \lor | \or or vee | 123 | | ∧ | \land | \and or \wedge | 124 | | ₁, ₂ | \1, \2 | \\\_1, \\\_2 | 125 | | ≡ | \equiv | \equiv or \\== | 126 | | ⊤ | \top | \top | 127 | | ⊥ | \bot | \bot | 128 | | × | \times | \times | 129 | | ⊎ | \dunion | \uplus | 130 | | λ | \l or lambda | \Gl or \lambda | 131 | -------------------------------------------------------------------------------- /ftplugin/agda.vim: -------------------------------------------------------------------------------- 1 | " Only do this when not done yet for this buffer 2 | if exists('b:did_ftplugin') 3 | finish 4 | endif 5 | let b:did_ftplugin = 1 6 | let b:undo_ftplugin = '' 7 | 8 | let s:cpo_save = &cpo 9 | set cpo&vim 10 | 11 | " The AgdaReloadSyntax function is reproduced from 12 | " http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Main.VIMEditing 13 | " the remainder is covered by the license described in LICENSE. 14 | function! AgdaReloadSyntax() 15 | syntax clear 16 | let f = expand('%:h') . "/." . expand('%:t') . ".vim" 17 | if filereadable(f) 18 | exec "source " . escape(f, '*') 19 | endif 20 | runtime syntax/agda.vim 21 | endfunction 22 | call AgdaReloadSyntax() 23 | 24 | function! AgdaLoad(quiet) 25 | " Do nothing. Overidden below with a Python function if python is supported. 26 | endfunction 27 | 28 | autocmd QuickfixCmdPost make call AgdaReloadSyntax()|call AgdaVersion(v:true)|call AgdaLoad(v:true) 29 | 30 | setlocal autowrite 31 | let b:undo_ftplugin .= ' | setlocal autowrite<' 32 | 33 | let g:agdavim_agda_includepathlist = deepcopy(['.'] + get(g:, 'agda_extraincpaths', [])) 34 | call map(g:agdavim_agda_includepathlist, ' ''"'' . v:val . ''"'' ') 35 | let &l:makeprg = 'agda --vim ' . '-i ' . join(g:agdavim_agda_includepathlist, ' -i ') . ' %' 36 | let b:undo_ftplugin .= ' | setlocal makeprg<' 37 | 38 | if get(g:, 'agdavim_includeutf8_mappings', v:true) 39 | runtime agda-utf8.vim 40 | endif 41 | 42 | let g:agdavim_enable_goto_definition = get(g:, 'agdavim_enable_goto_definition', v:true) ? v:true : v:false 43 | 44 | setlocal errorformat=\ \ /%\\&%f:%l\\,%c-%.%#,%E/%\\&%f:%l\\,%c-%.%#,%Z,%C%m,%-G%.%# 45 | let b:undo_ftplugin .= ' | setlocal errorformat<' 46 | 47 | setlocal nolisp 48 | let b:undo_ftplugin .= ' | setlocal nolisp<' 49 | 50 | setlocal formatoptions-=t 51 | setlocal formatoptions+=croql 52 | let b:undo_ftplugin .= ' | setlocal formatoptions<' 53 | 54 | setlocal autoindent 55 | let b:undo_ftplugin .= ' | setlocal autoindent<' 56 | 57 | " {- 58 | " -- Foo 59 | " -- bar 60 | " -} 61 | setlocal comments=sfl:{-,mb1:--,ex:-},:-- 62 | let b:undo_ftplugin .= ' | setlocal comments<' 63 | 64 | setlocal commentstring=--\ %s 65 | let b:undo_ftplugin .= ' | setlocal commentstring<' 66 | 67 | setlocal iskeyword=@,!-~,^\,,^\(,^\),^\",^\',192-255 68 | let b:undo_ftplugin .= ' | setlocal iskeyword<' 69 | 70 | setlocal matchpairs&vim 71 | setlocal matchpairs+=(:) 72 | setlocal matchpairs+=<:> 73 | setlocal matchpairs+=[:] 74 | setlocal matchpairs+={:} 75 | setlocal matchpairs+=«:» 76 | setlocal matchpairs+=‹:› 77 | setlocal matchpairs+=⁅:⁆ 78 | setlocal matchpairs+=⁽:⁾ 79 | setlocal matchpairs+=₍:₎ 80 | setlocal matchpairs+=⌈:⌉ 81 | setlocal matchpairs+=⌊:⌋ 82 | setlocal matchpairs+=〈:〉 83 | setlocal matchpairs+=⎛:⎞ 84 | setlocal matchpairs+=⎝:⎠ 85 | setlocal matchpairs+=⎡:⎤ 86 | setlocal matchpairs+=⎣:⎦ 87 | setlocal matchpairs+=⎧:⎫ 88 | setlocal matchpairs+=⎨:⎬ 89 | setlocal matchpairs+=⎩:⎭ 90 | setlocal matchpairs+=⎴:⎵ 91 | setlocal matchpairs+=❨:❩ 92 | setlocal matchpairs+=❪:❫ 93 | setlocal matchpairs+=❬:❭ 94 | setlocal matchpairs+=❮:❯ 95 | setlocal matchpairs+=❰:❱ 96 | setlocal matchpairs+=❲:❳ 97 | setlocal matchpairs+=❴:❵ 98 | setlocal matchpairs+=⟅:⟆ 99 | setlocal matchpairs+=⟦:⟧ 100 | setlocal matchpairs+=⟨:⟩ 101 | setlocal matchpairs+=⟪:⟫ 102 | setlocal matchpairs+=⦃:⦄ 103 | setlocal matchpairs+=⦅:⦆ 104 | setlocal matchpairs+=⦇:⦈ 105 | setlocal matchpairs+=⦉:⦊ 106 | setlocal matchpairs+=⦋:⦌ 107 | setlocal matchpairs+=⦍:⦎ 108 | setlocal matchpairs+=⦏:⦐ 109 | setlocal matchpairs+=⦑:⦒ 110 | setlocal matchpairs+=⦓:⦔ 111 | setlocal matchpairs+=⦕:⦖ 112 | setlocal matchpairs+=⦗:⦘ 113 | setlocal matchpairs+=⸠:⸡ 114 | setlocal matchpairs+=⸢:⸣ 115 | setlocal matchpairs+=⸤:⸥ 116 | setlocal matchpairs+=⸦:⸧ 117 | setlocal matchpairs+=⸨:⸩ 118 | setlocal matchpairs+=〈:〉 119 | setlocal matchpairs+=《:》 120 | setlocal matchpairs+=「:」 121 | setlocal matchpairs+=『:』 122 | setlocal matchpairs+=【:】 123 | setlocal matchpairs+=〔:〕 124 | setlocal matchpairs+=〖:〗 125 | setlocal matchpairs+=〘:〙 126 | setlocal matchpairs+=〚:〛 127 | setlocal matchpairs+=︗:︘ 128 | setlocal matchpairs+=︵:︶ 129 | setlocal matchpairs+=︷:︸ 130 | setlocal matchpairs+=︹:︺ 131 | setlocal matchpairs+=︻:︼ 132 | setlocal matchpairs+=︽:︾ 133 | setlocal matchpairs+=︿:﹀ 134 | setlocal matchpairs+=﹁:﹂ 135 | setlocal matchpairs+=﹃:﹄ 136 | setlocal matchpairs+=﹇:﹈ 137 | setlocal matchpairs+=﹙:﹚ 138 | setlocal matchpairs+=﹛:﹜ 139 | setlocal matchpairs+=﹝:﹞ 140 | setlocal matchpairs+=(:) 141 | setlocal matchpairs+=<:> 142 | setlocal matchpairs+=[:] 143 | setlocal matchpairs+={:} 144 | setlocal matchpairs+=⦅:⦆ 145 | setlocal matchpairs+=「:」 146 | let b:undo_ftplugin .= ' | setlocal matchpairs<' 147 | 148 | " Python 3 is NOT supported. This code and other changes are left here to 149 | " ease adding future Python 3 support. Right now the main issue is that 150 | " Python 3 treats strings are sequences of characters rather than sequences of 151 | " bytes which interacts poorly with the fact that the column offsets vim 152 | " returns are byte offsets in the current line. The code below should run 153 | " under Python 3, but it won't match up the holes correctly if you have 154 | " Unicode characters. 155 | function! s:UsingPython2() 156 | return 1 157 | "if has('python') 158 | " return 1 159 | "endif 160 | "return 0 161 | endfunction 162 | 163 | let s:using_python2 = s:UsingPython2() 164 | let s:python_cmd = s:using_python2 ? 'py ' : 'py3 ' 165 | let s:python_loadfile = s:using_python2 ? 'pyfile ' : 'py3file ' 166 | 167 | if has('python') " || has('python3') 168 | 169 | function! s:LogAgda(name, text, append) 170 | let agdawinnr = bufwinnr('__Agda__') 171 | let prevwinnr = winnr() 172 | if agdawinnr == -1 173 | let eventignore_save = &eventignore 174 | set eventignore=all 175 | 176 | silent keepalt botright 8split __Agda__ 177 | 178 | let &eventignore = eventignore_save 179 | setlocal noreadonly 180 | setlocal buftype=nofile 181 | setlocal bufhidden=hide 182 | setlocal noswapfile 183 | setlocal nobuflisted 184 | setlocal nolist 185 | setlocal nonumber 186 | setlocal nowrap 187 | setlocal textwidth=0 188 | setlocal nocursorline 189 | setlocal nocursorcolumn 190 | 191 | if exists('+relativenumber') 192 | setlocal norelativenumber 193 | endif 194 | else 195 | let eventignore_save = &eventignore 196 | set eventignore=BufEnter 197 | 198 | execute agdawinnr . 'wincmd w' 199 | let &eventignore = eventignore_save 200 | endif 201 | 202 | let lazyredraw_save = &lazyredraw 203 | set lazyredraw 204 | let eventignore_save = &eventignore 205 | set eventignore=all 206 | 207 | let &l:statusline = a:name 208 | if a:append == 'True' 209 | silent put =a:text 210 | else 211 | silent %delete _ 212 | silent 0put =a:text 213 | endif 214 | 215 | 0 216 | 217 | let &lazyredraw = lazyredraw_save 218 | let &eventignore = eventignore_save 219 | 220 | let eventignore_save = &eventignore 221 | set eventignore=BufEnter 222 | 223 | execute prevwinnr . 'wincmd w' 224 | let &eventignore = eventignore_save 225 | endfunction 226 | 227 | execute s:python_loadfile . resolve(expand(':p:h') . '/../agda.py') 228 | 229 | command! -buffer -nargs=0 AgdaLoad call AgdaLoad(v:false) 230 | command! -buffer -nargs=0 AgdaVersion call AgdaVersion(v:false) 231 | command! -buffer -nargs=0 AgdaReload silent! make!|redraw! 232 | command! -buffer -nargs=0 AgdaRestartAgda exec s:python_cmd 'AgdaRestart()' 233 | command! -buffer -nargs=0 AgdaShowImplicitArguments exec s:python_cmd "sendCommand('ShowImplicitArgs True')" 234 | command! -buffer -nargs=0 AgdaHideImplicitArguments exec s:python_cmd "sendCommand('ShowImplicitArgs False')" 235 | command! -buffer -nargs=0 AgdaToggleImplicitArguments exec s:python_cmd "sendCommand('ToggleImplicitArgs')" 236 | command! -buffer -nargs=0 AgdaConstraints exec s:python_cmd "sendCommand('Cmd_constraints')" 237 | command! -buffer -nargs=0 AgdaMetas exec s:python_cmd "sendCommand('Cmd_metas')" 238 | command! -buffer -nargs=0 AgdaSolveAll exec s:python_cmd "sendCommand('Cmd_solveAll')" 239 | command! -buffer -nargs=1 AgdaShowModule call AgdaShowModule() 240 | command! -buffer -nargs=1 AgdaWhyInScope call AgdaWhyInScope() 241 | command! -buffer -nargs=1 AgdaSetRewriteMode exec s:python_cmd "setRewriteMode('')" 242 | command! -buffer -nargs=0 AgdaSetRewriteModeAsIs exec s:python_cmd "setRewriteMode('AsIs')" 243 | command! -buffer -nargs=0 AgdaSetRewriteModeNormalised exec s:python_cmd "setRewriteMode('Normalised')" 244 | command! -buffer -nargs=0 AgdaSetRewriteModeSimplified exec s:python_cmd "setRewriteMode('Simplified')" 245 | command! -buffer -nargs=0 AgdaSetRewriteModeHeadNormal exec s:python_cmd "setRewriteMode('HeadNormal')" 246 | command! -buffer -nargs=0 AgdaSetRewriteModeInstantiated exec s:python_cmd "setRewriteMode('Instantiated')" 247 | 248 | nnoremap l :AgdaReload 249 | nnoremap t :call AgdaInfer() 250 | nnoremap r :call AgdaRefine("False") 251 | nnoremap R :call AgdaRefine("True") 252 | nnoremap g :call AgdaGive() 253 | nnoremap c :call AgdaMakeCase() 254 | nnoremap a :call AgdaAuto() 255 | nnoremap e :call AgdaContext() 256 | nnoremap n :call AgdaNormalize("IgnoreAbstract") 257 | nnoremap N :call AgdaNormalize("DefaultCompute") 258 | nnoremap M :call AgdaShowModule('') 259 | nnoremap y :call AgdaWhyInScope('') 260 | nnoremap h :call AgdaHelperFunction() 261 | nnoremap d :call AgdaGotoAnnotation() 262 | nnoremap m :AgdaMetas 263 | 264 | " Show/reload metas 265 | nnoremap :AgdaMetas 266 | inoremap :AgdaMetas 267 | 268 | " Go to next/previous meta 269 | nnoremap :let _s=@// {!\\| ?:let @/=_s2l 270 | inoremap :let _s=@// {!\\| ?:let @/=_s2l 271 | 272 | nnoremap 2h:let _s=@/? {!\\| \?:let @/=_s2l 273 | inoremap 2h:let _s=@/? {!\\| \?:let @/=_s2l 274 | 275 | AgdaReload 276 | 277 | endif 278 | 279 | let &cpo = s:cpo_save 280 | -------------------------------------------------------------------------------- /autoload/agda.vim: -------------------------------------------------------------------------------- 1 | " Agda Input Abbreviations 2 | " 3 | let s:cpo_save = &cpo 4 | set cpo&vim 5 | 6 | " Public to allow referencing in custom overrides. 7 | if !exists('g:agda#default_glyphs') 8 | let g:agda#default_glyphs = {} 9 | 10 | " Combining marks 11 | call extend(g:agda#default_glyphs, { 12 | \ 'over`': ' ̀', 13 | \ "over'": ' ́', 14 | \ 'over^': ' ̂', 15 | \ 'overv': ' ̌', 16 | \ 'over~': ' ̃', 17 | \ 'over-': ' ̄', 18 | \ 'over_': ' ̅', 19 | \ 'over–': ' ̅', 20 | \ 'over—': ' ̅', 21 | \ 'overcup': ' ̆', 22 | \ 'overcap': ' ̑', 23 | \ 'over.': ' ̇', 24 | \ 'over..': ' ̈', 25 | \ 'over"': ' ̈', 26 | \ 'over...': ' ⃛', 27 | \ 'overright.': ' ͘', 28 | \ 'overo': ' ̊', 29 | \ 'over``': ' ̏', 30 | \ "over''": ' ̋', 31 | \ 'overvec': ' ⃑', 32 | \ 'vec': ' ⃑', 33 | \ 'overlvec': ' ⃐', 34 | \ 'lvec': ' ⃐', 35 | \ 'overarc': ' ⃕', 36 | \ 'overlarc': ' ⃔', 37 | \ 'overto': ' ⃗', 38 | \ 'overfrom': ' ⃖', 39 | \ 'overfromto': ' ⃡', 40 | \ 'over*': ' ⃰', 41 | \ 'under`': ' ̖', 42 | \ "under'": ' ̗', 43 | \ 'under,': ' ̗', 44 | \ 'under.': ' ̣', 45 | \ 'under..': ' ̤', 46 | \ 'under"': ' ̤', 47 | \ 'undero': ' ̥', 48 | \ 'under-': ' ̱', 49 | \ 'under_': ' ̲', 50 | \ 'under–': ' ̲', 51 | \ 'under—': ' ̲', 52 | \ 'through~': ' ̴', 53 | \ 'through-': ' ̵', 54 | \ 'through_': ' ̶', 55 | \ 'through–': ' ̶', 56 | \ 'through—': ' ̶', 57 | \ 'through/': ' ̷', 58 | \ 'not': ' ̷', 59 | \ 'through?': ' ̸', 60 | \ 'Not': ' ̸', 61 | \ 'through\|': ' ⃒', 62 | \ 'throughshortmid': ' ⃓', 63 | \ 'througho': ' ⃘', 64 | \}) 65 | 66 | " Math 67 | call extend(g:agda#default_glyphs, { 68 | \ '{{': '⦃', 69 | \ '}}': '⦄', 70 | \ ':': '∶', 71 | \ '::': '∷', 72 | \ ';': '﹔', 73 | \ '..': '‥', 74 | \ '=?': '≟', 75 | \ 'all': '∀', 76 | \ 'always': '□', 77 | \ 'approx': '≈', 78 | \ 'bot': '⊥', 79 | \ 'box': '□', 80 | \ 'boxdot': '⊡', 81 | \ 'box.': '⊡', 82 | \ 'boxminus': '⊟', 83 | \ 'box-': '⊟', 84 | \ 'boxplus': '⊞', 85 | \ 'box+': '⊞', 86 | \ 'boxtimes': '⊠', 87 | \ 'box*': '⊠', 88 | \ 'bul': '•', 89 | \ 'C': 'ℂ', 90 | \ 'cdot': '∙', 91 | \ '.': '∙', 92 | \ 'cdots': '⋯', 93 | \ 'check': '✓', 94 | \ 'yes': '✓', 95 | \ 'Check': '✔', 96 | \ 'Yes': '✔', 97 | \ 'circ': '∘', 98 | \ 'clock': '↻', 99 | \ 'cclock': '↺', 100 | \ 'comp': '∘', 101 | \ 'contra': '↯', 102 | \ 'deg': '°', 103 | \ 'den': '⟦⟧', 104 | \ 'diamond': '◇', 105 | \ 'dots': '…', 106 | \ 'down': '↓', 107 | \ 'downtri': '▼', 108 | \ 'Down': '⇓', 109 | \ 'dunion': '⊎', 110 | \ 'du': '⊎', 111 | \ 'ell': 'ℓ', 112 | \ 'empty': '∅', 113 | \ 'equiv': '≡', 114 | \ 'eq': '≡', 115 | \ 'eventually': '◇', 116 | \ 'exists': '∃', 117 | \ 'flat': '♭', 118 | \ 'fold': '⦇⦈', 119 | \ '(\|': '⦇', 120 | \ '\|)': '⦈', 121 | \ 'forall': '∀', 122 | \ 'from': '←', 123 | \ '<-': '←', 124 | \ 'From': '⇐', 125 | \ 'fromto': '↔', 126 | \ 'Fromto': '⇔', 127 | \ 'ge': '≥', 128 | \ 'glub': '⊓', 129 | \ 'iff': '⇔', 130 | \ 'implies': '⇒', 131 | \ 'impliedby': '⇐', 132 | \ 'in': '∈', 133 | \ 'infty': '∞', 134 | \ 'inf': '∞', 135 | \ 'int': '∫', 136 | \ 'intersect': '∩', 137 | \ 'iso': '≅', 138 | \ 'join': '⋈', 139 | \ 'land': '∧', 140 | \ 'langle': '⟨', 141 | \ 'lbrac': '⟦', 142 | \ '[[': '⟦', 143 | \ 'ldots': '…', 144 | \ 'ldown': '⇃', 145 | \ 'leadsto': '⇝', 146 | \ '~>': '⇝', 147 | \ 'le': '≤', 148 | \ 'lift': '⌊⌋', 149 | \ 'floor': '⌊⌋', 150 | \ 'llangle': '⟪', 151 | \ 'longto': '⟶ ', 152 | \ '--': '⟶ ', 153 | \ '–': '⟶ ', 154 | \ 'lor': '∨', 155 | \ 'lower': '⌈⌉', 156 | \ 'ceil': '⌈⌉', 157 | \ 'lub': '⊔', 158 | \ 'lup': '↿', 159 | \ 'mapsto': '↦', 160 | \ 'map': '↦', 161 | \ 'mid': '∣', 162 | \ 'models': '⊨', 163 | \ '\|=': '⊨', 164 | \ 'N': 'ℕ', 165 | \ 'ne': '≠', 166 | \ 'nearrow': '↗', 167 | \ 'Nearrow': '⇗', 168 | \ 'neg': '¬', 169 | \ '/=': '≠', 170 | \ 'nequiv': '≢', 171 | \ 'neq': '≢', 172 | \ 'nexist': '∄', 173 | \ 'none': '∄', 174 | \ 'ni': '∋', 175 | \ 'nin': '∉', 176 | \ 'niso': '≇', 177 | \ 'notin': '∉', 178 | \ 'nwarrow': '↖', 179 | \ 'Nwarrow': '⇖', 180 | \ 'oast': '⊛', 181 | \ 'odot': '⊙', 182 | \ 'o.': '⊙', 183 | \ 'of': '∘', 184 | \ 'o': '∘', 185 | \ 'ominus': '⊖', 186 | \ 'o-': '⊖', 187 | \ 'oplus': '⊕', 188 | \ 'o+': '⊕', 189 | \ 'oslash': '⊘', 190 | \ 'o/': '⊘', 191 | \ 'otimes': '⊗', 192 | \ 'o*': '⊗', 193 | \ 'par': '∂', 194 | \ 'pge': '≽', 195 | \ 'pgt': '≻', 196 | \ 'ple': '≼', 197 | \ 'plt': '≺', 198 | \ 'p≥': '≽', 199 | \ 'p>': '≻', 200 | \ 'p≤': '≼', 201 | \ 'p<': '≺', 202 | \ 'pm': '±', 203 | \ 'prec': '≼', 204 | \ 'prod': '∏', 205 | \ 'proves': '⊢', 206 | \ '\|-': '⊢', 207 | \ 'provedby': '⊣', 208 | \ 'Q': 'ℚ', 209 | \ 'qed': '∎', 210 | \ 'R': 'ℝ', 211 | \ 'rangle': '⟩', 212 | \ 'rbrac': '⟧', 213 | \ ']]': '⟧', 214 | \ 'rdown': '⇂', 215 | \ 'righttri': '▸', 216 | \ 'rrangle': '⟫', 217 | \ 'rup': '↾', 218 | \ 'searrow': '↘', 219 | \ 'Searrow': '⇘', 220 | \ 'setminus': '∖', 221 | \ 'sharp': '♯', 222 | \ '#': '♯', 223 | \ 'sim': '∼', 224 | \ 'simeq': '≃', 225 | \ 'some': '∃', 226 | \ 'sqge': '⊒', 227 | \ 'sqgt': '⊐', 228 | \ 'sqle': '⊑', 229 | \ 'sqlt': '⊏', 230 | \ 's≥': '⊒', 231 | \ 's>': '⊐', 232 | \ 's≤': '⊑', 233 | \ 's<': '⊏', 234 | \ 'sqr': '²', 235 | \ 'sqrt': '√', 236 | \ 'star': '✭', 237 | \ 'subset': '⊂', 238 | \ 'sub': '⊂', 239 | \ 'subseteq': '⊆', 240 | \ 'subeq': '⊆', 241 | \ 'subsetneq': '⊊', 242 | \ 'subneq': '⊊', 243 | \ 'sum': '∑', 244 | \ 'supset': '⊃', 245 | \ 'sup': '⊃', 246 | \ 'supseteq': '⊇', 247 | \ 'supeq': '⊇', 248 | \ 'supsetneq': '⊋', 249 | \ 'supneq': '⊋', 250 | \ 'swarrow': '↙', 251 | \ 'Swarrow': '⇙', 252 | \ 'thus': '∴', 253 | \ 'times': '×', 254 | \ '*': '×', 255 | \ 'to': '→', 256 | \ '-': '→', 257 | \ 'To': '⇒', 258 | \ '=': '⇒', 259 | \ 'top': '⊤', 260 | \ 'tuple': '⟨⟩', 261 | \ 'up': '↑', 262 | \ 'updown': '↕', 263 | \ 'ud': '↕', 264 | \ 'unfold': '⦉⦊', 265 | \ '<\|': '⦉', 266 | \ '\|>': '⦊', 267 | \ 'up;down': '⇅', 268 | \ 'u;d': '⇅', 269 | \ 'uptri': '▲', 270 | \ 'Up': '⇑', 271 | \ 'union': '∪', 272 | \ 'vdots': '⋮', 273 | \ 'voltage': '⚡', 274 | \ 'xmark': '✗', 275 | \ 'no': '✗', 276 | \ 'Xmark': '✘', 277 | \ 'No': '✘', 278 | \ 'Z': 'ℤ', 279 | \}) 280 | 281 | " Not math 282 | call extend(g:agda#default_glyphs, { 283 | \ 'sec': '§', 284 | \}) 285 | 286 | " Superscripts 287 | call extend(g:agda#default_glyphs, { 288 | \ '^0': '⁰', 289 | \ '^1': '¹', 290 | \ '^2': '²', 291 | \ '^3': '³', 292 | \ '^4': '⁴', 293 | \ '^5': '⁵', 294 | \ '^6': '⁶', 295 | \ '^7': '⁷', 296 | \ '^8': '⁸', 297 | \ '^9': '⁹', 298 | \ '^A': 'ᴬ', 299 | \ '^B': 'ᴮ', 300 | \ '^D': 'ᴰ', 301 | \ '^E': 'ᴱ', 302 | \ '^G': 'ᴳ', 303 | \ '^H': 'ᴴ', 304 | \ '^I': 'ᴵ', 305 | \ '^J': 'ᴶ', 306 | \ '^K': 'ᴷ', 307 | \ '^L': 'ᴸ', 308 | \ '^M': 'ᴹ', 309 | \ '^N': 'ᴺ', 310 | \ '^O': 'ᴼ', 311 | \ '^P': 'ᴾ', 312 | \ '^R': 'ᴿ', 313 | \ '^T': 'ᵀ', 314 | \ '^U': 'ᵁ', 315 | \ '^V': 'ⱽ', 316 | \ '^W': 'ᵂ', 317 | \ '^a': 'ᵃ', 318 | \ '^b': 'ᵇ', 319 | \ '^c': 'ᶜ', 320 | \ '^d': 'ᵈ', 321 | \ '^e': 'ᵉ', 322 | \ '^f': 'ᶠ', 323 | \ '^g': 'ᵍ', 324 | \ '^h': 'ʰ', 325 | \ '^i': 'ⁱ', 326 | \ '^j': 'ʲ', 327 | \ '^k': 'ᵏ', 328 | \ '^l': 'ˡ', 329 | \ '^m': 'ᵐ', 330 | \ '^n': 'ⁿ', 331 | \ '^o': 'ᵒ', 332 | \ '^p': 'ᵖ', 333 | \ '^r': 'ʳ', 334 | \ '^s': 'ˢ', 335 | \ '^t': 'ᵗ', 336 | \ '^u': 'ᵘ', 337 | \ '^v': 'ᵛ', 338 | \ '^w': 'ʷ', 339 | \ '^x': 'ˣ', 340 | \ '^y': 'ʸ', 341 | \ '^z': 'ᶻ', 342 | \ '^+': '⁺', 343 | \ '^-': '⁻', 344 | \ '^=': '⁼', 345 | \ '^(': '⁽', 346 | \ '^)': '⁾', 347 | \ "'": '′', 348 | \ "''": '″', 349 | \ "'''": '‴', 350 | \ "''''": '⁗', 351 | \ '"': '″', 352 | \ '""': '⁗', 353 | \ '`': '‵', 354 | \ '``': '‶', 355 | \ '```': '‷', 356 | \}) 357 | 358 | " Subscripts 359 | call extend(g:agda#default_glyphs, { 360 | \ '0': '₀', 361 | \ '1': '₁', 362 | \ '2': '₂', 363 | \ '3': '₃', 364 | \ '4': '₄', 365 | \ '5': '₅', 366 | \ '6': '₆', 367 | \ '7': '₇', 368 | \ '8': '₈', 369 | \ '9': '₉', 370 | \ '_a': 'ₐ', 371 | \ '_e': 'ₑ', 372 | \ '_h': 'ₕ', 373 | \ '_i': 'ᵢ', 374 | \ '_j': 'ⱼ', 375 | \ '_k': 'ₖ', 376 | \ '_l': 'ₗ', 377 | \ '_m': 'ₘ', 378 | \ '_n': 'ₙ', 379 | \ '_o': 'ₒ', 380 | \ '_p': 'ₚ', 381 | \ '_r': 'ᵣ', 382 | \ '_s': 'ₛ', 383 | \ '_t': 'ₜ', 384 | \ '_u': 'ᵤ', 385 | \ '_v': 'ᵥ', 386 | \ '_x': 'ₓ', 387 | \ '_+': '₊', 388 | \ '_-': '₋', 389 | \ '_=': '₌', 390 | \ '_(': '₍', 391 | \ '_)': '₎', 392 | \ 'p0': 'π₀', 393 | \ 'p1': 'π₁', 394 | \ 'p2': 'π₂', 395 | \ 'p3': 'π₃', 396 | \ 'p4': 'π₄', 397 | \ 'p5': 'π₅', 398 | \ 'p6': 'π₆', 399 | \ 'p7': 'π₇', 400 | \ 'p8': 'π₈', 401 | \ 'p9': 'π₉', 402 | \ 'i0': 'ι₀', 403 | \ 'i1': 'ι₁', 404 | \ 'i2': 'ι₂', 405 | \ 'i3': 'ι₃', 406 | \ 'i4': 'ι₄', 407 | \ 'i5': 'ι₅', 408 | \ 'i6': 'ι₆', 409 | \ 'i7': 'ι₇', 410 | \ 'i8': 'ι₈', 411 | \ 'i9': 'ι₉', 412 | \}) 413 | 414 | " Greek (lower) 415 | call extend(g:agda#default_glyphs, { 416 | \ 'alpha': 'α', 417 | \ 'a': 'α', 418 | \ 'beta': 'β', 419 | \ 'b': 'β', 420 | \ 'gamma': 'γ', 421 | \ 'g': 'γ', 422 | \ 'delta': 'δ', 423 | \ 'd': 'δ', 424 | \ 'epsilon': 'ε', 425 | \ 'e': 'ε', 426 | \ 'zeta': 'ζ', 427 | \ 'z': 'ζ', 428 | \ 'eta': 'η', 429 | \ 'h': 'η', 430 | \ 'theta': 'θ', 431 | \ 'iota': 'ι', 432 | \ 'i': 'ι', 433 | \ 'kappa': 'κ', 434 | \ 'k': 'κ', 435 | \ 'lambda': 'λ', 436 | \ 'l': 'λ', 437 | \ 'mu': 'μ', 438 | \ 'm': 'μ', 439 | \ 'nu': 'ν', 440 | \ 'n': 'ν', 441 | \ 'xi': 'ξ', 442 | \ 'omicron': 'ο', 443 | \ 'pi': 'π', 444 | \ 'p': 'π', 445 | \ 'rho': 'ρ', 446 | \ 'r': 'ρ', 447 | \ 'sigma': 'σ', 448 | \ 's': 'σ', 449 | \ 'varsigma': 'ς', 450 | \ 'vars': 'ς', 451 | \ 'tau': 'τ', 452 | \ 't': 'τ', 453 | \ 'u': 'υ', 454 | \ 'phi': 'φ', 455 | \ 'f': 'φ', 456 | \ 'chi': 'χ', 457 | \ 'x': 'χ', 458 | \ 'psi': 'ψ', 459 | \ 'c': 'ψ', 460 | \ 'omega': 'ω', 461 | \ 'v': 'ω', 462 | \}) 463 | 464 | " Greek (upper) 465 | call extend(g:agda#default_glyphs, { 466 | \ 'Alpha': 'Α', 467 | \ 'Beta': 'Β', 468 | \ 'Gamma': 'Γ', 469 | \ 'G': 'Γ', 470 | \ 'Delta': 'Δ', 471 | \ 'D': 'Δ', 472 | \ 'Epsilon': 'Ε', 473 | \ 'Zeta': 'Ζ', 474 | \ 'Eta': 'Η', 475 | \ 'Theta': 'Θ', 476 | \ 'Iota': 'Ι', 477 | \ 'Kappa': 'Κ', 478 | \ 'Lambda': 'Λ', 479 | \ 'L': 'Λ', 480 | \ 'Mu': 'Μ', 481 | \ 'Nu': 'Ν', 482 | \ 'Xi': 'Ξ', 483 | \ 'Omicron': 'Ο', 484 | \ 'Pi': 'Π', 485 | \ 'P': 'Π', 486 | \ 'Rho': 'Ρ', 487 | \ 'Sigma': 'Σ', 488 | \ 'S': 'Σ', 489 | \ 'Tau': 'Τ', 490 | \ 'Upsilon': 'Υ', 491 | \ 'Phi': 'Φ', 492 | \ 'F': 'Φ', 493 | \ 'Chi': 'Χ', 494 | \ 'Psi': 'Ψ', 495 | \ 'Omega': 'Ω', 496 | \ 'V': 'Ω', 497 | \}) 498 | 499 | " Blackboard 500 | call extend(g:agda#default_glyphs, { 501 | \ 'bA': '𝔸', 502 | \ 'bB': '𝔹', 503 | \ 'bC': 'ℂ', 504 | \ 'bD': '𝔻', 505 | \ 'bE': '𝔼', 506 | \ 'bF': '𝔽', 507 | \ 'bG': '𝔾', 508 | \ 'bH': 'ℍ', 509 | \ 'bI': '𝕀', 510 | \ 'bJ': '𝕁', 511 | \ 'bK': '𝕂', 512 | \ 'bL': '𝕃', 513 | \ 'bM': '𝕄', 514 | \ 'bN': 'ℕ', 515 | \ 'bO': '𝕆', 516 | \ 'bP': 'ℙ', 517 | \ 'bQ': 'ℚ', 518 | \ 'bR': 'ℝ', 519 | \ 'bS': '𝕊', 520 | \ 'bT': '𝕋', 521 | \ 'bU': '𝕌', 522 | \ 'bV': '𝕍', 523 | \ 'bW': '𝕎', 524 | \ 'bX': '𝕏', 525 | \ 'bY': '𝕐', 526 | \ 'bZ': 'ℤ', 527 | \ 'b0': '𝟘', 528 | \ 'b1': '𝟙', 529 | \ 'b2': '𝟚', 530 | \ 'b3': '𝟛', 531 | \ 'b4': '𝟜', 532 | \ 'b5': '𝟝', 533 | \ 'b6': '𝟞', 534 | \ 'b7': '𝟟', 535 | \ 'b8': '𝟠', 536 | \ 'b9': '𝟡', 537 | \ 'bsum': '⅀', 538 | \}) 539 | 540 | " Math chars 541 | call extend(g:agda#default_glyphs, { 542 | \ 'McA': '𝓐', 543 | \ 'McB': '𝓑', 544 | \ 'McC': '𝓒', 545 | \ 'McD': '𝓓', 546 | \ 'McE': '𝓔', 547 | \ 'McF': '𝓕', 548 | \ 'McG': '𝓖', 549 | \ 'McH': '𝓗', 550 | \ 'McI': '𝓘', 551 | \ 'McJ': '𝓙', 552 | \ 'McK': '𝓚', 553 | \ 'McL': '𝓛', 554 | \ 'McM': '𝓜', 555 | \ 'McN': '𝓝', 556 | \ 'McO': '𝓞', 557 | \ 'McP': '𝓟', 558 | \ 'McQ': '𝓠', 559 | \ 'McR': '𝓡', 560 | \ 'McS': '𝓢', 561 | \ 'McT': '𝓣', 562 | \ 'McU': '𝓤', 563 | \ 'McV': '𝓥', 564 | \ 'McW': '𝓦', 565 | \ 'McX': '𝓧', 566 | \ 'McY': '𝓨', 567 | \ 'McZ': '𝓩', 568 | \ 'Mca': '𝒶', 569 | \ 'Mcb': '𝒷', 570 | \ 'Mcc': '𝒸', 571 | \ 'Mcd': '𝒹', 572 | \ 'Mcf': '𝒻', 573 | \ 'Mch': '𝒽', 574 | \ 'Mci': '𝒾', 575 | \ 'Mcj': '𝒿', 576 | \ 'Mck': '𝓀', 577 | \ 'Mcl': '𝓁', 578 | \ 'Mcm': '𝓂', 579 | \ 'Mcn': '𝓃', 580 | \ 'Mcp': '𝓅', 581 | \ 'Mcq': '𝓆', 582 | \ 'Mcr': '𝓇', 583 | \ 'Mcs': '𝓈', 584 | \ 'Mct': '𝓉', 585 | \ 'Mcu': '𝓊', 586 | \ 'Mcv': '𝓋', 587 | \ 'Mcw': '𝓌', 588 | \ 'Mcx': '𝓍', 589 | \ 'Mcy': '𝓎', 590 | \ 'Mcz': '𝓏', 591 | \ 'MfA': '𝔄', 592 | \ 'MfB': '𝔅', 593 | \ 'MfD': '𝔇', 594 | \ 'MfE': '𝔈', 595 | \ 'MfF': '𝔉', 596 | \ 'MfG': '𝔊', 597 | \ 'MfJ': '𝔍', 598 | \ 'MfK': '𝔎', 599 | \ 'MfL': '𝔏', 600 | \ 'MfM': '𝔐', 601 | \ 'MfN': '𝔑', 602 | \ 'MfO': '𝔒', 603 | \ 'MfP': '𝔓', 604 | \ 'MfQ': '𝔔', 605 | \ 'MfS': '𝔖', 606 | \ 'MfT': '𝔗', 607 | \ 'MfU': '𝔘', 608 | \ 'MfV': '𝔙', 609 | \ 'MfW': '𝔚', 610 | \ 'MfX': '𝔛', 611 | \ 'MfY': '𝔜', 612 | \ 'Mfa': '𝔞', 613 | \ 'Mfb': '𝔟', 614 | \ 'Mfc': '𝔠', 615 | \ 'Mfd': '𝔡', 616 | \ 'Mfe': '𝔢', 617 | \ 'Mff': '𝔣', 618 | \ 'Mfg': '𝔤', 619 | \ 'Mfh': '𝔥', 620 | \ 'Mfi': '𝔦', 621 | \ 'Mfj': '𝔧', 622 | \ 'Mfk': '𝔨', 623 | \ 'Mfl': '𝔩', 624 | \ 'Mfm': '𝔪', 625 | \ 'Mfn': '𝔫', 626 | \ 'Mfo': '𝔬', 627 | \ 'Mfp': '𝔭', 628 | \ 'Mfq': '𝔮', 629 | \ 'Mfr': '𝔯', 630 | \ 'Mfs': '𝔰', 631 | \ 'Mft': '𝔱', 632 | \ 'Mfu': '𝔲', 633 | \ 'Mfv': '𝔳', 634 | \ 'Mfw': '𝔴', 635 | \ 'Mfx': '𝔵', 636 | \ 'Mfy': '𝔶', 637 | \ 'Mfz': '𝔷', 638 | \}) 639 | 640 | 641 | lockvar g:agda#default_glyphs 642 | endif 643 | 644 | if !exists('g:agda#glyphs') 645 | let g:agda#glyphs = deepcopy(g:agda#default_glyphs) 646 | endif 647 | 648 | let &cpo = s:cpo_save 649 | -------------------------------------------------------------------------------- /agda.py: -------------------------------------------------------------------------------- 1 | import vim 2 | import re 3 | import subprocess 4 | from functools import wraps 5 | 6 | 7 | def vim_func(vim_fname_or_func=None, conv=None): 8 | '''Expose a python function to vim, optionally overriding its name.''' 9 | 10 | def wrap_func(func, vim_fname, conv): 11 | fname = func.func_name 12 | vim_fname = vim_fname or fname 13 | 14 | arg_names = func.func_code.co_varnames[:func.func_code.co_argcount] 15 | arg_defaults = dict(zip(arg_names[:-len(func.func_defaults or ()):], func.func_defaults or [])) 16 | 17 | @wraps(func) 18 | def from_vim(vim_arg_dict): 19 | args = {} 20 | for k in arg_names: 21 | try: 22 | val = vim_arg_dict[k] 23 | except KeyError: 24 | val = arg_defaults[k] 25 | 26 | if k in conv: 27 | val = conv[k](val) 28 | 29 | args[k] = val 30 | return func(**args) 31 | 32 | setattr(func, 'from_vim', from_vim) 33 | 34 | vim.command(''' 35 | function! {vim_fname}({vim_params}) 36 | py {fname}.from_vim(vim.eval(\'a:\')) 37 | endfunction 38 | '''.format( 39 | vim_fname=vim_fname, 40 | vim_params=', '.join(arg_names), 41 | fname=fname, 42 | )) 43 | return func 44 | 45 | if callable(vim_fname_or_func): 46 | return wrap_func(func=vim_fname_or_func, vim_fname=None, conv={}) 47 | 48 | def wrapper(func): 49 | return wrap_func(func=func, vim_fname=vim_fname_or_func, conv=conv or {}) 50 | return wrapper 51 | 52 | 53 | def vim_bool(s): 54 | if not s: 55 | return False 56 | elif s == 'False': 57 | return False 58 | elif s == 'True': 59 | return True 60 | return bool(int(s)) 61 | 62 | 63 | # start Agda 64 | # TODO: I'm pretty sure this will start an agda process per buffer which is less than desirable... 65 | agda = subprocess.Popen(["agda", "--interaction"], bufsize = 1, stdin = subprocess.PIPE, stdout = subprocess.PIPE, universal_newlines = True) 66 | 67 | goals = {} 68 | annotations = [] 69 | 70 | agdaVersion = [0,0,0,0] 71 | 72 | rewriteMode = "Normalised" 73 | 74 | # This technically needs to turn a string into a Haskell escaped string, buuuut just gonna cheat. 75 | def escape(s): 76 | return s.replace('\\', '\\\\').replace('"', '\\"').replace('\n','\\n') # keep '\\' case first 77 | 78 | # This technically needs to turn a Haskell escaped string into a string, buuuut just gonna cheat. 79 | def unescape(s): 80 | return s.replace('\\\\','\x00').replace('\\"', '"').replace('\\n','\n').replace('\x00', '\\') # hacktastic 81 | 82 | def setRewriteMode(mode): 83 | global rewriteMode 84 | mode = mode.strip() 85 | if mode not in ["AsIs", "Normalised", "Simplified", "HeadNormal", "Instantiated"]: 86 | rewriteMode = "Normalised" 87 | else: 88 | rewriteMode = mode 89 | 90 | def promptUser(msg): 91 | vim.command('call inputsave()') 92 | result = vim.eval('input("%s")' % msg) 93 | vim.command('call inputrestore()') 94 | return result 95 | 96 | def AgdaRestart(): 97 | global agda 98 | agda = subprocess.Popen(["agda", "--interaction"], bufsize = 1, stdin = subprocess.PIPE, stdout = subprocess.PIPE, universal_newlines = True) 99 | 100 | def findGoals(goalList): 101 | global goals 102 | 103 | vim.command('syn sync fromstart') # TODO: This should become obsolete given good sync rules in the syntax file. 104 | 105 | goals = {} 106 | lines = vim.current.buffer 107 | row = 1 108 | agdaHolehlID = vim.eval('hlID("agdaHole")') 109 | for line in lines: 110 | 111 | start = 0 112 | while start != -1: 113 | qstart = line.find("?", start) 114 | hstart = line.find("{!", start) 115 | if qstart == -1: 116 | start = hstart 117 | elif hstart == -1: 118 | start = qstart 119 | else: 120 | start = min(hstart, qstart) 121 | if start != -1: 122 | start = start + 1 123 | 124 | if vim.eval('synID("%d", "%d", 0)' % (row, start)) == agdaHolehlID: 125 | goals[goalList.pop(0)] = (row, start) 126 | if len(goalList) == 0: break 127 | if len(goalList) == 0: break 128 | row = row + 1 129 | 130 | vim.command('syn sync clear') # TODO: This wipes out any sync rules and should be removed if good sync rules are added to the syntax file. 131 | 132 | def findGoal(row, col): 133 | global goals 134 | for item in goals.items(): 135 | if item[1][0] == row and item[1][1] == col: 136 | return item[0] 137 | return None 138 | 139 | def getOutput(): 140 | line = agda.stdout.readline()[7:] # get rid of the "Agda2> " prompt 141 | lines = [] 142 | while not line.startswith('Agda2> cannot read') and line != "": 143 | lines.append(line) 144 | line = agda.stdout.readline() 145 | return lines 146 | 147 | def parseVersion(versionString): 148 | global agdaVersion 149 | agdaVersion = [int(c) for c in versionString[12:].split("-")[0].split('.')] 150 | agdaVersion = agdaVersion + [0]*max(0, 4-len(agdaVersion)) 151 | 152 | # This is not very efficient presumably. 153 | def c2b(n): 154 | return int(vim.eval('byteidx(join(getline(1, "$"), "\n"),%d)' % n)) 155 | 156 | # See https://github.com/agda/agda/blob/323f58f9b8dad239142ed1dfa0c60338ea2cb157/src/data/emacs-mode/annotation.el#L112 157 | def parseAnnotation(spans): 158 | global annotations 159 | anns = re.findall(r'\((\d+) (\d+) \([^\)]*\) \w+ \(\"([^"]*)\" \. (\d+)\)\)', spans) 160 | # TODO: This is assumed to be in sorted order. 161 | for ann in anns: 162 | annotations.append([c2b(int(ann[0])-1), c2b(int(ann[1])-1), ann[2], c2b(int(ann[3]))]) 163 | 164 | def searchAnnotation(lo, hi, idx): 165 | global annotations 166 | 167 | if hi == 0: return None 168 | 169 | while hi - lo > 1: 170 | mid = lo + (hi - lo) // 2 171 | midOffset = annotations[mid][0] 172 | if idx < midOffset: 173 | hi = mid 174 | else: 175 | lo = mid 176 | 177 | (loOffset, hiOffset) = annotations[lo][0:2] 178 | if idx > loOffset and idx <= hiOffset: 179 | return annotations[lo][2:4] 180 | else: 181 | return None 182 | 183 | def gotoAnnotation(): 184 | global annotations 185 | byteOffset = int(vim.eval('line2byte(line(".")) + col(".") - 1')) 186 | result = searchAnnotation(0, len(annotations), byteOffset) 187 | if result is None: return 188 | (file, pos) = result 189 | targetBuffer = None 190 | for buffer in vim.buffers: 191 | if buffer.name == file: targetBuffer = buffer.number 192 | 193 | if targetBuffer is None: 194 | vim.command('edit %s' % file) 195 | else: 196 | vim.command('buffer %s' % targetBuffer) 197 | vim.command('%dgo' % pos) 198 | 199 | def interpretResponse(responses, quiet = False): 200 | for response in responses: 201 | if response.startswith('(agda2-info-action ') or response.startswith('(agda2-info-action-and-copy '): 202 | if quiet and '*Error*' in response: vim.command('cwindow') 203 | strings = re.findall(r'"((?:[^"\\]|\\.)*)"', response[19:]) 204 | if strings[0] == '*Agda Version*': 205 | parseVersion(strings[1]) 206 | if quiet: continue 207 | vim.command('call s:LogAgda("%s","%s","%s")'% (strings[0], strings[1], response.endswith('t)'))) 208 | elif "(agda2-goals-action '" in response: 209 | findGoals([int(s) for s in re.findall(r'(\d+)', response[response.index("agda2-goals-action '")+21:])]) 210 | elif "(agda2-make-case-action-extendlam '" in response: 211 | response = response.replace("?", "{! !}") # this probably isn't safe 212 | cases = re.findall(r'"((?:[^"\\]|\\.)*)"', response[response.index("agda2-make-case-action-extendlam '")+34:]) 213 | col = vim.current.window.cursor[1] 214 | line = vim.current.line 215 | 216 | # TODO: The following logic is far from perfect. 217 | # Look for a semicolon ending the previous case. 218 | correction = 0 219 | starts = [mo for mo in re.finditer(r';', line[:col])] 220 | if len(starts) == 0: 221 | # Look for the starting bracket of the extended lambda.. 222 | correction = 1 223 | starts = [mo for mo in re.finditer(r'{[^!]', line[:col])] 224 | if len(starts) == 0: 225 | # Assume the case is on a line by itself. 226 | correction = 1 227 | starts = [mo for mo in re.finditer(r'^[ \t]*', line[:col])] 228 | start = starts[-1].end() - correction 229 | 230 | # Look for a semicolon ending this case. 231 | correction = 0 232 | ends = re.search(r';', line[col:]) 233 | if ends == None: 234 | # Look for the ending bracket of the extended lambda. 235 | correction = 1 236 | ends = re.search(r'[^!]}', line[col:]) 237 | if ends == None: 238 | # Assume the case is on a line by itself (or at least has nothing after it). 239 | correction = 0 240 | ends = re.search(r'[ \t]*$', line[col:]) 241 | end = ends.start() + col + correction 242 | 243 | vim.current.line = line[:start] + " " + "; ".join(cases) + " " + line[end:] 244 | f = vim.current.buffer.name 245 | sendCommandLoad(f, quiet) 246 | break 247 | elif "(agda2-make-case-action '" in response: 248 | response = response.replace("?", "{! !}") # this probably isn't safe 249 | cases = re.findall(r'"((?:[^"\\]|\\.)*)"', response[response.index("agda2-make-case-action '")+24:]) 250 | row = vim.current.window.cursor[0] 251 | prefix = re.match(r'[ \t]*', vim.current.line).group() 252 | vim.current.buffer[row-1:row] = [prefix + case for case in cases] 253 | f = vim.current.buffer.name 254 | sendCommandLoad(f, quiet) 255 | break 256 | elif response.startswith('(agda2-give-action '): 257 | response = response.replace("?", "{! !}") 258 | match = re.search(r'(\d+)\s+"((?:[^"\\]|\\.)*)"', response[19:]) 259 | replaceHole(unescape(match.group(2))) 260 | # elif response.startswith('(agda2-highlight-clear)'): 261 | # pass # Maybe do something with this. 262 | elif response.startswith('(agda2-highlight-add-annotations '): 263 | parseAnnotation(response) 264 | else: 265 | pass # print(response) 266 | 267 | def sendCommand(arg, quiet=False): 268 | vim.command('silent! write') 269 | f = vim.current.buffer.name 270 | # The x is a really hacky way of getting a consistent final response. Namely, "cannot read" 271 | agda.stdin.write('IOTCM "%s" None Direct (%s)\nx\n' % (escape(f), arg)) 272 | interpretResponse(getOutput(), quiet) 273 | 274 | def sendCommandLoadHighlightInfo(file, quiet): 275 | sendCommand('Cmd_load_highlighting_info "%s"' % escape(file), quiet = quiet) 276 | 277 | def sendCommandLoad(file, quiet): 278 | global agdaVersion 279 | if agdaVersion < [2,5,0,0]: # in 2.5 they changed it so Cmd_load takes commandline arguments 280 | incpaths_str = ",".join(vim.vars['agdavim_agda_includepathlist']) 281 | else: 282 | incpaths_str = "\"-i\"," + ",\"-i\",".join(vim.vars['agdavim_agda_includepathlist']) 283 | sendCommand('Cmd_load "%s" [%s]' % (escape(file), incpaths_str), quiet = quiet) 284 | 285 | #def getIdentifierAtCursor(): 286 | # (r, c) = vim.current.window.cursor 287 | # line = vim.current.line 288 | # try: 289 | # start = re.search(r"[^\s@(){};]+$", line[:c+1]).start() 290 | # end = re.search(r"^[^\s@(){};]+", line[c:]).end() + c 291 | # except AttributeError as e: 292 | # return None 293 | # return line[start:end] 294 | 295 | def replaceHole(replacement): 296 | rep = replacement.replace('\n', ' ').replace(' ', ';') # TODO: This probably needs to be handled better 297 | (r, c) = vim.current.window.cursor 298 | line = vim.current.line 299 | if line[c] == "?": 300 | start = c 301 | end = c+1 302 | else: 303 | try: 304 | mo = None 305 | for mo in re.finditer(r"{!", line[:min(len(line),c+2)]): pass 306 | start = mo.start() 307 | end = re.search(r"!}", line[max(0,c-1):]).end() + max(0,c-1) 308 | except AttributeError: 309 | return 310 | vim.current.line = line[:start] + rep + line[end:] 311 | 312 | def getHoleBodyAtCursor(): 313 | (r, c) = vim.current.window.cursor 314 | line = vim.current.line 315 | try: 316 | if line[c] == "?": 317 | return ("?", findGoal(r, c+1)) 318 | except IndexError: 319 | return None 320 | try: # handle virtual space better 321 | mo = None 322 | for mo in re.finditer(r"{!", line[:min(len(line),c+2)]): pass 323 | start = mo.start() 324 | end = re.search(r"!}", line[max(0,c-1):]).end() + max(0,c-1) 325 | except AttributeError: 326 | return None 327 | result = line[start+2:end-2].strip() 328 | if result == "": 329 | result = "?" 330 | return (result, findGoal(r, start+1)) 331 | 332 | def getWordAtCursor(): 333 | return vim.eval("expand('')").strip() 334 | 335 | 336 | ## Directly exposed functions: { 337 | 338 | @vim_func(conv={'quiet': vim_bool}) 339 | def AgdaVersion(quiet): 340 | sendCommand('Cmd_show_version', quiet=quiet) 341 | 342 | 343 | @vim_func(conv={'quiet': vim_bool}) 344 | def AgdaLoad(quiet): 345 | f = vim.current.buffer.name 346 | sendCommandLoad(f, quiet) 347 | if vim.vars['agdavim_enable_goto_definition']: 348 | sendCommandLoadHighlightInfo(f, quiet) 349 | 350 | 351 | @vim_func(conv={'quiet': vim_bool}) 352 | def AgdaLoadHighlightInfo(quiet): 353 | f = vim.current.buffer.name 354 | sendCommandLoadHighlightInfo(f, quiet) 355 | 356 | 357 | @vim_func 358 | def AgdaGotoAnnotation(): 359 | gotoAnnotation() 360 | 361 | 362 | @vim_func 363 | def AgdaGive(): 364 | result = getHoleBodyAtCursor() 365 | 366 | if agdaVersion < [2,5,3,0]: 367 | useForce = "" 368 | else: 369 | useForce = "WithoutForce" # or WithForce 370 | 371 | if result is None: 372 | print("No hole under the cursor") 373 | elif result[1] is None: 374 | print("Goal not loaded") 375 | elif result[0] == "?": 376 | sendCommand('Cmd_give %s %d noRange "%s"' % (useForce, result[1], escape(promptUser("Enter expression: ")))) 377 | else: 378 | sendCommand('Cmd_give %s %d noRange "%s"' % (useForce, result[1], escape(result[0]))) 379 | 380 | 381 | @vim_func 382 | def AgdaMakeCase(): 383 | result = getHoleBodyAtCursor() 384 | if result is None: 385 | print("No hole under the cursor") 386 | elif result[1] is None: 387 | print("Goal not loaded") 388 | elif result[0] == "?": 389 | sendCommand('Cmd_make_case %d noRange "%s"' % (result[1], escape(promptUser("Make case on: ")))) 390 | else: 391 | sendCommand('Cmd_make_case %d noRange "%s"' % (result[1], escape(result[0]))) 392 | 393 | 394 | @vim_func 395 | def AgdaRefine(unfoldAbstract): 396 | result = getHoleBodyAtCursor() 397 | if result is None: 398 | print("No hole under the cursor") 399 | elif result[1] is None: 400 | print("Goal not loaded") 401 | else: 402 | sendCommand('Cmd_refine_or_intro %s %d noRange "%s"' % (unfoldAbstract, result[1], escape(result[0]))) 403 | 404 | 405 | @vim_func 406 | def AgdaAuto(): 407 | result = getHoleBodyAtCursor() 408 | if result is None: 409 | print("No hole under the cursor") 410 | elif result[1] is None: 411 | print("Goal not loaded") 412 | else: 413 | if agdaVersion < [2,6,0,0]: 414 | sendCommand('Cmd_auto %d noRange "%s"' % (result[1], escape(result[0]) if result[0] != "?" else "")) 415 | else: 416 | sendCommand('Cmd_autoOne %d noRange "%s"' % (result[1], escape(result[0]) if result[0] != "?" else "")) 417 | 418 | 419 | @vim_func 420 | def AgdaContext(): 421 | result = getHoleBodyAtCursor() 422 | if result is None: 423 | print("No hole under the cursor") 424 | elif result[1] is None: 425 | print("Goal not loaded") 426 | else: 427 | sendCommand('Cmd_goal_type_context_infer %s %d noRange "%s"' % (rewriteMode, result[1], escape(result[0]))) 428 | 429 | 430 | @vim_func 431 | def AgdaInfer(): 432 | result = getHoleBodyAtCursor() 433 | if result is None: 434 | sendCommand('Cmd_infer_toplevel %s "%s"' % (rewriteMode, escape(promptUser("Enter expression: ")))) 435 | elif result[1] is None: 436 | print("Goal not loaded") 437 | else: 438 | sendCommand('Cmd_infer %s %d noRange "%s"' % (rewriteMode, result[1], escape(result[0]))) 439 | 440 | 441 | # As of 2.5.2, the options are "DefaultCompute", "IgnoreAbstract", "UseShowInstance" 442 | @vim_func 443 | def AgdaNormalize(unfoldAbstract): 444 | if agdaVersion < [2,5,2,0]: 445 | unfoldAbstract = str(unfoldAbstract == "DefaultCompute") 446 | 447 | result = getHoleBodyAtCursor() 448 | if result is None: 449 | sendCommand('Cmd_compute_toplevel %s "%s"' % (unfoldAbstract, escape(promptUser("Enter expression: ")))) 450 | elif result[1] is None: 451 | print("Goal not loaded") 452 | else: 453 | sendCommand('Cmd_compute %s %d noRange "%s"' % (unfoldAbstract, result[1], escape(result[0]))) 454 | 455 | 456 | @vim_func 457 | def AgdaWhyInScope(termName): 458 | result = getHoleBodyAtCursor() if termName == '' else None 459 | 460 | if result is None: 461 | termName = getWordAtCursor() if termName == '' else termName 462 | termName = promptUser("Enter name: ") if termName == '' else termName 463 | sendCommand('Cmd_why_in_scope_toplevel "%s"' % escape(termName)) 464 | elif result[1] is None: 465 | print("Goal not loaded") 466 | else: 467 | sendCommand('Cmd_why_in_scope %d noRange "%s"' % (result[1], escape(result[0]))) 468 | 469 | 470 | @vim_func 471 | def AgdaShowModule(moduleName): 472 | result = getHoleBodyAtCursor() if moduleName == '' else None 473 | 474 | if agdaVersion < [2,4,2,0]: 475 | if result is None: 476 | moduleName = promptUser("Enter module name: ") if moduleName == '' else moduleName 477 | sendCommand('Cmd_show_module_contents_toplevel "%s"' % escape(moduleName)) 478 | elif result[1] is None: 479 | print("Goal not loaded") 480 | else: 481 | sendCommand('Cmd_show_module_contents %d noRange "%s"' % (result[1], escape(result[0]))) 482 | else: 483 | if result is None: 484 | moduleName = promptUser("Enter module name: ") if moduleName == '' else moduleName 485 | sendCommand('Cmd_show_module_contents_toplevel %s "%s"' % (rewriteMode, escape(moduleName))) 486 | elif result[1] is None: 487 | print("Goal not loaded") 488 | else: 489 | sendCommand('Cmd_show_module_contents %s %d noRange "%s"' % (rewriteMode, result[1], escape(result[0]))) 490 | 491 | 492 | @vim_func 493 | def AgdaHelperFunction(): 494 | result = getHoleBodyAtCursor() 495 | 496 | if result is None: 497 | print("No hole under the cursor") 498 | elif result[1] is None: 499 | print("Goal not loaded") 500 | elif result[0] == "?": 501 | sendCommand('Cmd_helper_function %s %d noRange "%s"' % (rewriteMode, result[1], escape(promptUser("Enter name for helper function: ")))) 502 | else: 503 | sendCommand('Cmd_helper_function %s %d noRange "%s"' % (rewriteMode, result[1], escape(result[0]))) 504 | 505 | 506 | ## } 507 | --------------------------------------------------------------------------------