~martanne/devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
4 2

[PATCH v3 0/3] add vis-selection-new-match-all

Evan Gates
Details
Message ID
<20200925154016.26202-1-evan.gates@gmail.com>
DKIM signature
pass
Download raw message
Changes in v3:
- remove useless variable leftover from refactor
- change unecessary goto to break

Changes in v2:
- literal next/prev funcs in text-objects.c and separate commit
- don't change view/primary selection when matching all

Evan Gates (3):
  vis: add text_object_literal_find_next/prev
  vis: refactor selections_match_next
  vis: add vis-selection-new-match-all

 config.def.h   |  1 +
 main.c         | 77 ++++++++++++++++++++++----------------------------
 man/vis.1      |  3 ++
 text-objects.c | 20 +++++++++++++
 text-objects.h |  3 ++
 5 files changed, 61 insertions(+), 43 deletions(-)

-- 
2.28.0

[PATCH v3 1/3] vis: add text_object_literal_find_next/prev

Evan Gates
Details
Message ID
<20200925154016.26202-2-evan.gates@gmail.com>
In-Reply-To
<20200925154016.26202-1-evan.gates@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +23 -0
Add two new text-object functions to search forwards/backwards
for a string literal (not a regex) with the same signature as
text_object_word_find_next/prev.  This allows them to be used
interchangeably with the word based variant through function pointers.
---
 text-objects.c | 20 ++++++++++++++++++++
 text-objects.h |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/text-objects.c b/text-objects.c
index fb5adc2..240304b 100644
--- a/text-objects.c
+++ b/text-objects.c
@@ -137,6 +137,26 @@ Filerange text_object_word_find_prev(Text *txt, size_t pos, const char *word) {
	}
}

static Filerange text_object_literal_find(
	Text *txt, size_t pos, const char *search,
	size_t (*text_find)(Text *, size_t, const char *)
) {
	size_t start = text_find(txt, pos, search);
	if (start == pos)
		return text_range_empty();

	size_t len = strlen(search);
	return text_range_new(start, start+len);
}

Filerange text_object_literal_find_next(Text *txt, size_t pos, const char *search) {
	return text_object_literal_find(txt, pos, search, text_find_next);
}

Filerange text_object_literal_find_prev(Text *txt, size_t pos, const char *search) {
	return text_object_literal_find(txt, pos, search, text_find_prev);
}

Filerange text_object_line(Text *txt, size_t pos) {
	Filerange r;
	r.start = text_line_begin(txt, pos);
diff --git a/text-objects.h b/text-objects.h
index abab46e..734bf8c 100644
--- a/text-objects.h
+++ b/text-objects.h
@@ -19,6 +19,9 @@ Filerange text_object_word_outer(Text*, size_t pos);
/* find next occurance of `word' (as word not substring) in forward/backward direction */
Filerange text_object_word_find_next(Text*, size_t pos, const char *word);
Filerange text_object_word_find_prev(Text*, size_t pos, const char *word);
/* find next occurance of a literal string (not regex) in forward/backward direction */
Filerange text_object_literal_find_next(Text *txt, size_t pos, const char *search);
Filerange text_object_literal_find_prev(Text *txt, size_t pos, const char *search);
/* same semantics as above but for a longword (i.e. delimited by white spaces) */
Filerange text_object_longword(Text*, size_t pos);
Filerange text_object_longword_outer(Text*, size_t pos);
-- 
2.28.0

[PATCH v3 2/3] vis: refactor selections_match_next

Evan Gates
Details
Message ID
<20200925154016.26202-3-evan.gates@gmail.com>
In-Reply-To
<20200925154016.26202-1-evan.gates@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +8 -35
A lot of code from selections_match_next was
duplicated in selections_match_next_literal.  Use the new
text_object_literal_find_next/prev functions to combine the two match_next
functions into one.
---
 main.c | 43 ++++++++-----------------------------------
 1 file changed, 8 insertions(+), 35 deletions(-)

diff --git a/main.c b/main.c
index eb855ae..13ce71f 100644
--- a/main.c
+++ b/main.c
@@ -1337,37 +1337,6 @@ static const Selection *selection_new_primary(View *view, Filerange *r) {
	return s;
}

static const char *selections_match_next_literal(Vis *vis, const char *keys, const Arg *arg) {
	Text *txt = vis_text(vis);
	View *view = vis_view(vis);
	Selection *s = view_selections_primary_get(view);
	Filerange sel = view_selections_get(s);
	size_t len = text_range_size(&sel);
	if (!len)
		return keys;

	char *buf = text_bytes_alloc0(txt, sel.start, len);
	if (!buf)
		return keys;

	size_t start = text_find_next(txt, sel.end, buf);
	Filerange match = text_range_new(start, start+len);
	if (start != sel.end && selection_new_primary(view, &match))
		goto out;

	sel = view_selections_get(view_selections(view));
	start = text_find_prev(txt, sel.start, buf);
	if (start == sel.start)
		goto out;

	match = text_range_new(start, start+len);
	selection_new_primary(view, &match);

out:
	free(buf);
	return keys;
}

static const char *selections_match_next(Vis *vis, const char *keys, const Arg *arg) {
	Text *txt = vis_text(vis);
	View *view = vis_view(vis);
@@ -1383,19 +1352,23 @@ static const char *selections_match_next(Vis *vis, const char *keys, const Arg *
		match_word = text_range_equal(&sel, &word);
	}

	if (!match_word)
		return selections_match_next_literal(vis, keys, arg);
	Filerange (*find_next)(Text *, size_t, const char *) = text_object_word_find_next;
	Filerange (*find_prev)(Text *, size_t, const char *) = text_object_word_find_prev;
	if (!match_word) {
		find_next = text_object_literal_find_next;
		find_prev = text_object_literal_find_prev;
	}

	char *buf = text_bytes_alloc0(txt, sel.start, text_range_size(&sel));
	if (!buf)
		return keys;

	Filerange word = text_object_word_find_next(txt, sel.end, buf);
	Filerange word = find_next(txt, sel.end, buf);
	if (text_range_valid(&word) && selection_new_primary(view, &word))
		goto out;

	sel = view_selections_get(view_selections(view));
	word = text_object_word_find_prev(txt, sel.start, buf);
	word = find_prev(txt, sel.start, buf);
	if (!text_range_valid(&word))
		goto out;
	selection_new_primary(view, &word);
-- 
2.28.0

[PATCH v3 3/3] vis: add vis-selection-new-match-all

Evan Gates
Details
Message ID
<20200925154016.26202-4-evan.gates@gmail.com>
In-Reply-To
<20200925154016.26202-1-evan.gates@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +32 -10
Add new vis-selection-new-match-all command, default keybinding <C-a>
in visual mode.  Refactor selections_next_match to find all matches if
arg.b is true.  This does not affect existing configs as arg.b defaults
to false.
---
 config.def.h |  1 +
 main.c       | 38 ++++++++++++++++++++++++++++----------
 man/vis.1    |  3 +++
 3 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/config.def.h b/config.def.h
index 6a4555e..61b97b3 100644
--- a/config.def.h
+++ b/config.def.h
@@ -243,6 +243,7 @@ static const KeyBinding bindings_visual[] = {
	{ "+",                  ACTION(SELECTIONS_ROTATE_RIGHT)             },
	{ "<",                  ALIAS("<vis-operator-shift-left>gv")        },
	{ ">",                  ALIAS("<vis-operator-shift-right>gv")       },
	{ "<C-a>",              ACTION(SELECTIONS_NEW_MATCH_ALL)            },
	{ "<C-b>",              ALIAS("<PageUp>")                           },
	{ "<C-c>",              ACTION(SELECTIONS_REMOVE_COLUMN)            },
	{ "<C-d>",              ACTION(SELECTIONS_NEXT)                     },
diff --git a/main.c b/main.c
index 13ce71f..5a0339e 100644
--- a/main.c
+++ b/main.c
@@ -260,6 +260,7 @@ enum {
	VIS_ACTION_SELECTIONS_NEW_LINE_BELOW_LAST,
	VIS_ACTION_SELECTIONS_NEW_LINES_BEGIN,
	VIS_ACTION_SELECTIONS_NEW_LINES_END,
	VIS_ACTION_SELECTIONS_NEW_MATCH_ALL,
	VIS_ACTION_SELECTIONS_NEW_MATCH_NEXT,
	VIS_ACTION_SELECTIONS_NEW_MATCH_SKIP,
	VIS_ACTION_SELECTIONS_ALIGN,
@@ -917,6 +918,11 @@ static const KeyAction vis_action[] = {
		VIS_HELP("Create a new selection at the end of every line covered by selection")
		operator, { .i = VIS_OP_CURSOR_EOL }
	},
	[VIS_ACTION_SELECTIONS_NEW_MATCH_ALL] = {
		"vis-selection-new-match-all",
		VIS_HELP("Select all regions matching the current selection")
		selections_match_next, { .b = true }
	},
	[VIS_ACTION_SELECTIONS_NEW_MATCH_NEXT] = {
		"vis-selection-new-match-next",
		VIS_HELP("Select the next region matching the current selection")
@@ -1325,7 +1331,7 @@ static const char *selections_clear(Vis *vis, const char *keys, const Arg *arg)
	return keys;
}

static const Selection *selection_new_primary(View *view, Filerange *r) {
static Selection *selection_new(View *view, Filerange *r, bool isprimary) {
	Text *txt = view_text(view);
	size_t pos = text_char_prev(txt, r->end);
	Selection *s = view_selections_new(view, pos);
@@ -1333,7 +1339,8 @@ static const Selection *selection_new_primary(View *view, Filerange *r) {
		return NULL;
	view_selections_set(s, r);
	view_selections_anchor(s, true);
	view_selections_primary_set(s);
	if (isprimary)
		view_selections_primary_set(s);
	return s;
}

@@ -1363,15 +1370,26 @@ static const char *selections_match_next(Vis *vis, const char *keys, const Arg *
	if (!buf)
		return keys;

	Filerange word = find_next(txt, sel.end, buf);
	if (text_range_valid(&word) && selection_new_primary(view, &word))
		goto out;
	bool match_all = arg->b;

	for (;;) {
		sel = view_selections_get(s);
		Filerange word = find_next(txt, sel.end, buf);
		if (!text_range_valid(&word) || !(s = selection_new(view, &word, !match_all)))
			break;
		if (!match_all)
			goto out;
	}

	sel = view_selections_get(view_selections(view));
	word = find_prev(txt, sel.start, buf);
	if (!text_range_valid(&word))
		goto out;
	selection_new_primary(view, &word);
	for (;;) {
		sel = view_selections_get(view_selections(view));
		Filerange word = find_prev(txt, sel.start, buf);
		if (!text_range_valid(&word))
			break;
		selection_new(view, &word, !match_all);
		if (!match_all)
			break;
	}

out:
	free(buf);
diff --git a/man/vis.1 b/man/vis.1
index 10ad5bb..4082997 100644
--- a/man/vis.1
+++ b/man/vis.1
@@ -1097,6 +1097,9 @@ left align selections by inserting spaces
.It Aq Ic S-Tab
right align selections by inserting spaces
.
.It Aq Ic C-a
create new selections everywhere matching current word or selection
.
.It Aq Ic C-n
create new selection and select next word matching current selection
.
-- 
2.28.0

Re: [PATCH v3 3/3] vis: add vis-selection-new-match-all

Details
Message ID
<20200925164839.GA90314@thinkpad.localdomain>
In-Reply-To
<20200925154016.26202-4-evan.gates@gmail.com> (view parent)
DKIM signature
missing
Download raw message
On Fri, Sep 25, 2020 at 08:40:16AM -0700, Evan Gates wrote:
> @@ -1363,15 +1370,26 @@ static const char *selections_match_next(Vis *vis, const char *keys, const Arg *
>  	if (!buf)
>  		return keys;
>  
> -	Filerange word = find_next(txt, sel.end, buf);
> -	if (text_range_valid(&word) && selection_new_primary(view, &word))
> -		goto out;
> +	bool match_all = arg->b;
> +
> +	for (;;) {
> +		sel = view_selections_get(s);

This could be simplified, you don't need to look up the selection range
that you just set in the last loop iteration.

> +		Filerange word = find_next(txt, sel.end, buf);
> +		if (!text_range_valid(&word) || !(s = selection_new(view, &word, !match_all)))
> +			break;

selection_new will fail if the given range is already covered by
a selection. However, we probably still want to continue searching.

> +		if (!match_all)
> +			goto out;
> +	}
>  
> -	sel = view_selections_get(view_selections(view));
> -	word = find_prev(txt, sel.start, buf);
> -	if (!text_range_valid(&word))
> -		goto out;
> -	selection_new_primary(view, &word);
> +	for (;;) {
> +		sel = view_selections_get(view_selections(view));

Here you always start with the first selection. Instead we should start
from the primary selections towards the start of the file.

> +		Filerange word = find_prev(txt, sel.start, buf);
> +		if (!text_range_valid(&word))
> +			break;
> +		selection_new(view, &word, !match_all);
> +		if (!match_all)
> +			break;
> +	}
>  
>  out:
>  	free(buf);

Something like the following should work. I suggest to play around with
C-n, C-a, C-x, C-p, C-j, C-k etc. in visual mode to create different
cases where some selections are missing.

	bool match_all = arg->b;
	Filerange primary = sel;

	for (;;) {
		sel = find_next(txt, sel.end, buf);
		if (!text_range_valid(&sel))
			break;
		if (selection_new(view, &sel, !match_all) && !match_all)
			goto out;
	}

	sel = primary;

	for (;;) {
		sel = find_prev(txt, sel.start, buf);
		if (!text_range_valid(&sel))
			break;
		if (selection_new(view, &sel, !match_all) && !match_all)
			break;
	}

Also not sure whether "literal" could be dropped from the function names?
It would be a bit shorter and the text-motions.h counter part doesn't
include it either. Anyway no hard feelings about that.

Thanks,
Marc
Reply to thread Export thread (mbox)