vim 中自动 ruby​​ 折叠

发布于 2024-12-07 01:19:49 字数 491 浏览 6 评论 0原文

有没有一种方法可以设置 vim 自动折叠 ruby​​ 源文件,但只在方法级别折叠,而不管它们定义的级别如何?

因此,当我有:时它会折叠,

class MyClass
  def method
    ...
  end
end

而且当我有:时

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

它也会折叠我已经尝试过foldmethod=syntax和各种折叠级别,但它没有考虑定义方法的深度。

另外,我不希望方法内的任何内容被折叠(if 块、each 块等)。

我认为 Foldmethod=expr 将是我最好的选择,但我还没有弄清楚折叠表达式是如何工作的,而且 vim 中的帮助也不是很有启发。

Is there a way that I can setup vim to automatically fold ruby source files, but only fold at the method level regardless of the level that they are defined?

So it will fold when I have:

class MyClass
  def method
    ...
  end
end

but also when I have:

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

I've experimented with foldmethod=syntax and various fold levels but it doesn't take into account the depth where the method is defined.

Also I don't want nothing inside the method to get folded (if blocks, each blocks, etc).

I think foldmethod=expr would be my best bet, but I haven't manage to figure out how fold expressions work, and the help in vim hasn't been very enlightening.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情绪失控 2024-12-14 01:19:50

你可能会有更好的运气,特别是如果你已经有语法突出显示:

这将进入你的 ~/.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/

You may have better luck with this, especially if you already have syntax highlighting:

This would go into your ~/.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

This is also a great VIMcast on folding: http://vimcasts.org/episodes/how-to-fold/

つ可否回来 2024-12-14 01:19:50

对 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 函数,只会折叠 ruby​​ 定义方法:)

享受并祝你有美好的一天!

Made a change to Max Cantor's solution, mine works perfectly, it will fold def methods (including the end keyword) and documentations (=begin =end) blocks regardless of where it is (in a class, or indented)

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

Thanks to Max Cantor for his helper methods to print out syntax info.

Let me explain this line by line:

The most important line would be the second line where it gets the stacks of verious level of syntax element in a line.
So if you have a line like def methodname with whitespace or tabs before it, it will always get the stack at the first non blank character. The problem with Max Cantor's solution is that his code will only print out the lowest syntax element found at the first column of the line, so it will always return something random, elements like "rubyContant" which we don't care about.

So by using match(getline(a:line), '^\s*\zs') we can move our cursor to the column of the first non blank character so we can get a more accurate picture of the stacks. +1 because match is zero-indexed.

And then the rest is similar to the GetSynInfo method where we loop through the stack and match the elements we want, and return 1 so they are all on the same fold level and 0 for the rest.

And that's it, a working folding expr function that will only fold ruby define methods :)

Enjoy and have a nice day!

滥情空心 2024-12-14 01:19:50

我制作了 vim-ruby-fold 插件,用于在 ruby​​ 中进行简单的方法折叠。我希望它能帮助人们。

I made vim-ruby-fold plugin for simple method folding in ruby. I hope it helps people.

别低头,皇冠会掉 2024-12-14 01:19:50

通过使用 zO 命令,您也许能够得到一个也折叠在方法内的解决方案。 zO递归地打开折叠,因此如果您使用它而不是 zo,则就好像方法内没有任何内容被折叠一样。如果您感觉不舒服,也可以将 zo 重新映射到 zO

You might be able to get away with a solution which folds inside a method as well, by using the zO command. zO will recursively open a fold, so if you use it instead of zo, it will be as if nothing inside the method was folded. You could also remap zo to zO if you are feeling squirrely.

书信已泛黄 2024-12-14 01:19:49

我相信您对使用 expr 方法的预感是正确的!

您可以使用该文件的语法结构来临时配置您自己的语法样式折叠。我的 .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 可能会更好,因此与正则表达式匹配的行仅在紧邻折叠方法块时才会折叠。更严格的正则表达式也可以工作。

如果您感觉奇怪,您可以对此进行扩展,并为 rubyClassrubyModule 元素返回单独的折叠级别。

如果您决定走这条路,这里有一些有用的自定义函数我的 .vimrc 用于内省语法元素和突出显示。当映射到键绑定以便快速使用时,它们是最方便的,如下所示:

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

请告诉我这是否适合您!弄清楚这一点很有趣。另外,就其价值而言,虽然 :help 'foldexpr' 的细节很少,但 :help 'fold-expr' 更有帮助,甚至在以下位置有一些示例顶部。

Your hunch about using the expr method, I believe, was correct!

You can use the syntax structure of the file to jury-rig your own syntax-style folding. The following in my .vimrc produced expected behavior:

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)

Some caveats:

I'm not sure if the final argument to synID should be 0 or 1. It's the argument that determines whether you get the syntax information for the topmost transparent or non-transparent element at the provided location. When there's no transparent element, the argument has no effect. In the trivial example I tried, it didn't cause any issues, but it might.

It's also worth noting that the line_is_def regex is probably too lenient. It might be better to return -1 in this situation, so a line matching the regex is only folded when it's right next to the folded method block. A more restrictive regex could also work.

If you're feeling squirrely, you could expand on this and return separate foldlevels for rubyClass and rubyModule elements as well.

If you decide to go down that route, there are some useful custom functions in my .vimrc for introspecting into syntax elements and hilighting. They're handiest when mapped to a keybinding for quick use like so:

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

Please do let me know if this works out for you! It was fun to figure out. Also, for what it's worth, while :help 'foldexpr' is light on details, :help 'fold-expr' is much more helpful, and even has some examples at the top.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文