text objects

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

text objects

Oleksandr Manzyuk-2

Hi!

I have a general question: Is there a way to create custom text
objects in Vim (or to redefine the existing text objects)?

I have switched from Windows to Ubuntu recently. Under Windows, I was
using WinEdt to edit my LaTeX files. It has a nice feature that I miss
in Vim, namely, easy environment selection: the cursor being inside an
environment, you just hit F12 to select the environment (in fact, it
is even more clever: it selects the most inner block of the type (),
[], {}, \(\), \[\], \{\}, \begin{...}\end{...}, so that e.g. if the
cursor is within the word "document" of \begin{document}, then hitting
F12 selects {document}). I think a similar functionality in Vim could
be achieved using text objects. For example, it would be nice to have
something like a text object ae ("an environment") that would behave
similar to the text object at.

Another example: I use gwap to format my paragraphs manually (I don't
like neither to have paragraphs formatted automatically nor to wrap
lines). It would be nice to be able to redefine the ap text object to
make it understand LaTeX syntax (basically, I would like lines
starting with \\, \begin{...}, \end{...}, \[, \], and some other
commands to be treated as paragraph terminators; this would be easy if
the paragraph option could accept regexps).

Are you aware of any plugins that offer a similar functionality? I
have tried matchit.vim, however it doesn't work with LaTeX
environments as I would expect to (a% selects \begin{...}, the body of
an environment, and the first character of \end{...}), so I am
thinking about writing my own plugin, but I am confused: what are text
objects from the point of view of Vim script? Note that I want text
objects to be used both in Visual and Operator-pending mode.

Any help is appreciated!

Regards,
Oleksandr Manzyuk

--~--~---------~--~----~------------~-------~--~----~
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: text objects

Denis Smolyar
On Friday 06 February 2009 22:55:45 Oleksandr Manzyuk wrote:

map <Tab> <Esc>%v%

?

signature.asc (204 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: text objects

Luc Hermitte
In reply to this post by Oleksandr Manzyuk-2

Hello,

"Oleksandr Manzyuk" <[hidden email]> :

> I have a general question: Is there a way to create custom text
> objects in Vim (or to redefine the existing text objects)?

Yes, you will have to define an o-map that plays with visual
selection. I can't tell whether this is a normal behaviour or
just a temporary hack that will stop working eventually.

On vim.wikia, there is a tip that shows how to define such a
mapping.
  http://vim.wikia.com/wiki/Indent_text_object

I've applied it to define a motion that select parameters
(in function calls or definitions).
  http://code.google.com/p/lh-vim/source/browse/cpp/trunk/plugin/omap-param.vim

NB: it requires my vim-library available on the same site.

[...]
> so I am thinking about writing my own plugin, but I am
> confused: what are text objects from the point of view
> of Vim script? Note that I want text objects to be used
> both in Visual and Operator-pending mode.

You will also have to define a separate visual mode mapping.

HTH,

--
Luc Hermitte
http://lh-vim.googlecode.com/
http://hermitte.free.fr/vim/

--~--~---------~--~----~------------~-------~--~----~
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: text objects

Benjamin Fritz



On Feb 7, 5:30 am, Luc Hermitte <[hidden email]> wrote:

> On vim.wikia, there is a tip that shows how to define such a
> mapping.
>  http://vim.wikia.com/wiki/Indent_text_object
>

There's also:

http://vim.wikia.com/wiki/Creating_new_text_objects
--~--~---------~--~----~------------~-------~--~----~
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: text objects

Oleksandr Manzyuk-2

Hi everybody!

Thanks for helpful links on creating text objects. I have the
following issue now. As I described in my previous message, I am after
a text object ae (for "an environment") that would allow to select,
yank, delete, change etc. LaTeX environments. It turned fairly easy
out to code it if you don't want it to work with a count prefix,
namely, I use the following code:

nnoremap [e :<C-U>call
searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','','\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','bW')<CR>
nnoremap ]e :<C-U>call
searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','','\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','W')<CR>

vmap [e <Esc>[em'gv``
vmap ]e <Esc>]em'gv``
vmap ae <Esc>[ev]e

omap [e :normal v[e<CR>
omap ]e :normal v]e<CR>
omap ae :normal vae<CR>

It is transparent and seems to work fine: [e brings you to the
beginning of the environment you are currently in, ]e brings you to
its end (to the last character!), ae selects the environment, and the
operator-pending maps work fine, too. You can use [e and ]e repeatedly
to go up within nested environments, and then I decided I want my maps
work with a counter prefix as well, and to make that happen was more
complicated. The code now looks more cumbersome:

fun ToBeginEnv(count)
    let level = a:count
    let l = line(".")
    let c = col(".")
    while level
        if searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','',
                    \ '\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','bW') < 1
            call cursor(l,c)
            return
        endif
        let level -= 1
    endwhile
endfun

fun ToEndEnv(count)
    let level = a:count
    let l = line(".")
    let c = col(".")
    while level
        if searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','',
                    \ '\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','W') < 1
            call cursor(l,c)
            return
        endif
        let level -= 1
    endwhile
endfun

nnoremap <silent> [e :<C-U>call ToBeginEnv(v:count1)<CR>
nnoremap <silent> ]e :<C-U>call ToEndEnv(v:count1)<CR>

" using the above definitions doesn't work, I suppose because hitting
<Esc> discards the count
" prefix if any
vmap <silent> [e :<C-U>call ToBeginEnv(v:count1)<CR><Esc>m'gv``
vmap <silent> ]e :<C-U>call ToEndEnv(v:count1)<CR><Esc>m'gv``
vmap <silent> ae :<C-U>call ToBeginEnv(v:count1)<CR>v]e

" These seem to work fine...
omap <silent> [e :normal v[e<CR>
omap <silent> ]e :normal v]e<CR>

" ...but this doesn't!
omap <silent> ae :normal vae<CR>

I cannot figure out what is the problem with the last map. It behaves
as follows: if I do, e.g., y2ae, it goes 2 levels up to the beginning
of the environment, but then instead of yanking the piece of text from
that point to the matching end of environment it actually does 2]e,
that is, it goes to the matching end of the environment, and then goes
one more level up. In other words, the count gets substituted in both
(hidden) instances of [e and ]e.

Furthermore, although hitting v2ae in normal mode gives the correct
result, typing :normal v2ae selects only the most inner environment
(instead of going one level up). What is the difference between v2ae
and :normal v2ae?

Any suggestions as to how to fix this? Many thanks in advance to the
whole community! I am relatively new to Vim, but I'd like to say: Vim
rocks!

Regards,
Oleksandr

On Mon, Feb 9, 2009 at 10:12 AM, Ben Fritz <[hidden email]> wrote:

>
>
>
> On Feb 7, 5:30 am, Luc Hermitte <[hidden email]> wrote:
>
>> On vim.wikia, there is a tip that shows how to define such a
>> mapping.
>>  http://vim.wikia.com/wiki/Indent_text_object
>>
>
> There's also:
>
> http://vim.wikia.com/wiki/Creating_new_text_objects
> >
>

--~--~---------~--~----~------------~-------~--~----~
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: text objects

Oleksandr Manzyuk-2
In reply to this post by Benjamin Fritz

Hi everybody!

Thanks for helpful links on creating text objects. I have the
following issue now. As I described in my previous message, I am after
a text object ae (for "an environment") that would allow to select,
yank, delete, change etc. LaTeX environments. It turned fairly easy
out to code it if you don't want it to work with a count prefix,
namely, I use the following code:

nnoremap [e :<C-U>call
searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','','\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','bW')<CR>
nnoremap ]e :<C-U>call
searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','','\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','W')<CR>

vmap [e <Esc>[em'gv``
vmap ]e <Esc>]em'gv``
vmap ae <Esc>[ev]e

omap [e :normal v[e<CR>
omap ]e :normal v]e<CR>
omap ae :normal vae<CR>

It is transparent and seems to work fine: [e brings you to the
beginning of the environment you are currently in, ]e brings you to
its end (to the last character!), ae selects the environment, and the
operator-pending maps work fine, too. You can use [e and ]e repeatedly
to go up within nested environments, and then I decided I want my maps
work with a counter prefix as well, and to make that happen was more
complicated. The code now looks more cumbersome:

fun ToBeginEnv(count)
    let level = a:count
    let l = line(".")
    let c = col(".")
    while level
        if searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','',
                    \ '\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','bW') < 1
            call cursor(l,c)
            return
        endif
        let level -= 1
    endwhile
endfun

fun ToEndEnv(count)
    let level = a:count
    let l = line(".")
    let c = col(".")
    while level
        if searchpair('\\begin{\a\+\*\=}\|\\(\|\\\[','',
                    \ '\\end{\a\+\*\=\zs}\|\\\zs)\|\\\zs]','W') < 1
            call cursor(l,c)
            return
        endif
        let level -= 1
    endwhile
endfun

nnoremap <silent> [e :<C-U>call ToBeginEnv(v:count1)<CR>
nnoremap <silent> ]e :<C-U>call ToEndEnv(v:count1)<CR>

" using the above definitions doesn't work, I suppose because hitting
<Esc> discards the count
" prefix if any
vmap <silent> [e :<C-U>call ToBeginEnv(v:count1)<CR><Esc>m'gv``
vmap <silent> ]e :<C-U>call ToEndEnv(v:count1)<CR><Esc>m'gv``
vmap <silent> ae :<C-U>call ToBeginEnv(v:count1)<CR>v]e

" These seem to work fine...
omap <silent> [e :normal v[e<CR>
omap <silent> ]e :normal v]e<CR>

" ...but this doesn't!
omap <silent> ae :normal vae<CR>

I cannot figure out what is the problem with the last map. It behaves
as follows: if I do, e.g., y2ae, it goes 2 levels up to the beginning
of the environment, but then instead of yanking the piece of text from
that point to the matching end of environment it actually does 2]e,
that is, it goes to the matching end of the environment, and then goes
one more level up. In other words, the count gets substituted in both
(hidden) instances of [e and ]e.

Furthermore, although hitting v2ae in normal mode gives the correct
result, typing :normal v2ae selects only the most inner environment
(instead of going one level up). What is the difference between v2ae
and :normal v2ae?

Any suggestions as to how to fix this? Many thanks in advance to the
whole community! I am relatively new to Vim, but I'd like to say: Vim
rocks!

Regards,
Oleksandr

On Mon, Feb 9, 2009 at 10:12 AM, Ben Fritz <[hidden email]> wrote:

>
>
>
> On Feb 7, 5:30 am, Luc Hermitte <[hidden email]> wrote:
>
>> On vim.wikia, there is a tip that shows how to define such a
>> mapping.
>>  http://vim.wikia.com/wiki/Indent_text_object
>>
>
> There's also:
>
> http://vim.wikia.com/wiki/Creating_new_text_objects
> >
>

--~--~---------~--~----~------------~-------~--~----~
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: text objects

Andy Wokula
In reply to this post by Oleksandr Manzyuk-2

Oleksandr Manzyuk schrieb:

> [...]
> nnoremap <silent> [e :<C-U>call ToBeginEnv(v:count1)<CR>
> nnoremap <silent> ]e :<C-U>call ToEndEnv(v:count1)<CR>
>
> " using the above definitions doesn't work, I suppose because hitting
> <Esc> discards the count
> " prefix if any
> vmap <silent> [e :<C-U>call ToBeginEnv(v:count1)<CR><Esc>m'gv``
> vmap <silent> ]e :<C-U>call ToEndEnv(v:count1)<CR><Esc>m'gv``
> vmap <silent> ae :<C-U>call ToBeginEnv(v:count1)<CR>v]e
>
> " These seem to work fine...
> omap <silent> [e :normal v[e<CR>
> omap <silent> ]e :normal v]e<CR>
>
> " ...but this doesn't!
> omap <silent> ae :normal vae<CR>
>
> I cannot figure out what is the problem with the last map. It behaves
> as follows: if I do, e.g., y2ae, it goes 2 levels up to the beginning
> of the environment, but then instead of yanking the piece of text from
> that point to the matching end of environment it actually does 2]e,
> that is, it goes to the matching end of the environment, and then goes
> one more level up. In other words, the count gets substituted in both
> (hidden) instances of [e and ]e.
>
> Furthermore, although hitting v2ae in normal mode gives the correct
> result, typing :normal v2ae selects only the most inner environment
> (instead of going one level up). What is the difference between v2ae
> and :normal v2ae?
>
> Any suggestions as to how to fix this? Many thanks in advance to the
> whole community! I am relatively new to Vim, but I'd like to say: Vim
> rocks!
>
> Regards,
> Oleksandr

I'm not sure why, but v:count1 is only updated for a count that
has been typed in by the user.  ":normal 2vae" keeps v:count1 at 1.
The same applies for v:count.

--
Andy


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