aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-08-30 08:44:58 +0100
committerRon Yorston <rmy@pobox.com>2021-08-30 09:16:01 +0100
commit420afde92eb83c8c19b856f45491568cfa04a625 (patch)
treeeec8392147bc79ac58d0341be5b23ce97d4f5a21 /editors/vi.c
parenta9fc40467450f5afa9b220bb7c0fa9cade71c7a5 (diff)
downloadbusybox-w32-420afde92eb83c8c19b856f45491568cfa04a625.tar.gz
busybox-w32-420afde92eb83c8c19b856f45491568cfa04a625.tar.bz2
busybox-w32-420afde92eb83c8c19b856f45491568cfa04a625.zip
vi: add fileformats option
Add a limited version of the 'fileformats' option. Only the 'dos,unix' and 'unix,dos' settings are allowed with the former as default. When a file is read for editing its format is detected. If it only has LF line endings it's treated as being of type 'unix' otherwise its type is 'dos'. When an empty edit buffer is created it's given the first file type listed in 'fileformats'. The file type is stored in the read-only option 'fileformat' and is used to select the appropriate line endings when the file is written. See GitHub issue #220. Adds 168 bytes to the binary.
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c100
1 files changed, 97 insertions, 3 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 2c1048a4c..b973cc056 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -112,6 +112,15 @@
112//config: help 112//config: help
113//config: Enable the editor to set some (ai, ic, showmatch) options. 113//config: Enable the editor to set some (ai, ic, showmatch) options.
114//config: 114//config:
115//config:config FEATURE_VI_FILE_FORMAT
116//config: bool "Enable detection of file format"
117//config: default y
118//config: depends on VI && FEATURE_VI_SETOPTS && PLATFORM_MINGW32
119//config: help
120//config: Enable the editor to detect the format of files it reads
121//config: so they can be written out with the appropriate line
122//config: endings. Enable the 'fileformats' option.
123//config:
115//config:config FEATURE_VI_SET 124//config:config FEATURE_VI_SET
116//config: bool "Support :set" 125//config: bool "Support :set"
117//config: default y 126//config: default y
@@ -297,6 +306,7 @@ struct globals {
297 306
298 // the rest 307 // the rest
299#if ENABLE_FEATURE_VI_SETOPTS 308#if ENABLE_FEATURE_VI_SETOPTS
309#if !ENABLE_FEATURE_VI_FILE_FORMAT
300 smallint vi_setops; // set by setops() 310 smallint vi_setops; // set by setops()
301#define VI_AUTOINDENT (1 << 0) 311#define VI_AUTOINDENT (1 << 0)
302#define VI_EXPANDTAB (1 << 1) 312#define VI_EXPANDTAB (1 << 1)
@@ -304,6 +314,17 @@ struct globals {
304#define VI_IGNORECASE (1 << 3) 314#define VI_IGNORECASE (1 << 3)
305#define VI_SHOWMATCH (1 << 4) 315#define VI_SHOWMATCH (1 << 4)
306#define VI_TABSTOP (1 << 5) 316#define VI_TABSTOP (1 << 5)
317#else
318 smalluint vi_setops; // set by setops()
319#define VI_AUTOINDENT (1 << 0)
320#define VI_EXPANDTAB (1 << 1)
321#define VI_FILEFORMAT (1 << 2)
322#define VI_FILEFORMATS (1 << 3)
323#define VI_ERR_METHOD (1 << 4)
324#define VI_IGNORECASE (1 << 5)
325#define VI_SHOWMATCH (1 << 6)
326#define VI_TABSTOP (1 << 7)
327#endif
307#define autoindent (vi_setops & VI_AUTOINDENT) 328#define autoindent (vi_setops & VI_AUTOINDENT)
308#define expandtab (vi_setops & VI_EXPANDTAB ) 329#define expandtab (vi_setops & VI_EXPANDTAB )
309#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash 330#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash
@@ -313,10 +334,18 @@ struct globals {
313#define OPTS_STR \ 334#define OPTS_STR \
314 "ai\0""autoindent\0" \ 335 "ai\0""autoindent\0" \
315 "et\0""expandtab\0" \ 336 "et\0""expandtab\0" \
337 IF_FEATURE_VI_FILE_FORMAT("ff\0""fileformat\0") \
338 IF_FEATURE_VI_FILE_FORMAT("ffs\0""fileformats\0") \
316 "fl\0""flash\0" \ 339 "fl\0""flash\0" \
317 "ic\0""ignorecase\0" \ 340 "ic\0""ignorecase\0" \
318 "sm\0""showmatch\0" \ 341 "sm\0""showmatch\0" \
319 "ts\0""tabstop\0" 342 "ts\0""tabstop\0"
343
344#define FF_DOS_UNIX 0
345#define FF_UNIX_DOS 1
346#define FORMATS_STR \
347 "dos,unix\0" \
348 "unix,dos\0"
320#else 349#else
321#define autoindent (0) 350#define autoindent (0)
322#define expandtab (0) 351#define expandtab (0)
@@ -380,6 +409,10 @@ struct globals {
380#if ENABLE_FEATURE_VI_SETOPTS 409#if ENABLE_FEATURE_VI_SETOPTS
381 int indentcol; // column of recently autoindent, 0 or -1 410 int indentcol; // column of recently autoindent, 0 or -1
382#endif 411#endif
412#if ENABLE_FEATURE_VI_FILE_FORMAT
413 smallint fileformat;
414 smallint fileformats;
415#endif
383 smallint cmd_error; 416 smallint cmd_error;
384 417
385 // former statics 418 // former statics
@@ -507,6 +540,8 @@ struct globals {
507#define dotcnt (G.dotcnt ) 540#define dotcnt (G.dotcnt )
508#define last_search_pattern (G.last_search_pattern) 541#define last_search_pattern (G.last_search_pattern)
509#define indentcol (G.indentcol ) 542#define indentcol (G.indentcol )
543#define fileformat (G.fileformat )
544#define fileformats (G.fileformats )
510#define cmd_error (G.cmd_error ) 545#define cmd_error (G.cmd_error )
511 546
512#define edit_file__cur_line (G.edit_file__cur_line) 547#define edit_file__cur_line (G.edit_file__cur_line)
@@ -2066,6 +2101,10 @@ static int file_insert(const char *fn, char *p, int initial)
2066 undo_push_insert(p, size, ALLOW_UNDO); 2101 undo_push_insert(p, size, ALLOW_UNDO);
2067 } 2102 }
2068# endif 2103# endif
2104#if ENABLE_FEATURE_VI_FILE_FORMAT
2105 if (initial && cnt > 0)
2106 fileformat = cnt == size ? FF_UNIX_DOS : FF_DOS_UNIX;
2107#endif
2069 fi: 2108 fi:
2070 close(fd); 2109 close(fd);
2071 2110
@@ -2342,6 +2381,9 @@ static int init_text_buffer(char *fn)
2342 free(text); 2381 free(text);
2343 text_size = 10240; 2382 text_size = 10240;
2344 screenbegin = dot = end = text = xzalloc(text_size); 2383 screenbegin = dot = end = text = xzalloc(text_size);
2384#if ENABLE_FEATURE_VI_FILE_FORMAT
2385 fileformat = fileformats;
2386#endif
2345 2387
2346 update_filename(fn); 2388 update_filename(fn);
2347 rc = file_insert(fn, text, 1); 2389 rc = file_insert(fn, text, 1);
@@ -2387,6 +2429,13 @@ static uintptr_t string_insert(char *p, const char *s, int undo) // insert the s
2387static int file_write(char *fn, char *first, char *last) 2429static int file_write(char *fn, char *first, char *last)
2388{ 2430{
2389 int fd, cnt, charcnt; 2431 int fd, cnt, charcnt;
2432#if ENABLE_PLATFORM_MINGW32
2433# if ENABLE_FEATURE_VI_FILE_FORMAT
2434# define dos (fileformat == FF_DOS_UNIX)
2435# else
2436# define dos (1)
2437# endif
2438#endif
2390 2439
2391 if (fn == 0) { 2440 if (fn == 0) {
2392 status_line_bold("No current filename"); 2441 status_line_bold("No current filename");
@@ -2398,7 +2447,7 @@ static int file_write(char *fn, char *first, char *last)
2398#if !ENABLE_PLATFORM_MINGW32 2447#if !ENABLE_PLATFORM_MINGW32
2399 fd = open(fn, (O_WRONLY | O_CREAT), 0666); 2448 fd = open(fn, (O_WRONLY | O_CREAT), 0666);
2400#else 2449#else
2401 fd = open(fn, (O_WRONLY | O_CREAT | _O_TEXT), 0666); 2450 fd = open(fn, (O_WRONLY | O_CREAT | (dos ? _O_TEXT : 0)), 0666);
2402#endif 2451#endif
2403 if (fd < 0) 2452 if (fd < 0)
2404 return -1; 2453 return -1;
@@ -2407,9 +2456,9 @@ static int file_write(char *fn, char *first, char *last)
2407#if !ENABLE_PLATFORM_MINGW32 2456#if !ENABLE_PLATFORM_MINGW32
2408 ftruncate(fd, charcnt); 2457 ftruncate(fd, charcnt);
2409#else 2458#else
2410 // File was written in text mode; this makes it bigger so adjust 2459 // If file was written in text mode it will be bigger so adjust
2411 // the truncation to match. 2460 // the truncation to match.
2412 ftruncate(fd, charcnt + count_cr(first, cnt)); 2461 ftruncate(fd, charcnt + (dos ? count_cr(first, cnt) : 0));
2413#endif 2462#endif
2414 if (charcnt == cnt) { 2463 if (charcnt == cnt) {
2415 // good write 2464 // good write
@@ -2699,6 +2748,7 @@ static void setops(char *args, int flg_no)
2699 2748
2700 index = 1 << (index >> 1); // convert to VI_bit 2749 index = 1 << (index >> 1); // convert to VI_bit
2701 2750
2751#if !ENABLE_FEATURE_VI_FILE_FORMAT
2702 if (index & VI_TABSTOP) { 2752 if (index & VI_TABSTOP) {
2703 int t; 2753 int t;
2704 if (!eq || flg_no) // no "=NNN" or it is "notabstop"? 2754 if (!eq || flg_no) // no "=NNN" or it is "notabstop"?
@@ -2709,6 +2759,27 @@ static void setops(char *args, int flg_no)
2709 tabstop = t; 2759 tabstop = t;
2710 return; 2760 return;
2711 } 2761 }
2762#else
2763 if (index & VI_FILEFORMAT)
2764 goto bad;
2765 if (index & (VI_TABSTOP | VI_FILEFORMATS)) {
2766 if (!eq || flg_no) // no "=NNN" or it is "notabstop"?
2767 goto bad;
2768 if (index & VI_TABSTOP) {
2769 int t = bb_strtou(eq + 1, NULL, 10);
2770 if (t <= 0 || t > MAX_TABSTOP)
2771 goto bad;
2772 tabstop = t;
2773 return;
2774 } else { // VI_FILEFORMATS
2775 int t = index_in_strings(FORMATS_STR, eq + 1);
2776 if (t < 0)
2777 goto bad;
2778 fileformats = t;
2779 return;
2780 }
2781 }
2782#endif
2712 if (eq) goto bad; // boolean option has "="? 2783 if (eq) goto bad; // boolean option has "="?
2713 if (flg_no) { 2784 if (flg_no) {
2714 vi_setops &= ~index; 2785 vi_setops &= ~index;
@@ -3205,6 +3276,7 @@ static void colon(char *buf)
3205 if (!args[0] || strcmp(args, "all") == 0) { 3276 if (!args[0] || strcmp(args, "all") == 0) {
3206 // print out values of all options 3277 // print out values of all options
3207# if ENABLE_FEATURE_VI_SETOPTS 3278# if ENABLE_FEATURE_VI_SETOPTS
3279# if !ENABLE_FEATURE_VI_FILE_FORMAT
3208 status_line_bold( 3280 status_line_bold(
3209 "%sautoindent " 3281 "%sautoindent "
3210 "%sexpandtab " 3282 "%sexpandtab "
@@ -3219,6 +3291,28 @@ static void colon(char *buf)
3219 showmatch ? "" : "no", 3291 showmatch ? "" : "no",
3220 tabstop 3292 tabstop
3221 ); 3293 );
3294# else // ENABLE_FEATURE_VI_FILE_FORMAT
3295 unsigned int mask = 1, j = 0;
3296 go_bottom_and_clear_to_eol();
3297 for (;;) {
3298 const char *name = nth_string(OPTS_STR, 2 * j + 1);
3299 if (!name[0])
3300 break;
3301 if (mask == VI_FILEFORMAT)
3302 printf("%s=%s ", name, nth_string("dos\0unix\0", fileformat));
3303 else if (mask == VI_FILEFORMATS)
3304 printf("%s=%s ", name, nth_string(FORMATS_STR, fileformats));
3305 else if (mask == VI_TABSTOP)
3306 printf("%s=%u ", name, tabstop);
3307 else
3308 printf("%s%s ", vi_setops & mask ? "" : "no", name);
3309 if (j++ == 4)
3310 bb_putchar('\n');
3311 mask <<= 1;
3312 }
3313 bb_putchar('\n');
3314 Hit_Return();
3315# endif
3222# endif 3316# endif
3223 goto ret; 3317 goto ret;
3224 } 3318 }