如何垂直移动直到到达非空白字符?


27

在带有缩进代码的非常长的文件中,将光标直接移到光标上方或下方限制缩进的一行文本可能会有所帮助。

(执行此操作的一种方法可能是通过缩进折叠方法,即折叠当前的缩进级别,这会将限定缩进级别的行折叠成仅一个光标jk远离光标。但是,我发现没有缩进折叠的情况能够处理我感兴趣的缩进。)

这是一个示例,光标用下划线标记_(在class Bazz和定义之间的第二个字符列处class Qux),但是假设modules中的段落或行数未知或可变:

module Foo
  # lots of code...
end

module Bar
  class Baz
    # ...
  end

  class Bazz
    # lots of code...
  end
 _
  class Qux
    # ...
  end

  class Quux
    # lots of code...
  end
end

...我怎么能快速导航到omodule Bar光标上方或nend光标下方在最后一行?请注意,垂直列包含空格,但在class定义之间的第二列中也没有字符。


2
相关:“移动与同一缩进下一首/上线”上的Vim提示维基vim.wikia.com/wiki/Move_to_next/...
alxndr

按下g键,然后按方向键可能会避免制表符并
跨行

1
@alxndr链接中的解决方案效果很好,除非在空白空间维护不佳的情况下(例如,随机行仅包含空白空间),而您想忽略空白空间。如果有人担心这种情况,下面的superjer解决方案会更好。
nukeguy

Answers:


9

这个功能怎么样?

function FloatUp()
    while line(".") > 1
                \ && (strlen(getline(".")) < col(".")
                \ || getline(".")[col(".") - 1] =~ '\s')
        norm k
    endwhile
endfunction

您可以nnoremap gU :call FloatUp()<CR>gU代表“向上”),然后使用进行调用gU

这是一个解释:

  • norm k只要while条件成立,代码就会反复向上移动光标(带有)。
  • while如果这不是第一行(line(".") > 1), 则该条件成立
    • 该行太短(可能为空);要么
    • 当前行(getline("."))的,在当前的列字符([col(".") - 1])是空白(=~ '\s',即,匹配的空白图案)。

1
这似乎完美(快速),并且容易修改为FloatDown函数。进入我的.vimrc,谢谢!github.com/alxndr/dotfiles/commit/0e25a302
alxndr

1
刚刚发现,该解决方案在视觉模式下并不完全有效(取决于哪种视觉模式,行为会略有不同,它要么停留在同一位置,要么只移动一行)。关于发生了什么的任何指示?
alxndr

13

我喜欢使用search来搜索这些东西,因为在这种情况下,Vim的正则表达式包含大量可以搜索的东西,例如特定的虚拟列号:

nnoremap cd /\%<C-R>=virtcol(".")<CR>v\S<CR>

nnoremap cu ?\%<C-R>=virtcol(".")<CR>v\S<CR>

用于cd下降和cu上升。我想在这里“上下”。我几乎100%确信这些默认情况下为无操作。或选择您自己的映射。

无论您使用制表符还是空格或同时使用这两者,这都应该起作用。


1
我在解析这些命令时遇到了麻烦。您介意扩展一下吗?
davidlowryduda 2015年

1
/ 要么 ?向下或向上搜索,\%xv限制为搜索虚拟列号“ x”,在这种情况下,“ x”为“ <CR> = virtcol(“。”)<CR>”,它运行virtcol命令并插入光标位于表达式中的虚拟列号,\ S表示任何非空白字符。
乍得

1
感谢您解释乍得。我只是添加在插入模式或命令行模式下的<CR>会获取寄存器的内容。该=寄存器是表达寄存器,它在适当位置计算表达式。非常方便,即使看起来也不奇怪。
superjer 2015年

1
这种方法的一个缺点是,如果将搜索突出显示,则您会发现光标“垂直”列中的所有字符现在都在“列上”或“列下”之后被突出显示。
alxndr

3
如果您想保护现有的搜索,可以:let searchbak=@/<CR>添加和附加:let @/=searchbak<CR>。但是在这一点上,它变得漫长而难以接近,也许应该只是一个功能。
superjer 2015年

7

您可以使用JumpToVerticalOccurrence插件(默认映射到]|[|)。几乎没有其他类似的]V{char}作品f,但都是垂直的。当然,您可以根据需要重新映射它们。


如果你不想使用插件,你可以尝试使用:searchvirtcol(.),如:

:call search('\%' . virtcol('.') . 'v\S', 'bW')

哪里:

  • virtcol('.') 给您当前列
  • \S 代表非空白
  • bW 用于向后搜索

检查:help search以了解更多信息。

为了使其更易于使用,可以对其进行映射,例如:

:map <C-k> :call search('\%' . virtcol('.') . 'v\S', 'bW')<CR>
:map <C-j> :call search('\%' . virtcol('.') . 'v\S', 'W')<CR>

另外,如果你的代码中包含括号,使用%匹配他们(例如之间跳转{}[],等),或使用整段跳跃({}Shift必要时)。


链接/来源:


来自:h search()w手段wrap around the end of the fileW手段don't wrap around the end of the file。但是,为什么您将它们放在一起:map
JairLópez'16

@JairLopez正确,w不应该在那里,因此,我已将其删除,谢谢。可能我对动作键的含义感到困惑。
kenorb '16


2

这并不是您所要的,因为它不是垂直移动,而是相似,快速且可能对您来说足够好的是向后移动两段:{{。这将带您进入之前的行module Bar


2
想象一下,光标和其顶层module行之间没有多少行和/或段落。(特别是,这种情况是在最近我浏览第三方代码长达数千行,具有精确的缩进但没有空行并尝试查找模块定义的外部上下文时出现的。)
alxndr

按段跳是我首选的移动方式,但这不是一个选择:整个文件都是一个“段”。
alxndr


1

我使用自己的插件 为此 move_until_char_changes.vim

我将其映射到 gKgJ

它会跳过当前列中具有相同字符的许多行(而不仅仅是空白),这在日志文件或具有重复字符串的SQL转储中很有用。

默认情况下,它先移动一行,然后再拾取“搜索”字符。

如果您不尝试使用它两次,并且您不在行式或块状的可视模式下,则它可以在可视模式下工作(欢迎修复!)


1

由于我在这里没有找到答案(编辑只是注意到superjer提到了非常相似的内容)。您可以简单地/或?搜索。

例如,您可以像下面这样在第二列中向下搜索非空格字符:

/\%2v\S

细分为:

/    "search downward (use ? for upward movement)
\%2v "for the following char in the 2nd virtual column
\S   "any non white space character

然后,您可以使用常规运算符重复搜索。

有关该主题的更多信息,请参见:help \%c:help \%v

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.