Show function name in status line
Asked Answered
O

9

42

I edit a large C, C++, or Java file, say, about 15000 lines, with pretty long function definitions, say, about 400 lines. When the cursor is in middle of a function definition, it would be cool to see the function name in Vim status line.

When we set :set ls=2 in Vim, we can get the file path (relative to the current directory), line number, etc. It would be really cool if we could see the function name too. Any ideas how to get it?

Currently I use [[ to go to start of the function and Ctrl-O to get back to the line I'm editing.

Oberg answered 29/11, 2012 at 21:13 Comment(5)
What's wrong with your current method?Tu
He wants something quicker and easier... to have that info always displayed.Whidah
What's the point of having it always displayed and updated if he doesn't always look at it?Tu
@Whidah , Yeah i want it displayed always, so that whenever i want to look at it, i can just lookOberg
And that's your right as a Vim user!Whidah
A
16

You can use ctags.vim for this, it will show the current function name in the title or status bar.

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

Adamsun answered 29/11, 2012 at 22:28 Comment(0)
V
21

To show current function name in C programs add following in your 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>

Or if you need the "f" key, just map the function to whatever you like.

Vergos answered 24/4, 2014 at 4:23 Comment(2)
Tried most other options, and for me, this is the best and fastest. No need for ctags updates since my code stream is few hundred files, each is few 10k lines.Morocco
The 'n' flag in search() won't move the cursor, so a shorter version of this with the same functionality would be: fun! ShowFuncName() echohl ModeMsg echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bWn')) echohl None endfun map f :call ShowFuncName() <CR> Reference: run :help search()Glossology
A
16

You can use ctags.vim for this, it will show the current function name in the title or status bar.

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

Adamsun answered 29/11, 2012 at 22:28 Comment(0)
G
11

Based on @manav m-n's answer

The 'n' flag in search() won't move the cursor, so a shorter version of this with the same functionality would be:

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

Reference: run :help search()

Glossology answered 19/1, 2017 at 16:40 Comment(0)
L
2

Having investigated this and the accepted solution, I believe the simplest solution is:

  1. Install Universal Ctags https://ctags.io/

  2. Install Tagbar https://github.com/preservim/tagbar

  3. call tagbar#currenttag() when setting your statusline, e.g. in .vimrc:

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

Note that:

  • Spaces must be slash-escaped in the strings you pass to currenttag()...and it's even different between running the command inside vim and putting it in your .vimrc?? Anyway, spaces can be weird, and they're probably something you want when outputting the function name.

  • It took me some digging but the default statusline is

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

Lynnelynnea answered 2/6, 2021 at 0:14 Comment(0)
H
1

There are several plugins for status line or on-demand with a mapping, e.g.:

Hydantoin answered 30/11, 2012 at 8:17 Comment(0)
O
1

My solution is as follows:

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

I'm actually attempting to match the C/C++/Java allowed names for functions. This generally works for me (including for overloaded operators) but assumes that the opening { is at column 0 on a line by itself.

I just noticed today that it fails if included in a namespace {}, even if otherwise formatted as expected.

Oarlock answered 11/4, 2013 at 18:6 Comment(0)
S
0

I use https://github.com/mgedmin/chelper.vim for this. It doesn't needs a tags file, instead it parses the source code on the fly.

Serve answered 12/1, 2015 at 10:33 Comment(2)
Note this only works for C.Protasis
I've since switched to github.com/mgedmin/taghelper.vim which has support for a small number of other languages.Serve
S
0

Based on @solidak solution (which was already based on another one :)

I wanted to always show the function name in the bottom of the terminal. But I had some problems with very large function which I solved that way:

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
Sansculotte answered 29/5, 2020 at 14:37 Comment(0)
B
0

Based on other's people solutions, here is a Vim9 version, further extended to 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
  endif
  return text
enddef

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

set statusline+=%#StatusLineNC#\%{b:current_function}\ %*
Bolshevism answered 8/1 at 12:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.