是否可以在文件中的某一行之后更改Vim背景颜色(Ruby类定义中的`private`)?

时间:2017-02-21 13:31:25

标签: vim

我希望能够在Vim中看到我是否在私人"是否有Ruby类定义的一部分。类定义如下所示:

class Foo
  def a_public_method
  end

  private

  def a_private_method
  end
end

是否可以让Vim更改private行的背景颜色以及之后的所有内容?

2 个答案:

答案 0 :(得分:1)

可能的解决方案是:

:call matchadd('Error', '^.*private\_.\{-}\(^end\)\@=')

假设end结束class始终在一行开头(不是一个非常优雅的解决方案)。 您可以使用:hi列出的其他突出显示组,而不是'Error'

答案 1 :(得分:1)

我多年来一直试图在红宝石中标记私人方法,但我总是开始和停止,现在,由于你的问题,我终于有了一个合理工作的想法。所以,谢谢你。

现在,首先,理想解决方案将使用Vim的内置突出显示来扩展ruby的语法文件。我想象这种方法的方法是定义一个以" private"开头的语法区域(:help syn-region)。并以"结束"结束。棘手的一点是"私人"需要使用特定的语法组rubyAccess进行标记,或者它可能只是任何"私有"在一个字符串或评论。 end需要rubyClass,或者它可能不是关闭课程,而是关闭方法defdo

不幸的是,我无法弄清楚如何解决这个问题。我无法找到一种方法来定义从特定组到另一组的语法区域。如果你想学习语法高亮,也许有一天会想出问题的解决方案,这里有ruby的语法高亮:https://github.com/vim-ruby/vim-ruby/blob/f792ee3b2d005660da2e7303e43721ef222d7047/syntax/ruby.vim

现在,那就是说,在我用上面的术语定义问题之后,我意识到我可以找到相关的"私有"和"结束"具有正确语法组的关键字,在保存缓冲区或其他内容时。考虑到你无论如何都要考虑一个明确的命令,这对你来说也许是一个可行的解决方案。

如果您发现更具可读性,我在这里有一个要点:https://gist.github.com/AndrewRadev/d848ad9621b47b4151bbc61ab6c5765f。它需要进入~/.vim/ftplugin/ruby.vim。这里注释了一些注释:

" Define what color the private area will be
hi rubyPrivateArea ctermbg=darkgray

function! s:MarkPrivateArea()
  " Clear out any previous matches
  call clearmatches()

  " Store the current view, in order to restore it later
  let saved_view = winsaveview()

  " start at the last char in the file and wrap for the
  " first search to find match at start of file
  normal! G$
  let flags = "w"
  while search('\<private\>', flags) > 0
    let flags = "W"

    if s:CurrentSyntaxName() !~# "rubyAccess"
      " it's not a real access modifier, keep going
      continue
    endif

    let start_line = line('.')

    " look for the matching "end"
    let saved_position = getpos('.')
    while search('\<end\>', 'W') > 0
      if s:CurrentSyntaxName() !~# "rubyClass"
        " it's not an end that closes a class, keep going
        continue
      endif

      let end_line = line('.') - 1
      call matchadd('rubyPrivateArea', '\%'.start_line.'l\_.*\%'.end_line.'l')
      break
    endwhile

    " restore where we were before we started looking for the "end"
    call setpos('.', saved_position)
  endwhile

  " We're done highlighting, restore the view to what it was
  call winrestview(saved_view)
endfunction

function! s:CurrentSyntaxName()
  return synIDattr(synID(line("."), col("."), 0), "name")
endfunction

augroup rubyPrivateArea
  autocmd!

  " Initial marking
  autocmd BufEnter <buffer> call <SID>MarkPrivateArea()

  " Mark upon writing
  autocmd BufWrite <buffer> call <SID>MarkPrivateArea()

  " Mark when not moving the cursor for 'timeoutlen' time
  autocmd CursorHold <buffer> call <SID>MarkPrivateArea()
augroup END

在高级别:它定义了一个函数s:MarkPrivateArea,用于执行区域的实际搜索和标记。 s:表示它的脚本本地,因此它不会污染全局命名空间。它后来在自动命令中称为<SID>MarkPrivateArea - 它的功能相同。

该函数从文件末尾开始,循环,然后禁止循环,让它覆盖整个文件,只有一次。它寻找&#34;私人&#34;使用正确的语法组,找到下一个&#34; end&#34;关闭一个类,并保存该区域的start_lineend_line。您可以添加或删除- 1,以决定您的&#34;区域&#34;应包括或排除&#34;私人&#34;以及是否应该包含或排除最终的&#34;结束&#34;。

(旁注:为了实现这一目标,您需要进行&#34;昂贵的#34;语法突出显示,但默认情况下应该启用。相关文档:https://github.com/vim-ruby/vim-ruby/blob/f792ee3b2d005660da2e7303e43721ef222d7047/doc/ft-ruby-syntax.txt#L71

最后,开始和结束行组合成一个如下所示的模式:

'\%<start-line>l\_.*\%<end-line>.'l'

请尝试使用:help \%l获取更多信息,但这基本上是一个与文件特定行中的代码匹配的正则表达式模式。 \_..的多行形式。因此,它匹配从起始行到结束行的所有内容。

如果你想改变它,只有def被突出显示,它将如下所示:

call matchadd('rubyPrivateArea', '\%>'.start_line.'l\<def\>\%<'.end_line.'l')

这至少是我要做的事情,但你确实说过你想要标记整个区域。

最后的自动命令在启动时,在写入文件时以及在保持光标一段时间后运行该函数。如果你愿意,你可以删除其中的一些。例如,如果您经常保存,即使没有CursorHold,也可能没问题。

至于文件顶部的rubyPrivateArea突出显示组,有关于如何使用:help highlight-args设置颜色的完整说明。您还可以查看自己喜欢的colorscheme作为示例。