Thursday, September 20, 2012

Re: FileTypePre autocmd

exec "py3file" fnameescape(expand("<sfile>:p:h")."/context_menu.py")
function! context_menu#init()
augroup context_menu
autocmd BufEnter * :py3 handle_menu_add()
autocmd BufLeave * :py3 handle_menu_remove()

autocmd FileType * call <SID>recodeFiletype()
function! s:recodeFiletype()
if !exists('b:context_menu_current_filetype')
let b:context_menu_current_filetype = &filetype
else
let b:context_menu_privious_filetype = b:context_menu_current_filetype
let b:context_menu_current_filetype = &filetype
endif
endfunction

autocmd FileType * :py3 handle_filetype_change()
augroup END
endfunction
#!/usr/bin/python3


def vim_cmd_quote(s):
return s.replace(' ', r'\ ')


def build_vim_cmd(*args):
return ' '.join(map(vim_cmd_quote, args))


class VimMenu(object):
"A vim menu"

def __init__(self, name, rhs, mode='a', priority="500", silent=True):
self._name = name
self._rhs = rhs
self._mode = mode
self._priority = priority
self._silent = silent

modes = {'a': ['anoremenu', 'aunmenu'],
'n': ['nnoremenu', 'nunmenu'],
'i': ['inoremenu', 'iunmenu'],
'v': ['vnoremenu', 'vunmenu'],
'c': ['cnoremenu', 'cunmenu'],
'o': ['onoremenu', 'ounmenu'],
}

def add(self):
cmd = build_vim_cmd('silent',
VimMenu.modes[self._mode][0],
'<silent>' if self._silent else '',
self._priority,
self._name
) + ' ' + self._rhs
print(cmd)
vim.command(cmd)

def remove(self, force=False):
if force:
cmd = build_vim_cmd('silent!', VimMenu.modes[self._mode][1], self._name)
else:
cmd = build_vim_cmd('silent', VimMenu.modes[self._mode][1], self._name)
vim.command(cmd)


class VimPopUpMenu(VimMenu):
"Vim PopUp Menu"
def __init__(self, name, rhs, mode='a', priority="56", silent=False):
super(VimPopUpMenu, self).__init__(
'PopUp.'+name, rhs, mode, '1.'+priority, silent)


def get_current_filetype():
return vim.eval('&filetype')


def get_menu(filetype):
return FILETYPE_MENU.get(filetype, [])


def handle_menu_remove(filetype=None):
if filetype is None:
filetype = get_current_filetype()
for menu in get_menu(filetype):
menu.remove(force=True)


def handle_menu_add(filetype=None):
if filetype is None:
filetype = get_current_filetype()
for menu in get_menu(filetype):
menu.add()


def handle_filetype_change():
try:
from vim3.core import vimcall
except ImportError:
def vimcall(x, y):
return vim.eval('%s("%s")' % (x, y))

if vimcall('exists', 'b:context_menu_privious_filetype') == '1':
handle_menu_remove(vim.eval('b:context_menu_privious_filetype'))
if vimcall('exists', 'b:context_menu_current_filetype') == '1':
handle_menu_add(vim.eval('b:context_menu_current_filetype'))


FILETYPE_MENU = {
'fortran': [VimMenu('Fortran.Run', ':!./%:r<CR>'),
VimMenu('Fortran.Compile This File', ':!gfortran % -o %:r<CR>'),
VimPopUpMenu('Align ::', ':Align ::<CR>', mode='v')
],
'c': [VimMenu('C.Run', ':!./%:r<CR>'),
VimPopUpMenu('comment', ':s/^/!/<CR>', mode='v')]
}

def register_filetype_menu(filetype, menu):
if isinstance(menu, VimMenu):
if filetype in FILETYPE_MENU:
FILETYPE_MENU[filetype].append(menu)
else:
FILETYPE_MENU[filetype] = [menu]
else:
for m in menu:
register_filetype_menu(filetype, m)
On Do 20 Sep 2012 16:18:57 CST, Christian Brabandt wrote:
> On Thu, September 20, 2012 09:30, Fermat618 wrote:
>> I wrote a small plugin in python to handle filetype specific menu auto
>> add and auto remove.
>>
>> As long as I put
>>
>> py3 register_filetype_menu('python', VimMenu('Python.Foo', ':call
>> bar()<CR>'))
>>
>> in my .vimrc file, a menu 'Python' will and will only appear when my
>> current buffer is
>> has 'python' filetype, which means, e.g., when I leave a python buffer
>> and
>> enter a C buffer, Python menu whill disappear and a C menu will appear.
>>
>> autocmd BufEnter * :py3 handle_menu_add()
>> autocmd BufLeave * :py3 handle_menu_remove()
>>
>> The above autocmd are what I used. handle_menu_add() function will
>> detect the current filetype and get the menu informations of that
>> filetype which I stored with register_filetype_menu() function, then add
>> those menus.
>>
>> There should be enough information of what filetype I'm leaving and what
>> I'm entering, to remove old menus and add new menus.
>>
>> This fails when resetting the filetype of a buffer, because I don't know
>> how to get the previous filetype of the buffer.
>
> Programmatically, you can get the previous filetype, by recording each
> filetype (e.g. this should work to always see the previous filetype):
>
> let g:filetype_stack = []
> au FileType * echo get(g:filetype_stack, -1, '') |
> \ call add(g:filetype_stack, expand("<amatch>"))
>
> and then in your plugin check g:filetype_stack[-1] or -2 (depending on
> whether your Filetype autocommand is called before or after the above
> filetype autocommand).
>
> BTW: I would not mix different filetype settings in one single plugin,
> but put each filetype specific plugin below a separate
> ~/.vim/ftplugin/<filetype>.vim (where <filetype> stands for your
> actual filetype, as you probably guessed) see also :h filetype-plugin
>
> Here is what I do, in my csv filetype plugin:
> https://github.com/chrisbra/csv.vim/blob/master/ftplugin/csv.vim#L247
>
> regards,
> Christian
>
Thanks. These code work fine.

augroup context_menu
autocmd BufEnter * :py3 handle_menu_add()
autocmd BufLeave * :py3 handle_menu_remove()

autocmd FileType * call <SID>recodeFiletype()
function! s:recodeFiletype()
if !exists('b:context_menu_current_filetype')
let b:context_menu_current_filetype = &filetype
else
let b:context_menu_privious_filetype =
b:context_menu_current_filetype
let b:context_menu_current_filetype = &filetype
endif
endfunction

autocmd FileType * :py3 handle_filetype_change()
augroup END

I am just to build a mechanism that is absent from vim currently. Not to
mixture different filetype settings together. Now one command is enough
to add a context menu, and I will not care about those details when I
want to add context menu for new filetypes.

In fact, I put the

:py3 register_filetype_menu('python', VimMenu('Python.Run', xxx ))

in ftplugin/python.vim other than in my ~/.vimrc

Attachments are the code I finally get. Put those files in
~/.vim/autoload and add

call context_menu#init()

in ~/.vimrc. Then use

:py3 register_filetype_menu(filetype, VimMenu(menu, mapping))

to add a context menu for a filetype. (python3 support is required)

Hope that will help.

--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

No comments: