History
Article Edit this page Discussion

Show what function the cursor is in

From Vim Tips Wiki

Jump to: navigation, search

[edit] Duplicate tip

This tip is very similar to the following:

These tips need to be merged – see the merge guidelines.

Tip 1454 Previous Next Created: January 1, 2007 Complexity: intermediate Author: Shotaro Aoyama Version: n/a


This is a function to show what C/C++ function/struct/class the cursor is in. I think this method is fast enough for practical use, but it's not complete.

function! GetProtoLine()
  let ret       = ""
  let line_save = line(".")
  let col_save  = col(".")
  let top       = line_save - winline() + 1
  let so_save = &so
  let &so = 0
  let istypedef = 0
  " find closing brace
  let closing_lnum = search('^}','cW')
  if closing_lnum > 0
    if getline(line(".")) =~ '\w\s*;\s*$'
      let istypedef = 1
      let closingline = getline(".")
    endif
    " go to the opening brace
    normal! %
    " if the start position is between the two braces
    if line(".") <= line_save
      if istypedef
        let ret = matchstr(closingline, '\w\+\s*;')
      else
        " find a line contains function name
        let lnum = search('^\w','bcnW')
        if lnum > 0
          let ret = getline(lnum)
        endif
      endif
    endif
  endif
  " restore position and screen line
  exe "normal! " . top . "Gz\<CR>"
  call cursor(line_save, col_save)
  let &so = so_save
  return ret
endfunction

function! WhatFunction()
  if &ft != "c" && &ft != "cpp"
    return ""
  endif
  let proto = GetProtoLine()
  if proto == ""
    return "?"
  endif
  if stridx(proto, '(') > 0
    let ret = matchstr(proto, '\w\+(\@=')
  elseif proto =~# '\<struct\>'
    let ret = matchstr(proto, 'struct\s\+\w\+')
  elseif proto =~# '\<class\>'
    let ret = matchstr(proto, 'class\s\+\w\+')
  else
    let ret = strpart(proto, 0, 15) . "..."
  endif
  return ret
endfunction

" You may want to call WhatFunction in the statusline
set statusline=%f:%{WhatFunction()}\ %m%=\ %l-%v\ %p%%\ %02B

This function works well in the following testcase:

void draw()
{
    // When cursor is here, WhatFunction() shows "draw"
    glClear(GL_COLOR_BUFFER_BIT {{|}} GL_DEPTH_BUFFER_BIT);
}

typedef struct {
    int ident;  // { <- braces in comments are ignored thanks to %. Great!
    int version;    // here it shows "} HEADER"
} HEADER;

# define EX(a, b, c, d)  a
enum CMD_index
#endif
{
EX(CMD_append, "append", ex_append); // here "enum CMD_index..."
};

class Sys {
public:
    load() {
        // NG: here, it shows "Sys" instead of "load"...
    }
};

class Camera : public Object
{
public:
    void init();
};

void Camera::init()
{
    // here WhatFunction shows "init"
}

[edit] Comments

I again had some problems with scrolling. This time, side-to-side scrolling in diff mode (specifically no line wrap). When the text was scrolled left, pressing 'h' or 'l' would act as if I'd pressed 'zh' or 'zl'.

Similar to the previous issue, I solved the problem by storing the value returned from wincol() in a variable, at the beginning of GetProtoLine(). Then at the end of GetProtoLine(), if wincol() is different, I scroll appropriately.

So:

  " restore position and screen line
  exe "normal! " . top . "Gz\<CR>"
  call cursor(line_save, col_save)
  let &so = so_save

Became:

  " restore position and screen line
  exe "normal! " . top . "Gz\<CR>"
  call cursor(line_save, col_save)
  let line_diff = winline() - window_line
  if line_diff > 0
    exe 'normal ' . line_diff . '^E'
  elseif line_diff < 0
    exe 'normal ' . -line_diff . '^Y'
  endif
  let &so = so_save

Calling WhatFunction() in the status line breaks multi-line actions like "2yy" for me, just one line is copied instead of two. Any idea how to fix that?


To use it, simply enter this (perhaps using a mapping) to show the function name:

:echo WhatFunction()

Or use it in the statusline as already mentioned.

The method of finding opening brace can be replaced by the one of script#1628. That's better?


The regexp used to find the function name, assumes that the function name would not have underscores

present code:

let ret = matchstr(proto, '\w\+(\@=')

could be:

let ret = matchstr(proto, '[[:alnum:]_ ]\+(\@=')

Don't forget that you'll have tildes in destructor names.

So:

let ret = matchstr(proto, '[[:alnum:]_ ]\+(\@=')

could be:

let ret = matchstr(proto, '\~\?[[:alnum:]_ ]\+(\@=')

I set this up to show the function name in my statusline. However, when I was diff-ing two different versions of the same file, and odd scrolling behavior occurred... With the cursor on the bottom line of the window, I pressed 'k', and vi acted as if I pressed 'Ctrl-y'.

I solved the problem by storing the value returned from winline() in a variable, at the beginning of GetProtoLine(). Then at the end of GetProtoLine(), if winline() is different, I scroll appropriately.


Rate this article:

Share this article:

Hubs Highlights International Sites Wikia messages
Entertainment
Gaming
Cartoons & Comics
Science Fiction
Hobbies
Sports
See all...
Grand Theft Auto Wiki
Doctor Who
Legend of Zelda Wiki
Terminator Wiki
Everquest II Wiki
Mystery Science Theater 3000
German
Spanish
Chinese
Japanese
More...
Wikia is hiring for several open positions
Send this article to a friend
"Show what function the cursor is in"
 
 
Hi!

I thought you'd like this page from Wikia!

http://vim.wikia.com

Come check it out!
Send confirmation