aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c229
1 files changed, 186 insertions, 43 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 9d74acc91..deb471d04 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -21,11 +21,138 @@
21 * An "ex" line oriented mode- maybe using "cmdedit" 21 * An "ex" line oriented mode- maybe using "cmdedit"
22 */ 22 */
23 23
24//config:config VI
25//config: bool "vi"
26//config: default y
27//config: help
28//config: 'vi' is a text editor. More specifically, it is the One True
29//config: text editor <grin>. It does, however, have a rather steep
30//config: learning curve. If you are not already comfortable with 'vi'
31//config: you may wish to use something else.
32//config:
33//config:config FEATURE_VI_MAX_LEN
34//config: int "Maximum screen width in vi"
35//config: range 256 16384
36//config: default 4096
37//config: depends on VI
38//config: help
39//config: Contrary to what you may think, this is not eating much.
40//config: Make it smaller than 4k only if you are very limited on memory.
41//config:
42//config:config FEATURE_VI_8BIT
43//config: bool "Allow vi to display 8-bit chars (otherwise shows dots)"
44//config: default n
45//config: depends on VI
46//config: help
47//config: If your terminal can display characters with high bit set,
48//config: you may want to enable this. Note: vi is not Unicode-capable.
49//config: If your terminal combines several 8-bit bytes into one character
50//config: (as in Unicode mode), this will not work properly.
51//config:
52//config:config FEATURE_VI_COLON
53//config: bool "Enable \":\" colon commands (no \"ex\" mode)"
54//config: default y
55//config: depends on VI
56//config: help
57//config: Enable a limited set of colon commands for vi. This does not
58//config: provide an "ex" mode.
59//config:
60//config:config FEATURE_VI_YANKMARK
61//config: bool "Enable yank/put commands and mark cmds"
62//config: default y
63//config: depends on VI
64//config: help
65//config: This will enable you to use yank and put, as well as mark in
66//config: busybox vi.
67//config:
68//config:config FEATURE_VI_SEARCH
69//config: bool "Enable search and replace cmds"
70//config: default y
71//config: depends on VI
72//config: help
73//config: Select this if you wish to be able to do search and replace in
74//config: busybox vi.
75//config:
76//config:config FEATURE_VI_REGEX_SEARCH
77//config: bool "Enable regex in search and replace"
78//config: default n # Uses GNU regex, which may be unavailable. FIXME
79//config: depends on FEATURE_VI_SEARCH
80//config: help
81//config: Use extended regex search.
82//config:
83//config:config FEATURE_VI_USE_SIGNALS
84//config: bool "Catch signals"
85//config: default y
86//config: depends on VI
87//config: help
88//config: Selecting this option will make busybox vi signal aware. This will
89//config: make busybox vi support SIGWINCH to deal with Window Changes, catch
90//config: Ctrl-Z and Ctrl-C and alarms.
91//config:
92//config:config FEATURE_VI_DOT_CMD
93//config: bool "Remember previous cmd and \".\" cmd"
94//config: default y
95//config: depends on VI
96//config: help
97//config: Make busybox vi remember the last command and be able to repeat it.
98//config:
99//config:config FEATURE_VI_READONLY
100//config: bool "Enable -R option and \"view\" mode"
101//config: default y
102//config: depends on VI
103//config: help
104//config: Enable the read-only command line option, which allows the user to
105//config: open a file in read-only mode.
106//config:
107//config:config FEATURE_VI_SETOPTS
108//config: bool "Enable set-able options, ai ic showmatch"
109//config: default y
110//config: depends on VI
111//config: help
112//config: Enable the editor to set some (ai, ic, showmatch) options.
113//config:
114//config:config FEATURE_VI_SET
115//config: bool "Support for :set"
116//config: default y
117//config: depends on VI
118//config: help
119//config: Support for ":set".
120//config:
121//config:config FEATURE_VI_WIN_RESIZE
122//config: bool "Handle window resize"
123//config: default y
124//config: depends on VI
125//config: help
126//config: Make busybox vi behave nicely with terminals that get resized.
127//config:
128//config:config FEATURE_VI_ASK_TERMINAL
129//config: bool "Use 'tell me cursor position' ESC sequence to measure window"
130//config: default y
131//config: depends on VI
132//config: help
133//config: If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
134//config: this option makes vi perform a last-ditch effort to find it:
135//config: vi positions cursor to 999,999 and asks terminal to report real
136//config: cursor position using "ESC [ 6 n" escape sequence, then reads stdin.
137//config:
138//config: This is not clean but helps a lot on serial lines and such.
139//config:
140//config:config FEATURE_VI_OPTIMIZE_CURSOR
141//config: bool "Optimize cursor movement"
142//config: default y
143//config: depends on VI
144//config: help
145//config: This will make the cursor movement faster, but requires more memory
146//config: and it makes the applet a tiny bit larger.
147
148//applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP))
149
150//kbuild:lib-$(CONFIG_VI) += vi.o
151
24//usage:#define vi_trivial_usage 152//usage:#define vi_trivial_usage
25//usage: "[OPTIONS] [FILE]..." 153//usage: "[OPTIONS] [FILE]..."
26//usage:#define vi_full_usage "\n\n" 154//usage:#define vi_full_usage "\n\n"
27//usage: "Edit FILE\n" 155//usage: "Edit FILE\n"
28//usage: "\nOptions:"
29//usage: IF_FEATURE_VI_COLON( 156//usage: IF_FEATURE_VI_COLON(
30//usage: "\n -c Initial command to run ($EXINIT also available)" 157//usage: "\n -c Initial command to run ($EXINIT also available)"
31//usage: ) 158//usage: )
@@ -35,6 +162,10 @@
35//usage: "\n -H Short help regarding available features" 162//usage: "\n -H Short help regarding available features"
36 163
37#include "libbb.h" 164#include "libbb.h"
165/* Should be after libbb.h: on some systems regex.h needs sys/types.h: */
166#if ENABLE_FEATURE_VI_REGEX_SEARCH
167# include <regex.h>
168#endif
38 169
39/* the CRASHME code is unmaintained, and doesn't currently build */ 170/* the CRASHME code is unmaintained, and doesn't currently build */
40#define ENABLE_FEATURE_VI_CRASHME 0 171#define ENABLE_FEATURE_VI_CRASHME 0
@@ -53,9 +184,9 @@
53 184
54/* 0x9b is Meta-ESC */ 185/* 0x9b is Meta-ESC */
55#if ENABLE_FEATURE_VI_8BIT 186#if ENABLE_FEATURE_VI_8BIT
56#define Isprint(c) ((unsigned char)(c) >= ' ' && (c) != 0x7f && (unsigned char)(c) != 0x9b) 187# define Isprint(c) ((unsigned char)(c) >= ' ' && (c) != 0x7f && (unsigned char)(c) != 0x9b)
57#else 188#else
58#define Isprint(c) ((unsigned char)(c) >= ' ' && (unsigned char)(c) < 0x7f) 189# define Isprint(c) ((unsigned char)(c) >= ' ' && (unsigned char)(c) < 0x7f)
59#endif 190#endif
60 191
61#endif 192#endif
@@ -367,7 +498,6 @@ static void Hit_Return(void);
367 498
368#if ENABLE_FEATURE_VI_SEARCH 499#if ENABLE_FEATURE_VI_SEARCH
369static char *char_search(char *, const char *, int, int); // search for pattern starting at p 500static char *char_search(char *, const char *, int, int); // search for pattern starting at p
370static int mycmp(const char *, const char *, int); // string cmp based in "ignorecase"
371#endif 501#endif
372#if ENABLE_FEATURE_VI_COLON 502#if ENABLE_FEATURE_VI_COLON
373static char *get_one_address(char *, int *); // get colon addr, if present 503static char *get_one_address(char *, int *); // get colon addr, if present
@@ -1562,48 +1692,16 @@ static char *new_screen(int ro, int co)
1562} 1692}
1563 1693
1564#if ENABLE_FEATURE_VI_SEARCH 1694#if ENABLE_FEATURE_VI_SEARCH
1565static int mycmp(const char *s1, const char *s2, int len) 1695
1566{ 1696# if ENABLE_FEATURE_VI_REGEX_SEARCH
1567 if (ENABLE_FEATURE_VI_SETOPTS && ignorecase) {
1568 return strncasecmp(s1, s2, len);
1569 }
1570 return strncmp(s1, s2, len);
1571}
1572 1697
1573// search for pattern starting at p 1698// search for pattern starting at p
1574static char *char_search(char *p, const char *pat, int dir, int range) 1699static char *char_search(char *p, const char *pat, int dir, int range)
1575{ 1700{
1576#ifndef REGEX_SEARCH
1577 char *start, *stop;
1578 int len;
1579
1580 len = strlen(pat);
1581 if (dir == FORWARD) {
1582 stop = end - 1; // assume range is p - end-1
1583 if (range == LIMITED)
1584 stop = next_line(p); // range is to next line
1585 for (start = p; start < stop; start++) {
1586 if (mycmp(start, pat, len) == 0) {
1587 return start;
1588 }
1589 }
1590 } else if (dir == BACK) {
1591 stop = text; // assume range is text - p
1592 if (range == LIMITED)
1593 stop = prev_line(p); // range is to prev line
1594 for (start = p - len; start >= stop; start--) {
1595 if (mycmp(start, pat, len) == 0) {
1596 return start;
1597 }
1598 }
1599 }
1600 // pattern not found
1601 return NULL;
1602#else /* REGEX_SEARCH */
1603 char *q; 1701 char *q;
1604 struct re_pattern_buffer preg; 1702 struct re_pattern_buffer preg;
1605 int i; 1703 int i;
1606 int size, range; 1704 int size;
1607 1705
1608 re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; 1706 re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
1609 preg.translate = 0; 1707 preg.translate = 0;
@@ -1626,7 +1724,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
1626 // RANGE could be negative if we are searching backwards 1724 // RANGE could be negative if we are searching backwards
1627 range = q - p; 1725 range = q - p;
1628 1726
1629 q = re_compile_pattern(pat, strlen(pat), &preg); 1727 q = (char *)re_compile_pattern(pat, strlen(pat), (struct re_pattern_buffer *)&preg);
1630 if (q != 0) { 1728 if (q != 0) {
1631 // The pattern was not compiled 1729 // The pattern was not compiled
1632 status_line_bold("bad search pattern: \"%s\": %s", pat, q); 1730 status_line_bold("bad search pattern: \"%s\": %s", pat, q);
@@ -1660,8 +1758,53 @@ static char *char_search(char *p, const char *pat, int dir, int range)
1660 p = p - i; 1758 p = p - i;
1661 } 1759 }
1662 return p; 1760 return p;
1663#endif /* REGEX_SEARCH */
1664} 1761}
1762
1763# else
1764
1765# if ENABLE_FEATURE_VI_SETOPTS
1766static int mycmp(const char *s1, const char *s2, int len)
1767{
1768 if (ignorecase) {
1769 return strncasecmp(s1, s2, len);
1770 }
1771 return strncmp(s1, s2, len);
1772}
1773# else
1774# define mycmp strncmp
1775# endif
1776
1777static char *char_search(char *p, const char *pat, int dir, int range)
1778{
1779 char *start, *stop;
1780 int len;
1781
1782 len = strlen(pat);
1783 if (dir == FORWARD) {
1784 stop = end - 1; // assume range is p - end-1
1785 if (range == LIMITED)
1786 stop = next_line(p); // range is to next line
1787 for (start = p; start < stop; start++) {
1788 if (mycmp(start, pat, len) == 0) {
1789 return start;
1790 }
1791 }
1792 } else if (dir == BACK) {
1793 stop = text; // assume range is text - p
1794 if (range == LIMITED)
1795 stop = prev_line(p); // range is to prev line
1796 for (start = p - len; start >= stop; start--) {
1797 if (mycmp(start, pat, len) == 0) {
1798 return start;
1799 }
1800 }
1801 }
1802 // pattern not found
1803 return NULL;
1804}
1805
1806# endif
1807
1665#endif /* FEATURE_VI_SEARCH */ 1808#endif /* FEATURE_VI_SEARCH */
1666 1809
1667static char *char_insert(char *p, char c) // insert the char c at 'p' 1810static char *char_insert(char *p, char c) // insert the char c at 'p'
@@ -2023,8 +2166,8 @@ static void show_help(void)
2023 "\n\tNamed buffers with \"x" 2166 "\n\tNamed buffers with \"x"
2024#endif 2167#endif
2025#if ENABLE_FEATURE_VI_READONLY 2168#if ENABLE_FEATURE_VI_READONLY
2026 "\n\tReadonly if vi is called as \"view\"" 2169 //not implemented: "\n\tReadonly if vi is called as \"view\""
2027 "\n\tReadonly with -R command line arg" 2170 //redundant: usage text says this too: "\n\tReadonly with -R command line arg"
2028#endif 2171#endif
2029#if ENABLE_FEATURE_VI_SET 2172#if ENABLE_FEATURE_VI_SET
2030 "\n\tSome colon mode commands with \':\'" 2173 "\n\tSome colon mode commands with \':\'"