Отбрасывание счетчика в сопоставлениях ‹expr›

For example, I have the following expression mapping:

    function! DelNthSpace()
        let col=match(getline('.'), '[[:blank:] ]', col('.'), v:count1)
        return virtcol([line('.'), col+1])."|s \e"
    endfunction
    nnoremap  s DelNthSpace()
You see, v:count1 is already handled here. But if I try to replace second space with such function that is located, for example, at virtual column 35 (it will be if you place cursor on the return statement), then this tries to go to column 235 and replace it because this will be transformed from 2s to 2{DelNthSpace()} -> 235|s ^[. Now I am prepending bare useless | at the start of return statement which consumes unneeded count, but I do not like this solution as it uses two movements instead of one.

ОБНОВЛЕНИЕ: я должен был предоставить больше контекста:

function! ToNthSpace()
    let col=match(getline('.'), '[[:blank:] ]', col('.'), v:count1)
    return virtcol([line('.'), col+1])."|"
endfunction
noremap <expr> s ToNthSpace()

Существует множество функций, которые их используют, одна имитирует команду замены, но транслитерирует ее аргумент (так, при вызове r$ii символ заменяется на $ и вставляется i, \tr$ii заменяет символ на , такое же отношение между t и \tt и некоторыми другие), другие являются движениями. Поскольку эти функции определяют движения, я не могу использовать :<C-u>, он выйдет из визуального режима (или мне придется добавить хак, который скажет, из какого режима была вызвана функция). Я не знаю этого хака и не могу определить разные отображения для обычного и визуального режимов.


person ZyX    schedule 23.11.2010    source источник
comment
Я голосую за, потому что заголовок спрашивает, что мне нужно самому, но мне трудно понять текст, мне не ясно, нужно ли указывать все детали очень специального приложения.   -  person Alexey    schedule 03.03.2015
comment
У меня есть связанный с этим вопрос: если вы ввели счетчик в Vim, например, в визуальном режиме, но потом решили, что счет был неправильным или ненужным, как вы можете отменить счет, не выходя из визуального режима?   -  person Alexey    schedule 03.03.2015
comment
@Alexey Кажется, вы сами ответили на свой вопрос: @_ работает для этого. Я не знаю способа сделать это в режиме ожидания оператора (и я действительно не знал о @_).   -  person ZyX    schedule 03.03.2015


Ответы (2)


Невозможно заставить vim игнорировать счетчик для сопоставления <expr>, однако вы можете легко изменить свое сопоставление, чтобы ваша функция работала:

nnoremap s :<C-U>exe 'normal!' DelNthSpace()<CR>

См. :help v:count для получения информации об использовании CTRL+U для удаления счетчика.

person too much php    schedule 24.11.2010
comment
Нет, я не могу. 1. DelNthSpace на самом деле является функцией, которая использует getchar(), и она может случайно перехватывать части следующей команды, normal! отбрасывает их. 2. Я использую самописный плагин для определения отображений, он не позволяет ничего, кроме сопоставлений выражений, и я не буду его переписывать. Но вы как-то указали мне на решение (не работает движение в визуальном режиме, поэтому его выбросили) (вернуть ":\<C-u>normal! ".vcol."|\n".":\<C-u>call feedkeys(".substitute(string(nextcmd), '\n', '''."\<CR>".''', 'g').")\n". Подождем, может кто найдет решение получше. - person ZyX; 24.11.2010
comment
Я нашел пару способов заставить Vim игнорировать [count] в обычном режиме: нажмите <Esc> или @_. Второй (@_) также работает в визуальном режиме. Интересно, есть ли способ игнорировать [count] в режиме ожидания оператора. - person Alexey; 03.03.2015
comment
@ Алексей Я нашел твой способ особенно полезным. Это следует принять как ответ. Мне также нужен способ отменить подсчет в omap. Но <Esc> отменит всю операцию. - person doraemon; 05.11.2018
comment
@ Алексей, я нашел слово, которое вместо этого возвращает printf(':normal %s', rv). Это работает, когда выражение, которое вы хотите вернуть (например, rv), указывает позицию курсора - person doraemon; 07.11.2018

Подводя итог тому, что упоминает @Alexey, а также мой тест в режиме operator-pending, вы можете сделать следующее

nnoremap <expr> s "@_" . ToNthSpace()
vnoremap <expr> s "@_" . ToNthSpace()
onoremap <expr> s printf(":normal %s\<cr>", ToNthSpace())

Тогда 2, уже введенный в вашем примере, не будет иметь никакого эффекта.

person doraemon    schedule 07.11.2018