aboutsummaryrefslogtreecommitdiff
path: root/autoload
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-08-04 13:16:12 -0600
committerJosh Rahm <rahm@google.com>2022-08-04 13:16:12 -0600
commit3340b11176d467961ae8426091d53c6ad1a01d2c (patch)
tree49b7d8772081265088e69e7d7d50b747769418b0 /autoload
parent6f7c03150b25c2895c852e5068d8c890246ba231 (diff)
downloadfieldmarshal.vim-3340b11176d467961ae8426091d53c6ad1a01d2c.tar.gz
fieldmarshal.vim-3340b11176d467961ae8426091d53c6ad1a01d2c.tar.bz2
fieldmarshal.vim-3340b11176d467961ae8426091d53c6ad1a01d2c.zip
Add Fall.vim
Diffstat (limited to 'autoload')
-rw-r--r--autoload/fall.vim80
1 files changed, 80 insertions, 0 deletions
diff --git a/autoload/fall.vim b/autoload/fall.vim
new file mode 100644
index 0000000..493ded3
--- /dev/null
+++ b/autoload/fall.vim
@@ -0,0 +1,80 @@
+" Falling motions for Vim. "Falling" means moving the cursor down until it hits
+" text that doesn't match a pattern.
+
+" Returns an expression to be used in normal mode that results in the falling
+" motion. The semantics are as follows:
+"
+" The motion moves in the direction given by a:dir (which must be 'j' or 'k').
+" The motion moves while the character under the cursor does not match the
+" pattern, then it moves while the character under the cursor matches the
+" pattern stopping when the character under the cursor does not match the
+" pattern once again.
+"
+" ex.
+"
+" fall#fall('j', '^\s*$')
+"
+" for
+"
+" | t⌷is is some text
+" | this is some other text
+" |
+" |
+" | this is some bottom text
+" | this is some other bottom text
+"
+" will return an expression to update the cursor position to:
+"
+" | this is some text
+" | this is some other text
+" |
+" |
+" | t⌷is is some bottom text
+" | this is some other bottom text
+"
+" This works pretty well for navigating around languages that use indentation
+" and lack braces for bodies, i.e. vimscript, ruby. Less well for python, but
+" still okay.
+function! fall#fall(dir, pattern) abort
+ let i = 0
+ let n = 0
+
+ if a:dir == 'j'
+ let delta = 1
+ else
+ let delta = -1
+ endif
+
+ let line = line('.')
+ let column = col('.')
+ let c = v:count
+ if c == 0
+ let c = 1
+ endif
+
+ while i < c
+ let match = matchstr(getline(line), '\%' . column . 'c.')
+
+ while ! (match =~ a:pattern)
+ let n += 1
+ let line += delta
+ if line <= 0 || line >= line('$')
+ return "m'" . n . a:dir
+ endif
+ let match = matchstr(getline(line), '\%' . column . 'c.')
+ endwhile
+
+ while (match =~ a:pattern)
+ let n += 1
+ let line += delta
+ if line <= 0 || line >= line('$')
+ return "m'" . n . a:dir
+ endif
+ let match = matchstr(getline(line), '\%' . column . 'c.')
+ endwhile
+
+ let i += 1
+ endwhile
+
+ return "m'" . n . a:dir
+endfunction!