2013-09-13 2 views
1

Я работаю над небольшой платформой тестирования для плагинов vim и пытаюсь реализовать функцию, которая вызывает определенную пользователем функцию, и проверяет, вызывает ли функция при необходимости исключения. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу заставить предложение catch vim принять строку, переданную функции тестирования.Переменная интерполяция в выводе Vimscript catch

Вот упрощенная версия того, что я хотел бы.

function! TestException(fx, arguments, exception) 
    let Fx = function(a:fx) 
    try 
     call call(Fx, a:arguments) 
    catch a:exception   " Here's the problem line 
     return 1 
    endtry 
    return 0 
endfunction 

Эта функция отлично работает, если я жесткий код исключение в пункте улова

catch /E740/
или любой другой, но это не интерполировать передаваемая в переменной. Я попытался выполнить весь блок в строке «execute», но это тоже не работает.

До сих пор я опубликовал эту проблему и разрешил ей исключить любое исключение и доверять вызывающему абоненту, чтобы понять ограничение такого общего теста.

Итак, кто-нибудь знает, как это исправить, или кто-нибудь знает способ выяснить, какое исключение было выбрано после его заражения, чтобы я мог сравнить это с аргументом после факта?

+3

Вы можете «поймать» все исключения, а затем сравнить «v: exception» с «a: exception», чтобы определить, соответствует ли тип. Ваш '/ E740 /' является регулярным выражением, возможно, подстрокой полного исключения.Если вы превратите 'a: exception' в регулярное выражение (или интерполируете его в одно), это может быть лучшим решением, но я не могу заставить его работать самостоятельно. –

+0

Если ваше намерение - это тестовая среда для Vim, вы должны проверить [RunVimTests плагин] (http://www.vim.org/scripts/script.php?script_id=2565), который работает очень хорошо. – mMontu

ответ

2

Зачем использовать match()? Оператор =~#. Также отмечу, что

  1. a:exception не должен быть просто E470: это может быть выброшено пользователем. Он должен быть ^Vim\%((\a\+)\)\=:E470 (регулярное выражение взято из :h :catch).
  2. Вы не можете :throwVim(call):E107: Missing parenthesis: abc. :execute действительно лучше в этом случае:

    function TestException(fx, arguments, exception) 
        let d={} 
        " XXX You must not ever use plain variables for holding 
        "  function references because for every possible 
        "  variable name it is possible to construct 
        "   function Fx() 
        "   endfunction 
        "  definition that will prevent you from using this 
        "  variable. 
        let d.Fx=function(a:fx) 
        " Also note that for call() there is exactly no need in 
        " using function references, call() accepts function names 
        " as well. Thus I construct function reference above just 
        " to write the above comment, but use a:fx in call() call 
        " below. 
        execute "try" 
         \."\n call call(a:fx, a:arguments, {})" 
         \."\n let r=0" 
         \."\n catch /".a:exception."/" 
         \."\n let r=1" 
         \."\n endtry" 
        return r 
    endfunction 
    
  3. Примечание о ссылках на функции выше. Что произойдет, если у вас есть функция Fx is E705: Variable name conflicts with existing function: Fx.
  4. Примечание относительно call() приведенных выше аргументов. Если вы удалите function(), вы также можете передать TestException функции функции. И если вы добавляете третий аргумент (какой-то словарь, я обычно использую пустой, эти функции могут или не могут фактически использовать переменную self, но в любом случае требуется третий аргумент), это также позволит анонимным функциям, не делая никаких различий для не-анонимных, -dictionary вызовы функций.
  5. Обратите внимание: return r и let r=…: Я предполагаю, что это ошибка, которую вы обнаружили при создании обходного пути (если я обертываю этот блок, сохраняя возвращаемые значения, я всегда получаю нуль). Он также работает, если я заменю let r=… на return … (обратите внимание, что return 0 будет находиться внутри блока :try, а не за его пределами), но одна точка выхода выглядит лучше.
+0

Я сообщил о проблеме, описанной в 5. vim-dev: https://groups.google.com/forum/#!topic/vim_dev/RMoXuHfYB5g. – ZyX

+0

Спасибо за помощь, я включил большинство из того, что вы предлагаете в мою функцию, но я хотел обратиться к каждой точке. 1./E740/был просто примером того, как я мог заставить старую версию работать, я полностью согласен с тем, что следует использовать лучшее регулярное выражение для исключений. 2. С вашим блоком try, теперь мне даже не нужно беспокоиться об этом. 3 и 4. Отличные моменты и довольно надзор с моей стороны. Я полностью устранил необходимость в funcref. 5. Также хороший момент, но версия, которую я опубликовала, была упрощена, и я серьезно не планировал возвращать средний улов. Наконец, забыли о = ~ #. – Kevin

0

Джим Стюарт, это идеальное решение. Теперь у меня есть что-то вроде


function! TestException(fx, arguments, exception) 
    let Fx = function(a:fx) 
    try 
     call call(Fx, a:arguments) 
    catch 
     if match(v:exception, a:exception) >= 0 
      return 1 
     else 
      throw v:exception 
     endif 
    endtry 
    return 0 
endfunction 

Vim не нравится, когда вы бросаете Vim исключения вручную, но она по-прежнему позволяет пользователю узнать, когда был брошен другое исключение, чем ожидает. Не могу поверить, что я не заметил v: исключение.

Смежные вопросы