noxz-sites

A collection of a builder and various scripts creating the noxz.tech sites
git clone https://noxz.tech/git/noxz-sites.git
Log | Files | README | LICENSE

noxz.tech/articles/vi_indicator_for_loksh/loksh-viprompt-20190502-774e6d2.patch
1Author: Chris Noxz <chris@noxz.tech>
2
3This patch adds the feature to visually indicate the current vi mode in the
4prompt. It's required to add a placeholder in your PS1 such as '[xxx] '. The
5indicator will be inserted between the first '[' and the first ']'. All status
6indicators needs to be of the same visible size, such as 'cmd','ins' and 'rep'.
7
8Happy hacking
9
10diff --git a/vi.c b/vi.c
11index 12202d5..bd96137 100644
12--- a/vi.c
13+++ b/vi.c
14@@ -28,6 +28,10 @@ struct edstate {
15 	int	cursor;		/* byte# in cbuf having the cursor */
16 };
17 
18+static const char vprompt_normal[] = "\\[\x1b[1;31m\\]cmd\\[\x1b[0m\\]";
19+static const char vprompt_insert[] = "\\[\x1b[1;32m\\]ins\\[\x1b[0m\\]";
20+static const char vprompt_replace[] = "\\[\x1b[1;33m\\]rep\\[\x1b[0m\\]";
21+static void set_insert(int);
22 
23 static int	vi_hook(int);
24 static void	vi_reset(char *, size_t);
25@@ -754,21 +758,21 @@ vi_cmd(int argcnt, const char *cmd)
26 			if (es->linelen != 0)
27 				while (isu8cont(es->cbuf[++es->cursor]))
28 					continue;
29-			insert = INSERT;
30+			set_insert(INSERT);
31 			break;
32 
33 		case 'A':
34 			modified = 1; hnum = hlast;
35 			del_range(0, 0);
36 			es->cursor = es->linelen;
37-			insert = INSERT;
38+			set_insert(INSERT);
39 			break;
40 
41 		case 'S':
42 			es->cursor = domove(1, "^", 1);
43 			del_range(es->cursor, es->linelen);
44 			modified = 1; hnum = hlast;
45-			insert = INSERT;
46+			set_insert(INSERT);
47 			break;
48 
49 		case 'Y':
50@@ -811,7 +815,7 @@ vi_cmd(int argcnt, const char *cmd)
51 			}
52 			if (*cmd == 'c') {
53 				modified = 1; hnum = hlast;
54-				insert = INSERT;
55+				set_insert(INSERT);
56 			}
57 			break;
58 
59@@ -841,7 +845,7 @@ vi_cmd(int argcnt, const char *cmd)
60 		case 'C':
61 			modified = 1; hnum = hlast;
62 			del_range(es->cursor, es->linelen);
63-			insert = INSERT;
64+			set_insert(INSERT);
65 			break;
66 
67 		case 'D':
68@@ -870,13 +874,13 @@ vi_cmd(int argcnt, const char *cmd)
69 
70 		case 'i':
71 			modified = 1; hnum = hlast;
72-			insert = INSERT;
73+			set_insert(INSERT);
74 			break;
75 
76 		case 'I':
77 			modified = 1; hnum = hlast;
78 			es->cursor = domove(1, "^", 1);
79-			insert = INSERT;
80+			set_insert(INSERT);
81 			break;
82 
83 		case 'j':
84@@ -931,7 +935,7 @@ vi_cmd(int argcnt, const char *cmd)
85 
86 		case 'R':
87 			modified = 1; hnum = hlast;
88-			insert = REPLACE;
89+			set_insert(REPLACE);
90 			break;
91 
92 		case 's':
93@@ -943,7 +947,7 @@ vi_cmd(int argcnt, const char *cmd)
94 					if (argcnt-- == 0)
95 						break;
96 			del_range(es->cursor, cur);
97-			insert = INSERT;
98+			set_insert(INSERT);
99 			break;
100 
101 		case 'v':
102@@ -1087,7 +1091,7 @@ vi_cmd(int argcnt, const char *cmd)
103 					es->cursor--;
104 				return -1;
105 			}
106-			insert = INSERT;
107+			set_insert(INSERT);
108 			}
109 			break;
110 
111@@ -1297,7 +1301,7 @@ redo_insert(int count)
112 	if (es->cursor > 0)
113 		while (isu8cont(es->cbuf[--es->cursor]))
114 			continue;
115-	insert = 0;
116+	set_insert(0);
117 	return 0;
118 }
119 
120@@ -2031,7 +2035,7 @@ expand_word(int command)
121 	if (rval == 0 && i > 0)
122 		es->cursor += i;
123 	modified = 1; hnum = hlast;
124-	insert = INSERT;
125+	set_insert(INSERT);
126 	lastac = 0;
127 	refresh(0);
128 	return rval;
129@@ -2135,7 +2139,7 @@ complete_word(int command, int count)
130 	x_free_words(nwords, words);
131 
132 	modified = 1; hnum = hlast;
133-	insert = INSERT;
134+	set_insert(INSERT);
135 	lastac = 0;	 /* prevent this from being redone... */
136 	refresh(0);
137 
138@@ -2197,10 +2201,49 @@ x_vi_zotc(int c)
139 	x_putc(c);
140 }
141 
142+static void
143+set_insert(int nmode)
144+{
145+	int update = nmode != insert;
146+	insert = nmode;
147+
148+	if (update)
149+		ed_mov_opt(0, wbuf[1 - win]);
150+}
151+
152 static void
153 vi_pprompt(int full)
154 {
155-	pprompt(prompt + (full ? 0 : prompt_skip), prompt_trunc);
156+	const char *prefix = (
157+		insert == 0 ? vprompt_normal :
158+		insert == REPLACE ? vprompt_replace :
159+		vprompt_insert);
160+	char *nprompt = calloc(strlen(prefix) + strlen(prompt) + 1, sizeof(char));
161+	int start_index = 0,
162+		stop_index = 0,
163+		length = 0;
164+	char *start, *stop;
165+
166+	if ((start = strchr(prompt, '[')) && (stop = strchr(prompt, ']'))) {
167+		start_index = (int)(start - prompt);
168+		stop_index = (int)(stop - prompt);
169+		length = (int)(stop_index - start_index - 1);
170+	}
171+
172+	if (
173+		promptlen(vprompt_insert, NULL) == length
174+		&& promptlen(vprompt_normal, NULL) == length
175+		&& promptlen(vprompt_replace, NULL) == length
176+	) {
177+		strncpy(nprompt, prompt, start_index + 1);
178+		strcat(nprompt, prefix);
179+		strncat(nprompt, prompt + stop_index, strlen(prompt) - stop_index);
180+	} else {
181+		strcat(nprompt, prompt);
182+	}
183+
184+	pprompt(nprompt + (full ? 0 : prompt_skip), prompt_trunc);
185+	free(nprompt);
186 }
187 
188 static void