How to detect where the cursor is?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

How to detect where the cursor is?

Teemu Likonen

I'm doing some personal additions to "mail" filetype plugin. Among some
other things my ~/.vim/after/ftplugin/mail.vim file contains this:

    augroup Mail
        autocmd!
        autocmd! CursorMoved,CursorMovedI <buffer> call <SID>FormatOptions()
    augroup END

    function! s:FormatOptions()
        if getline('.') =~ '\m^\s\{0,3}> '
            setlocal fo-=a fo-=w
        else
            setlocal fo+=aw
        endif
    endfunction

The idea is this: When cursor is on a line which starts with "> " (i.e.,
a mail quotation line) then I want certain settings for 'formatoptions'
('fo'). When cursor is on other lines I want other kind of 'fo'
settings. This already works.

There is one problem. At the beginning of file there are mail headers
such as From, To, Subject etc. Afters headers there is an empty line and
after that the mail body begins. I'd want to detect if the cursor is on
the header area and have different settings applied (at least fo-=a
fo-=w).

So the question is how can I detect if the cursor is on the mail header
area? More generally: how can I detect if the cursor is on certain area in
the buffer? For example, below the line that matches certain pattern and
probably also above the line that matches certain other pattern.

Thanks

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: How to detect where the cursor is?

Ivan Tishchenko

You could use line('.') to get line number, and then getline({lnum}) to
inspect nearby lines.

Also, very nice trick can be done with search().  Like this:
  search('foo \%#bar', 'Wcbn')
will return you positive (>0) value, if the cursor is positioned at
letter 'b' in 'foo bar'.  \%# means 'cursor position'.  And all the
power of vim regexp to help you.  :)

WBR,
Ivan.

> I'm doing some personal additions to "mail" filetype plugin. Among some
> other things my ~/.vim/after/ftplugin/mail.vim file contains this:
>
>     augroup Mail
>         autocmd!
>         autocmd! CursorMoved,CursorMovedI <buffer> call <SID>FormatOptions()
>     augroup END
>
>     function! s:FormatOptions()
>         if getline('.') =~ '\m^\s\{0,3}> '
>             setlocal fo-=a fo-=w
>         else
>             setlocal fo+=aw
>         endif
>     endfunction
>
> The idea is this: When cursor is on a line which starts with "> " (i.e.,
> a mail quotation line) then I want certain settings for 'formatoptions'
> ('fo'). When cursor is on other lines I want other kind of 'fo'
> settings. This already works.
>
> There is one problem. At the beginning of file there are mail headers
> such as From, To, Subject etc. Afters headers there is an empty line and
> after that the mail body begins. I'd want to detect if the cursor is on
> the header area and have different settings applied (at least fo-=a
> fo-=w).
>
> So the question is how can I detect if the cursor is on the mail header
> area? More generally: how can I detect if the cursor is on certain area in
> the buffer? For example, below the line that matches certain pattern and
> probably also above the line that matches certain other pattern.

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: How to detect where the cursor is?

Ivan Tishchenko

Sorry, I've forgotten.

To speed up that trick with search(), use third arg. of search, stopline:
  search('foo \%#bar', 'Wcbn', line('.'))

> You could use line('.') to get line number, and then getline({lnum}) to
> inspect nearby lines.
>
> Also, very nice trick can be done with search().  Like this:
>   search('foo \%#bar', 'Wcbn')
> will return you positive (>0) value, if the cursor is positioned at
> letter 'b' in 'foo bar'.  \%# means 'cursor position'.  And all the
> power of vim regexp to help you.  :)
>  


--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: How to detect where the cursor is?

Cyril Slobin-4
In reply to this post by Teemu Likonen

On 7/24/08, Teemu Likonen <[hidden email]> wrote:

>  So the question is how can I detect if the cursor is on the mail header
>  area? More generally: how can I detect if the cursor is on certain area in
>  the buffer? For example, below the line that matches certain pattern and
>  probably also above the line that matches certain other pattern.

One possible solution: enable syntax highlighting and test for the
syntax type of the character under cursor. Highlighter have already
done a good job of classifying different parts of buffer for you.

--
http://slobin.pp.ru/ `When I use a word,' Humpty Dumpty said,
<[hidden email]> `it means just what I choose it to mean'

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: How to detect where the cursor is?

Teemu Likonen
In reply to this post by Ivan Tishchenko

Ivan Tishchenko wrote (2008-07-24 17:18 +0400):

> You could use line('.') to get line number, and then getline({lnum})
> to inspect nearby lines.
>
> Also, very nice trick can be done with search().  Like this:


Cyril Slobin wrote (2008-07-24 17:23 +0400):

> One possible solution: enable syntax highlighting and test for the
> syntax type of the character under cursor. Highlighter have already
> done a good job of classifying different parts of buffer for you.


Your ideas sound interesting, thank you. I'd like to ask a bit more
concrete examples, though. I'm a Vimscript newbie and neither can
I construct very complex regexp patterns. So how can I answer the
question "is the cursor on the mail header area?"

I'm not asking anybody to write complete script for me but a bit more
concrete examples (and browsing Vim manuals) will probably help me to
find and understand the solution. Thanks for your patience. :)

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: How to detect where the cursor is?

Gary Johnson

On 2008-07-24, Teemu Likonen <[hidden email]> wrote:
> Ivan Tishchenko wrote (2008-07-24 17:18 +0400):

> Cyril Slobin wrote (2008-07-24 17:23 +0400):
>
> > One possible solution: enable syntax highlighting and test for the
> > syntax type of the character under cursor. Highlighter have already
> > done a good job of classifying different parts of buffer for you.
>
>
> Your ideas sound interesting, thank you. I'd like to ask a bit more
> concrete examples, though. I'm a Vimscript newbie and neither can
> I construct very complex regexp patterns. So how can I answer the
> question "is the cursor on the mail header area?"
>
> I'm not asking anybody to write complete script for me but a bit more
> concrete examples (and browsing Vim manuals) will probably help me to
> find and understand the solution. Thanks for your patience. :)

I wrote a similar script a while back.  Here's what I used to
determine the region that the cursor was in:

    let syn_name = synIDattr(synID(line("."), col("."), 1), "name")

    if syn_name =~ "^mailHeader" || syn_name == "mailEmail" || syn_name == "mailSubject"
        let l:msg_part = "header"
        let in_body = 0
    elseif syn_name == "mailSignature"
        let l:msg_part = "signature"
        let in_body = 0
    else
        let l:msg_part = "body"
        let in_body = 1
    endif

I'm not completely happy with the behavior of the rest of the code,
though, so I won't suggest the rest as a solution.

HTH,
Gary


--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: How to detect where the cursor is?

Christian Brabandt
In reply to this post by Teemu Likonen

Hi Teemu!

On Thu, 24 Jul 2008, Teemu Likonen wrote:

> The idea is this: When cursor is on a line which starts with "> " (i.e.,
> a mail quotation line) then I want certain settings for 'formatoptions'
> ('fo'). When cursor is on other lines I want other kind of 'fo'
> settings. This already works.
>
> There is one problem. At the beginning of file there are mail headers
> such as From, To, Subject etc. Afters headers there is an empty line and
> after that the mail body begins. I'd want to detect if the cursor is on
> the header area and have different settings applied (at least fo-=a
> fo-=w).

You could use the information that is provided by the syntax
highlighting. Check the manual for synID() and synIDattr().
In the help for synID() look at the example. You could basically
use this example and check what region the cursor is on.

:h synID()
:h synIDattr()

regards,
Christian
--
:wq

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Different options in different buffer areas

Teemu Likonen
In reply to this post by Teemu Likonen

Teemu Likonen wrote (2008-07-24 16:04 +0300):

> I'm doing some personal additions to "mail" filetype plugin.

Thank you everybody! I tried different things and eventually found
a solution I'm really happy with. Indeed the easiest way is to check
synIDattr() but for special kind of areas I needed my own pattern
matching anyway. I ended up using a custom function everywhere because
there was a certain corner case where synIDattr() was not optimal.

For the sake of contributing back, below is my working prototype. I'll
likely tweak it a bit more in the future but the idea is there. This
detects mail headers, quotation and a diff (---/+++) area -- and, of
course, it sets different options for different areas.

The question "if cursor is on certain area" is answered with function
s:CheckArea(start,end). Both parameters are patterns. The First pattern
should match the first line of the wanted text are; the second should
match the last. The search starts upward from the cursor position and
when constructing patterns you should probably think that you are below
the text area in question. The text area detection can be turned on and
off with \ma1 and \ma0, respectively (\ = <LocalLeader>).

Have fun! :)


PS. Even though this does what I need of course I'm still open to any
    ideas you might have. No doubt there are many who can do this a lot
    better than I.



" ~/.vim/after/ftplugin/mail.vim

let s:defaults = 'setlocal tw=72 ts=8 sts=4 sw=4 fo='.&fo
execute s:defaults

nnoremap <buffer> <LocalLeader>ma1 :call <SID>MailAreaDetect_On()
    \ <bar> echo 'MailAreaDetect On'<CR>
nnoremap <buffer> <LocalLeader>ma0 :call <SID>MailAreaDetect_Off()
    \ <bar> echo 'MailAreaDetect Off'<CR>

function! s:MailAreaDetect_On()
    silent autocmd! MailAreaDetect CursorMoved,CursorMovedI
        \ <buffer> call <SID>AreaOptions()
endfunction

function! s:MailAreaDetect_Off()
    silent autocmd! MailAreaDetect
    execute s:defaults
endfunction

augroup MailAreaDetect
    autocmd!
    call <SID>MailAreaDetect_On()
augroup END

function! s:AreaOptions()
    execute s:defaults
    if <SID>CheckArea('\v^From( |: ).*\n','\v^$')
        "echo 'Header'
        setlocal fo-=a fo-=w fo-=t sts=0 sw=8 noet
    elseif getline('.') =~ '\m^\s*>'
        "echo 'Quotation'
        setlocal fo-=a fo-=w
    elseif <SID>CheckArea('\m^--- .*\n^+++ ','\v(^$|\n^-- $)')
        "echo 'Patch'
        setlocal fo-=a fo-=w fo-=t sts=0 sw=8 noet
    else
        "echo 'My text'
        setlocal fo+=aw et
    endif
endfunction

function! s:CheckArea(start, end)
    return (search(a:start,'bcnW')-line('.')) >
        \ (search(a:end,'bnW')-line('.'))
endfunction

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---