在状态行显示函数名称

问题描述 投票:0回答:9

我编辑一个大型 C、C++ 或 Java 文件,例如大约 15000 行,其中包含相当长的函数定义,例如大约 400 行。当光标位于函数定义中间时,在 Vim 状态行中看到函数名称会很酷。

当我们在 Vim 中设置

:set ls=2
时,我们可以获取文件路径(相对于当前目录)、行号等。如果我们也能看到函数名称,那就太酷了。有什么想法如何获得它吗?

目前我使用

[[
转到函数的开头,并使用 Ctrl-O 返回到我正在编辑的行。

vim
9个回答
20
投票

要在 C 程序中显示当前函数名称 在 vimrc 中添加以下内容:

fun! ShowFuncName()
  let lnum = line(".")
  let col = col(".")
  echohl ModeMsg
  echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bW'))
  echohl None
  call search("\\%" . lnum . "l" . "\\%" . col . "c")
endfun
map f :call ShowFuncName() <CR>

或者,如果您需要“f”键,只需将功能映射到您喜欢的任何位置即可。


16
投票

您可以使用ctags.vim来实现此目的,它将在标题或状态栏中显示当前的函数名称。

来源:https://superuser.com/questions/279651/how-can-i-make-vim-show-the-current-class-and-method-im-editing


10
投票

基于@manav m-n的回答

search()
中的“n”标志不会移动光标,因此具有相同功能的较短版本是:

fun! ShowFuncName()
  echohl ModeMsg
  echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bWn'))
  echohl None
endfun
map f :call ShowFuncName() <CR>

参考:运行

:help search()


2
投票

研究了这个问题和公认的解决方案后,我相信最简单的解决方案是:

  1. 安装通用 Ctags https://ctags.io/

  2. 安装标签栏https://github.com/preservim/tagbar

  3. 设置状态栏时,例如
  4. 调用

    tagbar#currenttag()
    在.vimrc中:

    :set statusline=%<%f\ %h%m%r%=%{tagbar#currenttag('%s\ ','','f')}%-.(%l,%c%V%)\ %P

请注意:

  • 传递给

    currenttag()
    的字符串中的空格必须是斜杠转义的...在 vim 中运行命令和将其放入 .vimrc 中甚至是不同的?不管怎样,空格可能很奇怪,它们可能是你在输出函数名称时想要的东西。

  • 我花了一些时间挖掘,但默认状态行是

    :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P



1
投票

我的解决方案如下:

set stl=%f%h%m%r\ %{Options()}%=%l,%c-%v\ %{line('$')}
fu! PlusOpt(opt)
  let option = a:opt
  if option
    return "+"
  else
    return "-"
  endif
endf

fu! Options()
  let opt="ic".PlusOpt(&ic)
  let opt=opt." ".&ff
  let opt=opt." ".&ft
  if &ft==?"cpp" || &ft==?"perl"
    let text = " {" . FindCurrentFunction() . "}"
    let opt= opt.text
  endif
  return opt

fu! FindCurrentFunction()
  let text =''

  let save_cursor = getpos(".")

  let opening_brace = searchpair('{','','}','bWr', '', '', 100)
  if opening_brace > 0
    let oldmagic = &magic
    let &magic = 1

    let operators='operator\s*\%((\s*)\|\[]\|[+*/%^&|~!=<>-]=\?\|[<>&|+-]\{2}\|>>=\|<<=\|->\*\|,\|->\|(\s*)\)\s*'
    let class_func_string = '\(\([[:alpha:]_]\w*\)\s*::\s*\)*\s*\%(\~\2\|'.operators
    let class_func_string = class_func_string . '\|[[:alpha:]_]\w*\)\ze\s*('

    let searchstring = '\_^\S.\{-}\%('.operators
    let searchstring = searchstring.'\|[[:alpha:]_]\w*\)\s*(.*\n\%(\_^\s.*\n\)*\_^{'

    let l = search(searchstring, 'bW', line(".")-20 )

    if l != 0
      let line_text = getline(l)
      let matched_text = matchstr(line_text, class_func_string)
      let matched_text = substitute(matched_text, '\s', '', 'g')
      let text = matched_text
    endif

    call setpos('.', save_cursor)

    let &magic = oldmagic
  endif

  return text
endfunction

我实际上正在尝试匹配 C/C++/Java 允许的函数名称。这通常对我有用(包括重载运算符),但假设开头 { 位于一行的第 0 列。

我今天刚刚注意到,如果包含在命名空间 {} 中,即使按预期格式化,它也会失败。


0
投票

我使用 https://github.com/mgedmin/chelper.vim 为此。它不需要标签文件,而是动态解析源代码。


0
投票

基于@solidak解决方案(该解决方案已经基于另一个解决方案:)

我想始终在终端底部显示函数名称。 但是我在非常大的函数上遇到了一些问题,我用这种方法解决了:

fun! ShowFuncName()
  echohl ModeMsg
  echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bWn'))[:winwidth('%')-3]
  echohl None
endfun

augroup show_funcname
  autocmd CursorMoved * :call ShowFuncName()
augroup end

0
投票

基于别人的解决方案,这里有一个Vim9版本,进一步扩展到python:

def ShowFuncName(): string
  var n_max = 20 # max chars to be displayed.
  var filetypes = ['c', 'cpp', 'python']
  var text = "" # displayed text

  if index(filetypes, &filetype) != -1
      # If the filetype is recognized, then search the function line
      var line = 0
      if index(['c', 'cpp'], &filetype) != -1
          line = search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bWn')
      elseif &filetype ==# 'python'
          line = search("^ \\{0,}def \\+.*", 'bWn')
      endif
      var n = match(getline(line), '\zs)') # Number of chars until ')'
      if n < n_max
          text = "|" .. trim(getline(line)[: n])
      else
          text = "|" .. trim(getline(line)[: n_max]) .. "..."
      endif
  else
      # If no filetype recognized, just don't show anything.
      text = ""
  endif
  return text
enddef

augroup show_funcname
  autocmd!
  autocmd BufEnter,BufWinEnter,CursorMoved * b:current_function = ShowFuncName()
augroup end

set statusline+=%#StatusLineNC#\%{b:current_function}\ %*
© www.soinside.com 2019 - 2024. All rights reserved.