Commits

ZyX_I committed 298bb6a

@/commands: Added unoverridable buffer:1 for ftplugins

Comments (0)

Files changed (6)

         bar       0 or 1, see |:command-bar|. Default: 1.
         register  0 or 1, see |:command-register|. Default: 0. Adds <q-reg> to 
                   argument list.
-        buffer    0 or 1, see |:command-buffer|. Default: 0.
+        buffer    0 or 1, see |:command-buffer|. Default: 0, 1 for ftplugins.
+                  Note that if plugin type is `ftplugin', then `buffer' is on 
+                  by default and you cannot switch it off.
         complete  Defines completion for the command. Possible values:
                   1. String, see |:command-complete|.
                   2. Function reference. Anonymous and script-local functions 

plugin/frawor/commands.vim

 "▶1 command feature
 let s:F.command={}
 let s:commands={}
+let s:bufcommands={}
+let s:fts={}
 "▶2 addfunc      :: cmd, fdescr → + cmd | :function
 function s:F.addfunc(cmd, plstatus, fdescr)
     if a:plstatus!=2
         call s:F.loadplugin(a:cmd)
         let a:cmd.f=call(a:cmd.wrapfunc, [a:cmd.f], {})
         execute 'delcommand' a:cmd.id
-        execute 'command' a:cmd.cmdstring
-        unlet a:cmd.cmdstring
+        execute 'command' a:cmd.newcmdstring
+        let a:cmd.cmdstring=a:cmd.newcmdstring
+        unlet a:cmd.newcmdstring
     endif
     return call(a:cmd.f, a:args, {})
 endfunction
                 \'funs': [],
                 \  'fs': {},
                 \}
+    if a:plugdict.type is# 'ftplugin'
+        let cmd.filetype=matchstr(a:plugdict.id, '\v^[^/]*', 9)
+    endif
     let cmdstring=''
     let addargs=[]
     "▶3 Process *splitfunc
     let cmd.rsp=s:F.getspfunc(a:plugdict.id, a:cid, a:copts, 'r')
     "▶3 Create :command -options
     for [key, value] in sort(items(s:cmddefaults))
-        if has_key(a:copts, key)
+        if a:plugdict.type is# 'ftplugin' && key is# 'buffer'
+            let value=1
+        elseif has_key(a:copts, key)
             "▶4 Completion
             if key is# 'complete'
                 let d={}
                 endif
             "▶4 Other options
             else
-                " TODO: Make unoverridable buffer=1 for filetype plugins
                 unlet value
                 let value=a:copts[key]
                 if key is# 'range'
             let args.='s:commands.'.a:cid.'.rsp(<q-args>)'
         endif
         if type(a:cstr)==type({})
-            let cmd.cmdstring=cmdstring.
+            let cmd.newcmdstring=cmdstring.
                         \     'call call(s:commands.'.a:cid.'.f, '.args.', {})'
             let cmdstring.='call s:F.runcmd(s:commands.'.a:cid.', '.args.')'
         else
         endif
     endif
     "▲3
+    let cmd.cmdstring=cmdstring
+    let a:fdict[cmd.id]=cmd
+    "▶3 Add cmd to various global variables, execute :command
     let s:commands[cmd.id]=cmd
-    let a:fdict[cmd.id]=cmd
-    execute 'command' cmdstring
+    if has_key(cmd, 'filetype')
+        if !has_key(s:fts, cmd.filetype)
+            let s:fts[cmd.filetype]={}
+        endif
+        let s:fts[cmd.filetype][cmd.id]=cmd
+        let buf=bufnr('%')
+        if !has_key(s:bufcommands, buf)
+            let s:bufcommands[buf]={}
+        endif
+        if index(split(&filetype, '\.'), cmd.filetype)!=-1
+            execute 'command' cmdstring
+            let s:bufcommands[buf][cmd.id]=cmd
+        endif
+    else
+        execute 'command' cmdstring
+    endif
+    "▲3
 endfunction
 "▶2 command.del  :: {f}[, cid] → + :delcommand, s:commands
 function s:F.command.del(plugdict, fdict, ...)
 "▶2 Register feature
 call s:_f.newfeature('command', {'cons': s:F.command,
             \                  'unload': s:F.command.del,})
+"▶1 ftcommand     :: () → + :delcommand, :command, s:bufcommands
+function s:F.ftcommand()
+    let buf=expand('<abuf>')
+    if has_key(s:bufcommands, buf)
+        for cid in keys(s:bufcommands[buf])
+            execute 'delcommand' cid
+        endfor
+    else
+        let s:bufcommands[buf]={}
+    endif
+    for filetype in filter(split(&filetype, '\V.'), 'has_key(s:fts, v:val)')
+        for cmd in values(s:fts[filetype])
+            execute 'command' cmd.cmdstring
+            let s:bufcommands[buf][cmd.id]=cmd
+        endfor
+    endfor
+endfunction
+"▶1 bufentered    :: () → s:F.ftcommand()
+function s:F.bufentered()
+    let buf=expand('<abuf>')
+    if !has_key(s:bufcommands, buf)
+        call s:F.ftcommand()
+    endif
+endfunction
+"▶1 bufdeleted    :: () → + s:bufcommands
+function s:F.bufdeleted()
+    let buf=expand('<abuf>')
+    if has_key(s:bufcommands, buf)
+        unlet s:bufcommands[buf]
+    endif
+endfunction
+"▶1 Create autocommands
+call s:_f.augroup.add('Commands', [['BufEnter',  '*', 0, s:F.bufentered],
+            \                      ['BufDelete', '*', 0, s:F.bufdeleted],
+            \                      ['Filetype',  '*', 0, s:F.ftcommand ]])
 "▶1
-call frawor#Lockvar(s:, 'commands')
+call frawor#Lockvar(s:, 'commands,fts,bufcommands')
 " vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80

plugin/frawor/mappings.vim

     endif
     "▶3 filetype
     if !mgroup.dontmap && a:plugdict.type is# 'ftplugin'
-        let mgroup.filetype=matchstr(a:plugdict.id[9:], '^[^/]*')
+        let mgroup.filetype=matchstr(a:plugdict.id, '\v^[^/]*', 9)
         let mgroup.dontmap=1
     endif
     "▲3
     else
         call s:F.bufentered()
     endif
-    let filetypes=split(expand('<amatch>'), '\.')
+    let filetypes=split(expand('<amatch>'), '\V.')
     for filetype in filter(filetypes, 'has_key(s:fts, v:val)')
         for mgroup in values(s:fts[filetype])
             call s:F.mapmgroup(mgroup, 0, 1)
     endif
 endfunction
 "▶1 Create autocommands
-call s:_f.augroup.add('Mappings', [["BufEnter",  '*', 0, s:F.bufentered   ],
-            \                      ["BufDelete", '*', 0, s:F.delbuffermaps],
-            \                      ["Filetype",  '*', 0, s:F.ftmap        ]])
+call s:_f.augroup.add('Mappings', [['BufEnter',  '*', 0, s:F.bufentered   ],
+            \                      ['BufDelete', '*', 0, s:F.delbuffermaps],
+            \                      ['Filetype',  '*', 0, s:F.ftmap        ]])
 "▶1 map resource
 call s:_f.postresource('map', {'maparg': s:F.savemap,
             \                     'map': s:F.map,

test/filetype-commands.in

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="ftplugin/test.vim"
+:source test.vim
+:FtWrite
+:W: ft=test
+:set ft=test
+:FtWrite
+:W: ft=
+:set ft=
+:FtWrite
+:W+ 2()
+:new
+:FtWrite
+:W+ 3(test)
+:new test
+:FtWrite
+:W+ 4()
+:new
+:FtWrite
+:W: 2 ft=test
+:call setbufvar(2, "&ft", "test")
+:FtWrite
+:W> 2
+:b 2
+:FtWrite

test/filetype-commands.ok

+: ft=test
+In buffer 1:test
+: ft=
++ 2()
++ 3(test)
+In buffer 3:test
++ 4()
+: 2 ft=test
+> 2
+In buffer 2:test

test/rtp/ftplugin/test.vim

-if !exists('s:_pluginloaded')
-    execute frawor#Setup('0.0', {'plugin/frawor/mappings': '0.0'}, 1)
-endif
+execute frawor#Setup('0.0', {'@/mappings': '0.0',
+            \                '@/commands': '0.0',}, 1)
 call s:_f.mapgroup.add('FtGroup', {'test': {'expr': 1, 'lhs': 'a', 'rhs': 'WriteFile("a")'}})
+call s:_f.command.add('FtWrite', 'execute "W In buffer ".bufnr("%").":".&ft', {})
 autocmd BufNewFile test setlocal ft=test