PatternsOnText : Advanced commands to apply regular expressions.
script karma |
Rating 50/26,
Downloaded by 5853 |
Comments, bugs, improvements
|
Vim wiki
|
created by |
Ingo Karkat |
|
script type |
utility |
|
description |
DESCRIPTION
This plugin provides a toolbox of commands to delete, substitute, or
de-duplicate text based on a passed regular expression (or the last used
search pattern), something which would otherwise require multiple steps, a
complex sub-replace-expression or a macro. One way or the other, all
commands here are extensions of the :substitute command. Use them whenever
the general built-in doesn't suffice.
SOURCE
:DeleteExcept
http://stackoverflow.com/questions/6249172/vim-delete-anything-other-than-pattern
:SubstituteInSearch inspired by
http://stackoverflow.com/questions/13763880/in-vim-how-can-i-search-and-replace-every-other-match
:DeleteDuplicateLinesOf inspired by
http://stackoverflow.com/questions/14236226/hanging-only-to-the-first-instance-of-the-line-and-deleting-all-further-copies
:DeleteDuplicateLinesIgnoring inspired by
http://stackoverflow.com/questions/1896793/remove-duplicate-line-in-vim
:DeleteAllDuplicateLinesIgnoring inspired by
http://stackoverflow.com/questions/22193596/in-vim-how-to-remove-all-lines-that-are-duplicate-somewhere
:SubstituteNotInSearch inspired by
http://stackoverflow.com/questions/26569959/ignore-keywords-in-quotes-in-vim-regex-substitute
:DeleteUniqueLinesIgnoring inspired by
http://stackoverflow.com/questions/26981192/how-do-i-remove-non-duplicate-lines-in-vim
:SubstituteChoices inspired by
http://vi.stackexchange.com/questions/9700/mutliple-choice-substitute
SEE ALSO
- The ExtractMatches.vim plugin (vimscript #4795) provides commands to yank
matches into a register, optionally only unique matches without duplicates.
- The EditSimilar.vim plugin (vimscript #2544) uses the same
{wildcard}={string} replacement pairs of :SubstituteWildcard, but for
editing a similar file, e.g. via :EditSubstitute.
- The ingo#syntaxitem#IsOnSyntax() function provided by ingo-library.vim can
be used with :SubstituteIf as a predicate that checks for the syntax of
the current match. For example, a predicate that detects comments can be
defined as:
function! Comment()
return ingo#syntaxitem#IsOnSyntax(getpos('.'), '^Comment$')
endfunction
RELATED WORKS
- The :SubstituteSelected command can be emulated with built-ins via
:call feedkeys('yyyq') | %s/{pattern}/{string}/gc
(Source: http://stackoverflow.com/a/25840884/813602)
- substitute_unless_string.vim
(https://github.com/LucHermitte/lh-misc/blob/master/plugin/substitute_unless_string.vim)
implements a :SubstituteIf with a fixed predicate (that checks the current
syntax).
USAGE
:[range]SubstituteExcept/{pattern}/{string}/[flags] [count]
Replace text in the current line / [range] that does
not match {pattern} / the last used search pattern
with {string}; "g" is implicit. Empty lines (without
any whitespace) are kept empty.
In {string}, & refers to the text that does not match,
whereas \1 etc. refer to the previous match of a
sub-expression in {pattern}.
:[range]SubstituteExcept [flags] [count]
Repeat the last substitution with the last used search
pattern, last used replacement string, and last used
:s_flags; "g" is implicit.
:[range]DeleteExcept [{pattern}]
:[range]DeleteExcept /{pattern}/[flags]
Delete all text in the current line / [range] except
for the text matching {pattern} / the last used search
pattern. For [flags], see :s_flags; "g" is implicit.
:[range]SubstituteSelected/{pattern}/{string}/[flags] {answers}
Replace matches of {pattern} in the current line /
[range] with {string}, determining whether a
particular match should be replaced on the sequence of
"y" or "n" (a count can be prefixed, e.g. "3y4n2y") or
numeric positions "2,5", or ranges "3-5" in {answers}.
If no numeric positions follow, the last "y" / "n"
sequence repeats for further matches. For example with
"ynn", the first match is replaced, the second and
third are not, the fourth is again replaced, ...
Handles & and \0, \1 .. \9 in {string}, also \=
sub-replace-expression and \r, \n, \t, \b.
:[range]SubstituteSelected [flags] [answers]
Repeat the last substitution with the last used search
pattern, last used replacement string, last used
:s_flags, and last used answers.
:[range]SubstituteSubsequent/{pattern}/{string}/[flags]
Replace all matches of {pattern} on or after the
current cursor position (and in all entire following
lines) in [range] with {string}.
For a "blockwise to end" replacement that is
restricted to positions on and after the current
column in all lines, pass the special flag [b].
:[range]SubstituteSubsequent/{pattern}/{string}/[flags] {answers}
Replace all matches of {pattern} on or after the
current cursor position in [range] with {string},
determining whether a particular match should be
replaced on the sequence of "y" or "n" (a count can be
prefixed, e.g. "3y4n2y") or numeric positions "2,5",
or ranges "3-5" in {answers}, as with
:SubstituteSelected.
:[range]SubstituteSubsequent [flags] [answers]
Repeat the last substitution with the last used search
pattern, last used replacement string, last used
:s_flags, and last used answers.
:SubstituteUnderCursor/{pattern}/{string}/[flags]
Replace a match of {pattern} if the cursor is
(somewhere) on the match. Stuff excluded by /\zs and
/\ze still counts a match.
:SubstituteUnderCursor [flags]
Repeat the last substitution with the last used search
pattern, last used replacement string, and last used
:s_flags.
:[range]SubstituteInSearch/{pattern}/{string}/[flags] [count]
Within the current search pattern matches, replace all
matches of {pattern} with {string}. Shortcut for
:%s//\=substitute(submatch(0), "foo", "bar", "g")/gc
~ is replaced with the {string} of the previous
:Substitute[Not]InSearch.
Handles \= sub-replace-expression in {string}, which
can't be used recursively in the above built-in
:%s//\=...
[flags] and [count] apply to the outer matching of the
last search pattern. The [e] from :s_flags also
suppresses the error message when {pattern} never
matches.
To replace only the first occurrence of {pattern},
pass the special flag [f].
For a case-insensitive substitution, prepend '\c' to
{pattern}.
Does not modify the last search pattern quote/.
:[range]SubstituteInSearch/{search}/{pattern}/{string}/[flags] [count]
Like above, but additionally specifies the {search}
pattern instead of using quote/ (which again isn't
modified).
:[range]SubstituteInSearch [flags] [count]
Repeat last :SubstituteInSearch with same search
{pattern} and substitute {string}, but without the
same flags or given {search} pattern.
:[range]SubstituteNotInSearch/{pattern}/{string}/[flags] [count]
Outside the current search pattern matches, replace
all matches of {pattern} with {string}. Combination of
:SubstituteExcept and :SubstituteInSearch.
~ is replaced with the {string} of the previous
:Substitute[Not]InSearch.
[flags] and [count] apply to the outer matching of the
last search pattern. The [e] from :s_flags also
suppresses the error message when {pattern} never
matches.
To replace only the first occurrence of {pattern},
pass the special flag [f].
For a case-insensitive substitution, prepend '\c' to
{pattern}.
Does not modify the last search pattern quote/.
:[range]SubstituteNotInSearch/{search}/{pattern}/{string}/[flags] [count]
Like above, but additionally specifies the {search}
pattern instead of using quote/ (which again isn't
modified).
:[range]SubstituteNotInSearch [flags] [count]
Repeat last :SubstituteNotInSearch with same search
{pattern} and substitute {string}, but without the
same flags or given {search} pattern.
:[range]SubstituteIf/{pattern}/{string}/[flags] {predicate}
:[range]SubstituteUnless/{pattern}/{string}/[flags] {predicate}
Replace matches of {pattern} in the current line /
[range] with {string} if the expression {predicate}
returns a true (:SubstituteIf) / false
(:SubstituteUnless) value.
Inside {predicate}, you can reference a context object
via v:val. It provides the following information:
matchCount: number of current match of {pattern}
replacementCount: number of actual replacements
done so far, i.e. where
{predicate} was true
It also contains pre-initialized variables for use by
{predicate}. These get cleared by each :SubstituteIf
/ :SubstituteUnless invocation:
n: number / flag (0 / false)
m: number / flag (1 / true)
l: empty List []
d: empty Dictionary {}
s: empty String ""
:[range]SubstituteIf [flags] [predicate]
:[range]SubstituteUnless [flags] [predicate]
Repeat the last substitution with the last used search
pattern, last used replacement string, last used
:s_flags, and last used predicate.
:[range]SubstituteChoices /{pattern}/{string1}/{string2}/[.../] [flags] [count]
Replace a match of {pattern} with one of {string1},
{string2}, ..., with each replacement queried from the
user.
:[range]SubstituteChoices [flags] [count]
Repeat the last substitution with the last used search
pattern, last used replacement choices, last used
:s_flags and count.
:[range]SubstituteMultiple /{pattern}/{string}/ [...] [flags] [count]
Change any of the {pattern} given to the corresponding
{string}. As this is done in a single :substitute,
this can have different (better) semantics than
sequential :s/new/old/ | s/older/newer/ commands. For
example, you can swap texts with this.
Note: You cannot use capturing groups /\( here!
Handles & and \= sub-replace-expression in {string}.
:[range]SubstituteMultiple [flags] [count]
Repeat the last substitution with the last used search
patterns, last used replacement strings, last used
:s_flags and count.
:[range]SubstituteWildcard {wildcard}={string} [...] [flags] [count]
Change (first in the line, with "g" flag all) matches
of wildcard to {string}. Modeled after the Korn
shell's "cd {old} {new}" command.
Handles & and \= sub-replace-expression in {string}.
Whitespace in the substitution pairs must be escaped;
for a literal backslash search / replace, use \\:
C:\\=my\ drive
:[range]SubstituteWildcard [flags] [count]
Repeat the last substitution with the last used search
pattern, last used wildcard replacements, last used
:s_flags and count.
:[range]SubstituteMultipleExpr /{pattern-expr}/{replacement-expr}/ [flags] [count]
Evaluate {pattern-expr}, either as a List of patterns,
or else as String, which is then split into lines of
patterns. Change any of these patterns to the
corresponding (i.e. with the same index, using the
last available if there are fewer replacements
available) List element of {replacement-expr}.
Note: You cannot use capturing groups /\( here!
Each replacement handles & and \=.
:[range]SubstituteMultipleExpr [flags] [count]
Repeat the last substitution with the last used search
and replacement expressions, last used :s_flags and
count.
:[range]SubstituteTransactional /{pattern}/{string}/
[flags][t/{test-expr}/][u/{update-predicate}/]
First record every match of {pattern} without changing
anything.
The optional {test-expr} is invoked at each match
(v:val contains a context Dict Substitute-v:val that
can be used to store additional information. It also
has the matchCount information (but not
replacementCount)). You can skip that match by
throwing "skip".
The optional {update-predicate} is invoked once at the
end (and passed that context object as v:val again,
now also with matchNum information); it has to return
1 or 0; in the latter case, no replacements are done
(the transaction is aborted). In case of 1 (commit),
all recorded positions (in reverse order from last to
first) are replaced with {string}, which handles & and
also \=; with the latter sub-replace-expression, the
cursor is positioned on the match, and can use the
context via v:val, which contains the following
additional information:
matchNum: total number of matches
matchCount: number of current match of {pattern};
decreases from matchNum to 1
matches: List of all recorded matches, index
with matchCount to obtain the current
one
matchText: matched text (as you cannot use
submatch(0) any longer
startPos: [line, col] of the start of the match
endPos: [line, col] of the end of the match
:[range]SubstituteTransactional [flags][t/{test-expr}/][u/{update-predicate}/]
Repeat the last substitution with the last used search
pattern, last used replacement, last used :s_flags
and {test-expr} / {update-predicate} (unless
specified).
:[range]SubstituteTransactionalExpr /{pattern-expr}/{replacement-expr}/
[flags][t/{test-expr}/][u/{update-predicate}/]
Evaluate {pattern-expr}, either as a List of patterns,
or else as String, which is then split into lines of
patterns. First record (the optional {test-expr}, and
a later sub-replace-expression have an additional
patternIndex that shows which pattern matched) and
then at the end change any of these patterns given to
the corresponding (i.e. with the same index, using the
last available if there are fewer replacements
available) List element of {replacement-expr}, like
:SubstituteTransactional.
Note: You cannot use capturing groups /\( here!
:[range]SubstituteTransactionalExpr [flags][t/{test-expr}/][u/{update-predicate}/]
Repeat the last substitution with the last used search
and replacement expressions, last used :s_flags and
{test-expr} / {update-predicate} (unless specified).
:[range]SubstituteTransactionalExprEach /{pattern-expr}/{replacement-expr}/
[flags][t/{test-expr}/][u/{update-predicate}/]
Evaluate {pattern-expr}, either as a List of patterns,
or else as String, which is then split into lines of
patterns. First record (the optional {test-expr}, and
a later sub-replace-expression have an additional
patternIndex that shows which pattern matched) and
then at the end change any of these patterns given to
the corresponding (i.e. with the same index, using the
last available if there are fewer replacements
available) List element of {replacement-expr}, like
:SubstituteTransactional.
In contrast to :SubstituteTransactionalExpr, each
pattern is searched separately, not as alternative
regexp branches (where the first branch matches, and
other potential matches are eclipsed). As the
replacements are only done at the very end, this means
that _any_ pattern match is recorded and later
replaced, not just the first alternative! (And you can
use capturing groups here.)
:[range]SubstituteTransactionalExprEach [flags][t/{test-expr}/][u/{update-predicate}/]
Repeat the last substitution with the last used search
and replacement expressions, last used :s_flags and
{test-expr} / {update-predicate} (unless specified).
:[range]SubstituteRotate /{pattern}[/{shift-value}]/[+-]N/[flags]
:[range]SubstituteRotate /{pattern}[/\={shift-value-expr}]/[+-]N/[flags]
[t/{test-expr}/][u/{update-predicate}/]
Replace every match of {pattern} with the preceding
(+N) / following (-N) one. A given {shift-value} is
used for the first / last match(es) (which are then
put into the default register), and a
{shift-value-expr} can refer to the context via v:val;
else, matches will rotate, and the [+N] first are
taken from behind / the [-N] last are taken from the
front.
For {test-expr} and {update-predicate} see
:SubstituteTransactional.
:[range]SubstituteRotate [flags][t/{test-expr}/][u/{update-predicate}/]
Repeat the last substitution with the last used search
pattern, last used {shift-value} / [+-]N, last used
:s_flags and {test-expr} / {update-predicate}
(unless specified).
:[range]SubstituteRotateMemoized[!] /{pattern}[/{shift-value}]/[+-]N/[flags]
:[range]SubstituteRotateMemoized[!] /{pattern}[/\={shift-value-expr}]/[+-]N/[flags]
[t/{test-expr}/][u/{update-predicate}/]
:[range]SubstituteRotateMemoized[!] [flags][t/{test-expr}/][u/{update-predicate}/]
Replace every match of {pattern} with the preceding
(+N) / following (-N) one, and do the same replacement
for further identical matches (instead of taking a
possibly different neighbor there). Everything else
works like :SubstituteRotate. Useful to make space
in a list of matches in a consistent way. This
persists across invocations (so you can apply the same
rotation on multiple ranges / buffers); use ! to clear
any stored associations and reset the context object.
:[range]SubstituteExecute/{pattern}/[flags] {expr}
Replace matches of {pattern} in the current line /
[range] with whatever {expr} |:return|s.
This is like :sub-replace-expression, but you can
use commands like :let, and have to explicitly
:return the replacement value.
Inside {expr}, you can reference a context object, as
with :SubstituteIf. Cp. Substitute-v:val
:[range]SubstituteExecute [flags] [expr]
Repeat the last substitution with the last used search
pattern, last used :s_flags, and last used
expression.
:[range]SubstituteTranslate[!] /{pattern}/\={expr}/[flags]
Put each unique match of {pattern} through {expr} ...
Inside {expr}, you can reference a context object, as
with :SubstituteIf. Cp. Substitute-v:val; here,
the information is:
matchCount: number of non-memoized match of
{pattern}
replacementCount: number of actual replacements
(memoized and new) done so far
:[range]SubstituteTranslate[!] /{pattern}/{func}/[flags]
Invoke {func} (a context object, as with
:SubstituteIf, cp. Substitute-v:val is the only
argument; the match can be inspected via submatch())
for each unique match ...
:[range]SubstituteTranslate[!] /{pattern}/{item1}/{item2}[/...]/[flags]
Replace each unique match of {pattern} with the
{item1}, ... (from left to right; if these are new
{itemA} or there are additional appended {item3},
those are added to the original ones, unless ! is
given) ...
... and memoize the association, so that further
identical matches will automatically use the same
value (without invoking {expr} / {func} / popping
{item1}). This persists across invocations (so you can
apply the same translation on multiple ranges /
buffers); use ! to clear any stored associations and
reset the context object.
By returning a List, {expr} / {func} can indicate the
the current match should be skipped (this decision
isn't memoized), just like if there are no {item1}
available any longer.
:[range]SubstituteTranslate[!] [flags] [count]
Repeat the last substitution with the last used search
pattern, last used {expr} / {func} / {item1}..., last
used :s_flags and count.
:[line]PutTranslations [{template-expr}]
Put all translations from :SubstituteTranslate after
[line] (default current line), according to
{template-expr}, which can refer to each original
match as v:val.match, the associated replacement as
v:val.replacement, and the (original) number of
translation (which also determines the output order)
as v:val.count. The default template associates the
replacement with the original match:
repl1: match1
repl2: match2
:YankTranslations [x] [{template-expr}]
Yank all translations from :SubstituteTranslate
[into register x], according to {template-expr} (see
above). The default template creates :substitute
commands that undo the translation:
:'[,']substitute/repl1/match1/g
:[range]PrintDuplicateLinesOf[!] [{pattern}]
:[range]PrintDuplicateLinesOf[!] /{pattern}/
Print all occurrences of lines matching (with [!]: not
matching) {pattern} (or the current line, if omitted).
All matching lines are added to the jumplist, so you
can use CTRL-O to revisit the locations.
:[range]DeleteDuplicateLinesOf[!] [{pattern}]
:[range]DeleteDuplicateLinesOf[!] /{pattern}/
Delete all subsequent occurrences of lines matching
(with [!]: not matching) {pattern} (or the current
line, if omitted).
:[range]PrintDuplicateLinesIgnoring[!] [{pattern}]
:[range]PrintDuplicateLinesIgnoring[!] /{pattern}/
Print all occurrences of a line whose text (ignoring
any text matched (with [!]: not matched) by {pattern})
appears multiple times. To ignore empty lines, use a
{pattern} of ^$ (strict) or ^\s*$ (lenient).
All matching lines are added to the jumplist, so you
can use CTRL-O to revisit the locations.
:[range]DeleteDuplicateLinesIgnoring[!] [{pattern}]
:[range]DeleteDuplicateLinesIgnoring[!] /{pattern}/
Delete all subsequent occurrences of a line (ignoring
any text matched (with [!]: not matched) by
{pattern}).
:[range]DeleteAllDuplicateLinesIgnoring[!] [{pattern}]
:[range]DeleteAllDuplicateLinesIgnoring[!] /{pattern}/
Delete all (including the very first) occurrences of a
duplicate line (ignoring any text matched (with [!]:
not matched) by {pattern}).
:[range]PrintUniqueLinesOf[!] [/]{pattern}[/]
Print all unique occurrences of lines matching (with
[!]: not matching) {pattern}. All matching lines are
added to the jumplist, so you can use CTRL-O to
revisit the locations.
:[range]DeleteUniqueLinesOf[!] [/]{pattern}[/]
Delete all unique occurrences of lines matching (with
[!]: not matching) {pattern}. Only duplicate lines are
kept.
:[range]PrintUniqueLinesIgnoring[!] [{pattern}]
:[range]PrintUniqueLinesIgnoring[!] /{pattern}/
Print all lines whose text (ignoring any text matched
(with [!]: not matched) by {pattern}) appears only
once in the buffer / [range].
All matching lines are added to the jumplist, so you
can use CTRL-O to revisit the locations.
:[range]DeleteUniqueLinesIgnoring[!] [{pattern}]
:[range]DeleteUniqueLinesIgnoring[!] /{pattern}/
Delete all unique occurrences of a line (ignoring
any text matched (with [!]: not matched) by
{pattern}). Only duplicate lines are kept.
For the following commands, the [!] suppresses the
error when there are no duplicates.
:[range]PrintUniques[!] [{pattern}]
:[range]PrintUniques[!] /{pattern}/
Print all matches of {pattern} (if omitted: the last
search pattern) that appear only once in the current
line / [range].
To print all unique matches of {pattern} within a
single line, processing a [range] or the entire
buffer, use:
:global/^/PrintUniques! [{pattern}]
:global/^/PrintUniques! /{pattern}/
The [!] suppresses the error when there are no
uniques in a particular line.
:[range]DeleteUniques[!] [{pattern}]
:[range]DeleteUniques[!] /{pattern}/
Delete all unique matches of {pattern} (or the last
search pattern, if omitted). Only duplicate matches
are kept.
:[range]PrintDuplicates[!] [{pattern}]
:[range]PrintDuplicates[!] /{pattern}/
Print all matches of {pattern} (if omitted: the last
search pattern) that appear multiple times in the
current line / [range].
To print all duplicate matches of {pattern} within a
single line, processing a [range] or the entire
buffer, use:
:global/^/PrintDuplicates! [{pattern}]
:global/^/PrintDuplicates! /{pattern}/
The [!] suppresses the error when there are no
duplicates in a particular line.
:[range]DeleteDuplicates[!] [{pattern}]
:[range]DeleteDuplicates[!] /{pattern}/
Delete all subsequent matches of {pattern} (or the
last search pattern, if omitted) except the first.
To delete all non-unique matches, use
:DeleteAllDuplicates instead.
:[range]DeleteAllDuplicates[!] [{pattern}]
:[range]DeleteAllDuplicates[!] /{pattern}/
Delete all non-unique matches of {pattern} (or the last
search pattern, if omitted). To keep the first match,
use :DeleteDuplicates instead.
:[range]DeleteRanges[!] {range} [range] [...] [x]
:[range]YankRanges[!] {range} [range] [...] [x]
Within the entire buffer / passed [range], delete /
yank all lines that fall within {range} (with [!]: do
not fall within) into register [x] (or the unnamed
register). When multiple [range]s are given, each line
is yanked only once (in ascending order).
:[range]PrintRanges[!] {range} [range] [...]
Within the entire buffer / passed [range], print all
lines that fall within {range} (with [!]: do not fall
within).
Each start of a block is added to the jumplist, so
you can use CTRL-O to revisit the locations.
:[range]RangeDo[!] {range} [range] [...] {command}
Within the entire buffer / passed [range], execute the
Ex command {cmd} on each line that falls within
{range} (with [!]: does not fall within). When
multiple [range]s are given, each line is processed
only once (in ascending order).
Note: {command} must be separated by whitespace from
the preceding ranges!
Works like
:global/apples/,/peaches/ {cmd}
but:
- processes each line only once when the ranges are
overlapping
- supports multiple ranges (which are joined) and
inversion with [!]
:[range]Renumber [N][/{pattern}/[{fmt}/]][flags][[*]offset]
Search for decimal numbers / {pattern} with [flags],
and replace each (according to :s_flags with
1, 2, ... / [N], [N] + [offset], ...
(or [N] * [offset])
formatted as {fmt} (cp. printf()).
:[range]Renumber & Continue renumbering with the last used number, same
{pattern}, {fmt}, [flags] and [offset]. Useful with
:global to cover only certain lines. Use
:0Renumber ... to prime the required values, e.g.:
:0Renumber 100 g 10 | global/^#/.Renumber & |
|
install details |
INSTALLATION
The code is hosted in a Git repo at
https://github.com/inkarkat/vim-PatternsOnText
You can use your favorite plugin manager, or "git clone" into a directory used
for Vim packages. Releases are on the "stable" branch, the latest unstable
development snapshot on "master".
This script is also packaged as a vimball. If you have the "gunzip"
decompressor in your PATH, simply edit the *.vmb.gz package in Vim; otherwise,
decompress the archive first, e.g. using WinZip. Inside Vim, install by
sourcing the vimball or via the :UseVimball command.
vim PatternsOnText*.vmb.gz
:so %
To uninstall, use the :RmVimball command.
DEPENDENCIES
- Requires Vim 7.0 or higher.
- Requires the ingo-library.vim plugin (vimscript #4433), version 1.045 or
higher. |
|
script versions (upload new version)
Click on the package to download.
PatternsOnText-2.21.vmb.gz |
2.21 |
2024-11-12 |
7.0 |
Ingo Karkat |
- :SubstituteChoices: CHG: Beep and continue querying on invalid accelerator key or number; only <Esc> or Ctrl-C abort.
- :SubstituteChoices: Show the [part of the] current line with the current match highlighted with IncSearch, and other matches with Search, for a better overview of where we are. Thanks to Vitaly for the suggestion.
- :SubstituteChoices: BUG: 10th, 20th, etc. entry cannot be selected by number if it is the last.
- :SubstituteChoices: BUG: Don't add accelerators for numbers, as those interfere with the by-count selection. *** You need to update to ingo-library (vimscript #4433) version 1.045! *** |
PatternsOnText-2.20.vmb.gz |
2.20 |
2022-06-13 |
7.0 |
Ingo Karkat |
- Adapt: :PutTranslations and :Renumber need to check <count> == -1 instead of <line2> to support current line as well as a lnum of 0 (since Vim 8.1.1241).
- ENH: :SubstituteTransactional* additionally support arbitrary access of matched texts via v:val.matches context.
- ENH: Add :SubstituteRotate[Memoized] for the special case of using :SubstituteTransactional for rotating or shifting matches; i.e. replacing with preceding or following matches to make space for something new. Comes as both a stateless variant and :SubstituteRotateMemoized that keeps the mappings from old match to new, similar to what :SubstituteTranslate does.
- ENH: Add :SubstituteUnderCursor for applying {pattern} only at the cursor position.
- All commands support prepended command modifiers (like :keeppatterns). *** You need to update to ingo-library (vimscript #4433) version 1.043! *** |
PatternsOnText-2.11.vmb.gz |
2.11 |
2019-03-29 |
7.0 |
Ingo Karkat |
- Extract PatternsOnText#Translate#Translate() API function to allow easier creation of custom translation commands without having to reassemble (and then re-parse) the entire command arguments.
- Add :PutTranslations and :YankTranslations companion commands of :SubstituteTranslate.
- ENH: Also support \= |sub-replace-expression| for :SubstituteMultiple and :SubstituteWildcard.
- ENH: Add :SubstituteMultipleExpr variant of :SubstituteMultiple.
- ENH: Add :SubstituteTransactional[Expr[Each]] commands. |
PatternsOnText-2.10.vmb.gz |
2.10 |
2018-10-19 |
7.0 |
Ingo Karkat |
- Add :Renumber command.
- Add :DeleteAllDuplicates command, a variant of :DeleteDuplicates and inverse of :DeleteUniques.
- Minor: Do proper escaping of pattern separators when adding to the search history.
- CHG: Allow inversion of :...LinesOf and :...LinesIgnoring {pattern} via ! (instead of suppressing error message with !) Affects :PrintDuplicateLinesOf, :DeleteDuplicateLinesOf, :PrintDuplicateLinesIgnoring, :DeleteDuplicateLinesIgnoring, :DeleteAllDuplicateLinesIgnoring, :PrintUniqueLinesOf, :DeleteUniqueLinesOf, :PrintUniqueLinesIgnoring, :DeleteUniqueLinesIgnoring
- :SubstituteChoices: FIX: Forgot to update current line number; current line is re-printed on each occurrence.
- :SubstituteChoices: Only rely on 'cursorline' highlighting if the line isn't actually folded.
- :SubstituteChoices: ENH: Include count of match replacements in current line in query.
- :SubstituteChoices: Correctly handle multi-digit entry, leading zeros with /c flag.
- FIX: Many :Substitute... commands did not yet check for read-only or unmodifiable buffer and instead printed an ugly multi-line error.
- :SubstituteChoices: Also offer "no" and "last as ..." choices if the |:s_c| flag is given, to offer feature parity with built-in :substitute.
- Add :SubstituteTranslate command.
- CHG: Escaping of whitespace and backslashes in :SubstituteMultiple is not necessary any longer (but now the full /{pattern}/{string}/ needs to be given; you cannot omit e.g. the trailing /). This parsing better matches the user expectation. :SubstituteWildcard still requires escaping, though. *** You need to update to ingo-library (vimscript #4433) version 1.035! *** |
PatternsOnText-2.01.vmb.gz |
2.01 |
2017-08-15 |
7.0 |
Ingo Karkat |
- Add :SubstituteUnless variant of :SubstituteIf.
- Move PatternsOnText#DefaultReplacementOnPredicate(), PatternsOnText#ReplaceSpecial(), and PatternsOnText#DefaultReplacer() to ingo-library. *** You need to update to ingo-library (vimscript #4433) version 1.032! *** |
PatternsOnText-2.00.vmb.gz |
2.00 |
2016-09-30 |
7.0 |
Ingo Karkat |
- Add :SubstituteChoices command.
- Add :SubstituteIf command.
- Add :SubstituteExecute command.
- ENH: Support recall of previous pairs / substitutions in :SubstituteWildcard / :SubstituteMultiple.
- FIX: Minor: With :SubstituteSelected, Cursor jumps to first line if no substitution at all ("nnnnn"). Initialize l:lastNum to current line. *** You need to update to ingo-library (vimscript #4433) version 1.027! *** |
PatternsOnText-1.51.vmb.gz |
1.51 |
2014-12-23 |
7.0 |
Ingo Karkat |
- Don't set the buffer 'modified' for :PrintDuplicates and :PrintUniques.
- Improve reporting of readonly buffers for :SubstituteExcept, :DeleteExcept, :SubstituteSelected, and :SubstituteSubsequent.
- FIX: Misplaced :continue in s:Collect() safety check; must :return out of factored out function. |
PatternsOnText-1.50.vmb.gz |
1.50 |
2014-11-20 |
7.0 |
Ingo Karkat |
- ENH: Add :PrintUniqueLinesOf, :DeleteUniqueLinesOf, :PrintUniqueLinesIgnoring, :DeleteUniqueLinesIgnoring, :PrintUniques, :DeleteUniques commands that are the opposite of the corresponding :...Duplicate... commands. |
PatternsOnText-1.40.vmb.gz |
1.40 |
2014-10-28 |
7.0 |
Ingo Karkat |
- FIX: :SubstituteSubsequent can give "E488: Trailing characters". Previous search pattern must be properly escaped in case the separators are different.
- Add :SubstituteNotInSearch, a combination of :SubstituteExcept and :SubstituteInSearch. |
PatternsOnText-1.36.vmb.gz |
1.36 |
2014-10-26 |
7.0 |
Ingo Karkat |
- BUG: :.DeleteRange et al. don't work correctly on a closed fold; need to use ingo#range#NetStart().
- BUG: :.DeleteDuplicateLines... et al. don't work correctly on a closed fold; need to use ingo#range#NetStart().
- BUG: :SubstituteSubsequent doesn't work correctly on a closed fold; need to use ingo#range#NetStart().
- Make the deletions work with closed folds (i.e. only delete the duplicate lines / lines in range itself, not the entire folds) by temporarily disabling folding.
- Correctly report :PrintDuplicates on folded lines.
- Refactoring: Use ingo#cmdargs#pattern#ParseUnescaped().
- Factor out ingo#range#lines#Get() into ingo-library. *** You need to update to ingo-library (vimscript #4433) version 1.022! *** |
PatternsOnText-1.35.vmb.gz |
1.35 |
2014-04-25 |
7.0 |
Ingo Karkat |
- ENH: Allow to pass multiple ranges to the :*Ranges commands.
- FIX: The *Ranges commands only handled /{pattern}/,... ranges, not line numbers or marks. Only use :global for patterns; for everything else, there's only a single range, so we can just prepend it to :call directly.
- Don't clobber the search history with the :*Ranges commands (through using :global).
- Add :RangeDo command.
- ENH: Also support passing the search pattern inline with :SubstituteInSearch/{search}/{pattern}/{string}/[flags] instead of using the last search pattern. |
PatternsOnText-1.30.vmb.gz |
1.30 |
2014-03-13 |
7.0 |
Ingo Karkat |
- Add :DeleteAllDuplicateLinesIgnoring command.
- CHG: The :[Print|Delete]DuplicateLines[ Of|Ignoring] commands do not automatically ignore empty lines any more. Use a {pattern} like ^$ to ignore them explicitly.
- FIX: Wrong use of ingo#escape#Unescape().
- ENH: Enable use of \= sub-replace-expression in :SubstituteInSearch through emulation, as the command implementation itself uses \=, Vim doesn't allow recursive use inside it. This has been inspired by http://stackoverflow.com/questions/21588649/increment-numbers-between-delimiters-in-vim
- Add :DeleteRanges, :YankRanges, :PrintRanges commands.
- Handle \r, \n, \t, \b in {string}, too. *** You need to update to ingo-library (vimscript #4433) version 1.017! *** |
PatternsOnText-1.20.vmb.gz |
1.20 |
2014-02-18 |
7.0 |
Ingo Karkat |
- ENH: Add :SubstituteWildcard {wildcard}={string} and :SubstituteMultiple /{pattern}/{string}/ commands. *** You need to update to ingo-library (vimscript #4433) version 1.016! *** |
PatternsOnText-1.12.vmb.gz |
1.12 |
2013-11-21 |
7.0 |
Ingo Karkat |
- FIX: Use of \v and \V magicness atoms in the pattern for :DeleteExcept and :SubstituteExcept cause errors like "E54: Unmatched (" and "E486: Pattern not found". Revert to the default 'magic' mode after each pattern insertion to the workhorse regular expression.
- FIX: Abort :DeleteExcept / :SubstituteExcept commands when the pattern contains the set start / end match patterns \zs / \ze, as these interfere with the internal implemenation.
- Minor: Make substitute() and matchlist() robust against 'ignorecase'. |
PatternsOnText-1.11.vmb.gz |
1.11 |
2013-06-13 |
7.0 |
Ingo Karkat |
- FIX: Remove -bar from all commands to correctly handle patterns like foo\|bar without escaping as foo\\|bar.
- :SubstituteSelected now positions the cursor on the line where the last selected replacement happened, to behave like :substitute. |
PatternsOnText-1.10.vmb.gz |
1.10 |
2013-06-06 |
7.0 |
Ingo Karkat |
- ENH: :SubstituteSelected handles count before "y" and "n" answers, numeric positions "2,5", and ranges "3-5".
- Also recall previous answers in a bare :SubstituteSelected command.
- The commands that take a {pattern}, i.e. :SubstituteExcept, :DeleteExcept, :SubstituteSelected now consistently set that as the last search pattern.
- Refactoring: Move functions from ingo/cmdargs.vim to ingo/cmdargs/pattern.vim and ingo/cmdargs/substitute.vim. *** You need to update to ingo-library (vimscript #4433) version 1.007! *** |
PatternsOnText-1.01.vmb.gz |
1.01 |
2013-05-30 |
7.0 |
Ingo Karkat |
Implement abort on error for :SubstituteExcept, :DeleteExcept, :SubstituteSelected, and :SubstituteInSearch, too. |
PatternsOnText-1.00.vmb.gz |
1.00 |
2013-05-29 |
7.0 |
Ingo Karkat |
Initial upload |
ip used for rating: 18.97.9.175
|