Подтвердить что ты не робот

Автоматическая рубиновая складка в vim

Есть ли способ, которым я могу настроить vim, чтобы автоматически складывать исходные файлы ruby, но только сбрасывать на уровне метода независимо от уровня, который они определены?

Поэтому он будет складываться, когда у меня есть:

class MyClass
  def method
    ...
  end
end

но также, когда у меня есть:

module FirstModule
  module SecondModule
    class MyClass
      def method
        ...
      end
    end
  end
end

Я экспериментировал с синтаксисом foldmethod = и различными уровнями сгиба, но не учитывал глубину, где определяется метод.

Также я не хочу, чтобы внутри метода не было ничего сложного (если блоки, блоки и т.д.).

Я думаю, что foldmethod = expr будет моей лучшей ставкой, но мне не удастся выяснить, как работают сглаженные выражения, а помощь в vim не очень просвещала.

4b9b3361

Ответ 1

Ваша уверенность в использовании метода expr, я считаю, была правильной!

Вы можете использовать структуру синтаксиса файла для создания присяжных-прикладов вашей собственной syntax -складкой. Следующее в моем .vimrc вызвало ожидаемое поведение:

function! RubyMethodFold(line)
  let line_is_method_or_end = synIDattr(synID(a:line,1,0), 'name') == 'rubyMethodBlock'
  let line_is_def = getline(a:line) =~ '\s*def '
  return line_is_method_or_end || line_is_def
endfunction

set foldexpr=RubyMethodFold(v:lnum)

Некоторые оговорки:

Я не уверен, что конечный аргумент synID должен быть 0 или 1. Это аргумент, определяющий, получать ли синтаксическую информацию для самого верхнего прозрачного или непрозрачного элемента в указанном месте. Когда нет прозрачного элемента, аргумент не действует. В тривиальном примере, который я пробовал, он не вызывал никаких проблем, но он мог бы.

Также стоит отметить, что регулярное выражение line_is_def, вероятно, слишком мягкое. Возможно, было бы лучше возвратить -1 в этой ситуации, поэтому строка, соответствующая регулярному выражению, будет складываться только тогда, когда она находится рядом со слоем сложенного метода. Может также работать более ограничивающее регулярное выражение.

Если вы чувствуете себя безвольно, вы можете расширить его и вернуть отдельные уровни сложения для элементов rubyClass и rubyModule.

Если вы решите пойти по этому маршруту, есть некоторые полезные пользовательские функции в моем .vimrc для интроспекции элементов синтаксиса и hilighting. Они наиболее удобны при сопоставлении клавиш для быстрого использования, например:

nnoremap g<C-h> :echo GetSynInfo()<CR>

Пожалуйста, дайте мне знать, если это сработает для вас! Было здорово разобраться. Кроме того, для того, что стоит, в то время как :help 'foldexpr' освещен в деталях, :help 'fold-expr' гораздо полезнее и даже имеет некоторые примеры в верхней части.

Ответ 2

Сделал изменение в решении Max Cantor, он отлично работает, он будет сворачивать методы def (включая ключевое слово end) и блокировку документов (= begin = end) независимо от того, где он находится (в классе или в отступе)

function! RubyMethodFold(line)
  let stack = synstack(a:line, (match(getline(a:line), '^\s*\zs'))+1)

  for synid in stack
    if GetSynString(GetSynDict(synid)) ==? "rubyMethodBlock" || GetSynString(GetSynDict(synid)) ==? "rubyDefine" || GetSynString(GetSynDict(synid)) ==? "rubyDocumentation"
      return 1
    endif
  endfor

  return 0
endfunction

set foldexpr=RubyMethodFold(v:lnum)

set foldmethod=expr

Благодаря Max Cantor за его вспомогательные методы распечатывают информацию о синтаксисе.

Позвольте мне объяснить эту строку за строкой:

Самая важная строка - это вторая строка, в которой он получает стеки из достоверного уровня элемента синтаксиса в строке. Поэтому, если перед ним есть строка типа def methodname с пробелами или вкладками, она всегда будет получать стек при первом непустом символе. Проблема с решением Max Cantor заключается в том, что его код будет распечатывать только самый младший синтаксический элемент, найденный в первом столбце строки, поэтому он всегда будет возвращать что-то случайное, такие элементы, как "rubyContant", который нам неинтересен.

Таким образом, используя match(getline(a:line), '^\s*\zs'), мы можем переместить наш курсор в столбец первого непустого символа, чтобы мы могли получить более точную картину стеков. +1, потому что совпадение индексируется нулем.

И тогда остальное похоже на метод GetSynInfo, где мы прокручиваем стек и сопоставляем элементы, которые хотим, и возвращаем 1, чтобы все они находились на одном уровне сложения и 0 для остальных.

И что это, работающая функция сгибания expr, которая будет только сбрасывать рубины, определяет методы:)

Наслаждайтесь приятным днем!

Ответ 3

Вам может быть повезло с этим, особенно если у вас уже есть подсветка синтаксиса:

Это пойдет в ваш ~/.vimrc

"" Enable folding based on syntax rules
set foldmethod=syntax

"" Adjust the highlighting
highlight Folded guibg=grey guifg=blue

"" Map folding to Spacebar
nnoremap  za

Это также отличный VIMcast при складывании: http://vimcasts.org/episodes/how-to-fold/

Ответ 4

Вы можете уйти с решением, которое складывается внутри метода, используя команду zO. zO будет рекурсивно открывать складку, поэтому, если вы используете ее вместо zO, это будет так, как будто ничего внутри метода не было сложенным. Вы также можете перенаправить zO в zO, если вы чувствуете себя безвольно.

Ответ 5

Я сделал vim-ruby-fold плагин для простого сложения метода в рубине. Надеюсь, это помогает людям.