diff options
Diffstat (limited to 'editors/vi.c')
-rw-r--r-- | editors/vi.c | 229 |
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 |
369 | static char *char_search(char *, const char *, int, int); // search for pattern starting at p | 500 | static char *char_search(char *, const char *, int, int); // search for pattern starting at p |
370 | static 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 |
373 | static char *get_one_address(char *, int *); // get colon addr, if present | 503 | static 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 |
1565 | static 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 |
1574 | static char *char_search(char *p, const char *pat, int dir, int range) | 1699 | static 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 | ||
1766 | static 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 | |||
1777 | static 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 | ||
1667 | static char *char_insert(char *p, char c) // insert the char c at 'p' | 1810 | static 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 \':\'" |