aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-06-07 11:34:06 +0100
committerRon Yorston <rmy@pobox.com>2021-06-07 11:34:06 +0100
commitabe872e2a0342357a5608342cb2892e94027b3e7 (patch)
tree297cdccf332fbb5e4eb31b1eac643180059f9b5f /editors
parent1f33f42d7bcb019b268d938df643a7a785dc19ab (diff)
parent4d983dcddeee94892d3072e84c7c9a01d4696055 (diff)
downloadbusybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.tar.gz
busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.tar.bz2
busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'editors')
-rw-r--r--editors/vi.c111
1 files changed, 77 insertions, 34 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 3dcde9b24..a4d6b21b4 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -307,7 +307,6 @@ struct globals {
307#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash 307#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash
308#define ignorecase (vi_setops & VI_IGNORECASE) 308#define ignorecase (vi_setops & VI_IGNORECASE)
309#define showmatch (vi_setops & VI_SHOWMATCH ) 309#define showmatch (vi_setops & VI_SHOWMATCH )
310#define openabove (vi_setops & VI_TABSTOP )
311// order of constants and strings must match 310// order of constants and strings must match
312#define OPTS_STR \ 311#define OPTS_STR \
313 "ai\0""autoindent\0" \ 312 "ai\0""autoindent\0" \
@@ -316,15 +315,10 @@ struct globals {
316 "ic\0""ignorecase\0" \ 315 "ic\0""ignorecase\0" \
317 "sm\0""showmatch\0" \ 316 "sm\0""showmatch\0" \
318 "ts\0""tabstop\0" 317 "ts\0""tabstop\0"
319#define set_openabove() (vi_setops |= VI_TABSTOP)
320#define clear_openabove() (vi_setops &= ~VI_TABSTOP)
321#else 318#else
322#define autoindent (0) 319#define autoindent (0)
323#define expandtab (0) 320#define expandtab (0)
324#define err_method (0) 321#define err_method (0)
325#define openabove (0)
326#define set_openabove() ((void)0)
327#define clear_openabove() ((void)0)
328#endif 322#endif
329 323
330#if ENABLE_FEATURE_VI_READONLY 324#if ENABLE_FEATURE_VI_READONLY
@@ -380,6 +374,9 @@ struct globals {
380#if ENABLE_FEATURE_VI_SEARCH 374#if ENABLE_FEATURE_VI_SEARCH
381 char *last_search_pattern; // last pattern from a '/' or '?' search 375 char *last_search_pattern; // last pattern from a '/' or '?' search
382#endif 376#endif
377#if ENABLE_FEATURE_VI_SETOPTS
378 int indentcol; // column of recently autoindent, 0 or -1
379#endif
383 380
384 // former statics 381 // former statics
385#if ENABLE_FEATURE_VI_YANKMARK 382#if ENABLE_FEATURE_VI_YANKMARK
@@ -505,6 +502,7 @@ struct globals {
505#define ioq_start (G.ioq_start ) 502#define ioq_start (G.ioq_start )
506#define dotcnt (G.dotcnt ) 503#define dotcnt (G.dotcnt )
507#define last_search_pattern (G.last_search_pattern) 504#define last_search_pattern (G.last_search_pattern)
505#define indentcol (G.indentcol )
508 506
509#define edit_file__cur_line (G.edit_file__cur_line) 507#define edit_file__cur_line (G.edit_file__cur_line)
510#define refresh__old_offset (G.refresh__old_offset) 508#define refresh__old_offset (G.refresh__old_offset)
@@ -2155,15 +2153,26 @@ static uintptr_t stupid_insert(char *p, char c) // stupidly insert the char c at
2155 return bias; 2153 return bias;
2156} 2154}
2157 2155
2156// find number of characters in indent, p must be at beginning of line
2157static size_t indent_len(char *p)
2158{
2159 char *r = p;
2160
2161 while (r < (end - 1) && isblank(*r))
2162 r++;
2163 return r - p;
2164}
2165
2158#if !ENABLE_FEATURE_VI_UNDO 2166#if !ENABLE_FEATURE_VI_UNDO
2159#define char_insert(a,b,c) char_insert(a,b) 2167#define char_insert(a,b,c) char_insert(a,b)
2160#endif 2168#endif
2161static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' 2169static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2162{ 2170{
2163#if ENABLE_FEATURE_VI_SETOPTS 2171#if ENABLE_FEATURE_VI_SETOPTS
2164 char *q;
2165 size_t len; 2172 size_t len;
2173 int col, ntab, nspc;
2166#endif 2174#endif
2175 char *bol = begin_line(p);
2167 2176
2168 if (c == 22) { // Is this an ctrl-V? 2177 if (c == 22) { // Is this an ctrl-V?
2169 p += stupid_insert(p, '^'); // use ^ to indicate literal next 2178 p += stupid_insert(p, '^'); // use ^ to indicate literal next
@@ -2185,25 +2194,36 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2185 if ((p[-1] != '\n') && (dot > text)) { 2194 if ((p[-1] != '\n') && (dot > text)) {
2186 p--; 2195 p--;
2187 } 2196 }
2188 } else if (c == 4) { // ctrl-D reduces indentation 2197#if ENABLE_FEATURE_VI_SETOPTS
2189 int prev; 2198 if (autoindent) {
2190 char *r, *bol; 2199 len = indent_len(bol);
2191 bol = begin_line(p); 2200 if (len && get_column(bol + len) == indentcol) {
2192 for (r = bol; r < end_line(p); ++r) { 2201 // remove autoindent from otherwise empty line
2193 if (!isblank(*r)) 2202 text_hole_delete(bol, bol + len - 1, undo);
2194 break; 2203 p = bol;
2204 }
2195 } 2205 }
2196 2206#endif
2197 prev = prev_tabstop(get_column(r)); 2207 } else if (c == 4) { // ctrl-D reduces indentation
2208 char *r = bol + indent_len(bol);
2209 int prev = prev_tabstop(get_column(r));
2198 while (r > bol && get_column(r) > prev) { 2210 while (r > bol && get_column(r) > prev) {
2199 if (p > bol) 2211 if (p > bol)
2200 p--; 2212 p--;
2201 r--; 2213 r--;
2202 r = text_hole_delete(r, r, ALLOW_UNDO_QUEUED); 2214 r = text_hole_delete(r, r, ALLOW_UNDO_QUEUED);
2203 } 2215 }
2216
2217#if ENABLE_FEATURE_VI_SETOPTS
2218 if (autoindent && indentcol && r == end_line(p)) {
2219 // record changed size of autoindent
2220 indentcol = get_column(p);
2221 return p;
2222 }
2223#endif
2204#if ENABLE_FEATURE_VI_SETOPTS 2224#if ENABLE_FEATURE_VI_SETOPTS
2205 } else if (c == '\t' && expandtab) { // expand tab 2225 } else if (c == '\t' && expandtab) { // expand tab
2206 int col = get_column(p); 2226 col = get_column(p);
2207 col = next_tabstop(col) - col + 1; 2227 col = next_tabstop(col) - col + 1;
2208 while (col--) { 2228 while (col--) {
2209# if ENABLE_FEATURE_VI_UNDO 2229# if ENABLE_FEATURE_VI_UNDO
@@ -2242,27 +2262,46 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2242 showmatching(p - 1); 2262 showmatching(p - 1);
2243 } 2263 }
2244 if (autoindent && c == '\n') { // auto indent the new line 2264 if (autoindent && c == '\n') { // auto indent the new line
2245 // use current/previous line as template 2265 // use indent of current/previous line
2246 q = openabove ? p : prev_line(p); 2266 bol = indentcol < 0 ? p : prev_line(p);
2247 len = strspn(q, " \t"); // space or tab 2267 len = indent_len(bol);
2248 if (openabove) { 2268 col = get_column(bol + len);
2249 p--; // this replaces dot_prev() in do_cmd() 2269
2250 q += len; // template will be shifted by text_hole_make() 2270 if (len && col == indentcol) {
2271 // previous line was empty except for autoindent
2272 // move the indent to the current line
2273 memmove(bol + 1, bol, len);
2274 *bol = '\n';
2275 return p;
2251 } 2276 }
2277
2278 if (indentcol < 0)
2279 p--; // open above, indent before newly inserted NL
2280
2252 if (len) { 2281 if (len) {
2253 uintptr_t bias; 2282 indentcol = col;
2254 bias = text_hole_make(p, len); 2283 if (expandtab) {
2255 p += bias; 2284 ntab = 0;
2256 q += bias; 2285 nspc = col;
2286 } else {
2287 ntab = col / tabstop;
2288 nspc = col % tabstop;
2289 }
2290 p += text_hole_make(p, ntab + nspc);
2257# if ENABLE_FEATURE_VI_UNDO 2291# if ENABLE_FEATURE_VI_UNDO
2258 undo_push_insert(p, len, undo); 2292 undo_push_insert(p, ntab + nspc, undo);
2259# endif 2293# endif
2260 memcpy(p, q, len); 2294 memset(p, '\t', ntab);
2261 p += len; 2295 p += ntab;
2296 memset(p, ' ', nspc);
2297 return p + nspc;
2262 } 2298 }
2263 } 2299 }
2264#endif 2300#endif
2265 } 2301 }
2302#if ENABLE_FEATURE_VI_SETOPTS
2303 indentcol = 0;
2304#endif
2266 return p; 2305 return p;
2267} 2306}
2268 2307
@@ -2647,7 +2686,6 @@ static void setops(char *args, int flg_no)
2647 index = 1 << (index >> 1); // convert to VI_bit 2686 index = 1 << (index >> 1); // convert to VI_bit
2648 2687
2649 if (index & VI_TABSTOP) { 2688 if (index & VI_TABSTOP) {
2650 // don't set this bit in vi_setops, it's reused as 'openabove'
2651 int t; 2689 int t;
2652 if (!eq || flg_no) // no "=NNN" or it is "notabstop"? 2690 if (!eq || flg_no) // no "=NNN" or it is "notabstop"?
2653 goto bad; 2691 goto bad;
@@ -3783,6 +3821,7 @@ static void do_cmd(int c)
3783# endif 3821# endif
3784 } while (--cmdcnt > 0); 3822 } while (--cmdcnt > 0);
3785 dot += cnt; 3823 dot += cnt;
3824 dot_skip_over_ws();
3786# if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS 3825# if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS
3787 yank_status("Put", p, i); 3826 yank_status("Put", p, i);
3788# endif 3827# endif
@@ -4109,17 +4148,18 @@ static void do_cmd(int c)
4109 break; 4148 break;
4110 case 'O': // O- open an empty line above 4149 case 'O': // O- open an empty line above
4111 dot_begin(); 4150 dot_begin();
4112 set_openabove(); 4151#if ENABLE_FEATURE_VI_SETOPTS
4152 indentcol = -1;
4153#endif
4113 goto dc3; 4154 goto dc3;
4114 case 'o': // o- open an empty line below 4155 case 'o': // o- open an empty line below
4115 dot_end(); 4156 dot_end();
4116 dc3: 4157 dc3:
4117 dot = char_insert(dot, '\n', ALLOW_UNDO); 4158 dot = char_insert(dot, '\n', ALLOW_UNDO);
4118 if (c == 'O' && !autoindent) { 4159 if (c == 'O' && !autoindent) {
4119 // done in char_insert() for openabove+autoindent 4160 // done in char_insert() for 'O'+autoindent
4120 dot_prev(); 4161 dot_prev();
4121 } 4162 }
4122 clear_openabove();
4123 goto dc_i; 4163 goto dc_i;
4124 break; 4164 break;
4125 case 'R': // R- continuous Replace char 4165 case 'R': // R- continuous Replace char
@@ -4238,6 +4278,9 @@ static void do_cmd(int c)
4238 if (dot != (end-1)) { 4278 if (dot != (end-1)) {
4239 dot_prev(); 4279 dot_prev();
4240 } 4280 }
4281 } else if (c == 'd') {
4282 dot_begin();
4283 dot_skip_over_ws();
4241 } else { 4284 } else {
4242 dot = save_dot; 4285 dot = save_dot;
4243 } 4286 }