aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/buffer.c1
-rw-r--r--src/nvim/aucmd.c1
-rw-r--r--src/nvim/auevents.lua1
-rw-r--r--src/nvim/autocmd.c1
-rw-r--r--src/nvim/buffer.c1
-rw-r--r--src/nvim/change.c287
-rw-r--r--src/nvim/channel.c1
-rw-r--r--src/nvim/charset.c1
-rw-r--r--src/nvim/cursor.c1
-rw-r--r--src/nvim/diff.c2
-rw-r--r--src/nvim/digraph.c1
-rw-r--r--src/nvim/edit.c11
-rw-r--r--src/nvim/eval.c1
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/eval/typval.c2
-rw-r--r--src/nvim/eval/userfunc.c1
-rw-r--r--src/nvim/event/rstream.c1
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/ex_cmds2.c1
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/ex_session.c1
-rw-r--r--src/nvim/file_search.c1
-rw-r--r--src/nvim/fileio.c2
-rw-r--r--src/nvim/fold.c1
-rw-r--r--src/nvim/getchar.c11
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/indent.c1
-rw-r--r--src/nvim/indent_c.c1
-rw-r--r--src/nvim/input.c255
-rw-r--r--src/nvim/input.h9
-rw-r--r--src/nvim/lua/executor.c1
-rw-r--r--src/nvim/lua/stdlib.c1
-rw-r--r--src/nvim/main.c1
-rw-r--r--src/nvim/mbyte.c2
-rw-r--r--src/nvim/memline.c2
-rw-r--r--src/nvim/memory.c1
-rw-r--r--src/nvim/menu.c1
-rw-r--r--src/nvim/message.c47
-rw-r--r--src/nvim/misc1.c912
-rw-r--r--src/nvim/misc1.h10
-rw-r--r--src/nvim/mouse.c27
-rw-r--r--src/nvim/move.c2
-rw-r--r--src/nvim/msgpack_rpc/channel.c1
-rw-r--r--src/nvim/normal.c1
-rw-r--r--src/nvim/ops.c1
-rw-r--r--src/nvim/option.c1
-rw-r--r--src/nvim/os/fs.c1
-rw-r--r--src/nvim/os/input.c1
-rw-r--r--src/nvim/os/shell.c113
-rw-r--r--src/nvim/os/signal.c1
-rw-r--r--src/nvim/os/users.c60
-rw-r--r--src/nvim/os_unix.c1
-rw-r--r--src/nvim/path.c1
-rw-r--r--src/nvim/quickfix.c1
-rw-r--r--src/nvim/regexp.c1
-rw-r--r--src/nvim/runtime.c1
-rw-r--r--src/nvim/screen.c1
-rw-r--r--src/nvim/search.c6
-rw-r--r--src/nvim/spell.c2
-rw-r--r--src/nvim/spellfile.c12
-rw-r--r--src/nvim/strings.c1
-rw-r--r--src/nvim/syntax.c1
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/terminal.c1
-rw-r--r--src/nvim/ui.c39
-rw-r--r--src/nvim/undo.c2
-rw-r--r--src/nvim/window.c1
68 files changed, 874 insertions, 991 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 718743ed9c..7988bff25a 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -29,7 +29,6 @@
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/undo.h"
diff --git a/src/nvim/aucmd.c b/src/nvim/aucmd.c
index a236b47027..d7f73fa4a1 100644
--- a/src/nvim/aucmd.c
+++ b/src/nvim/aucmd.c
@@ -8,7 +8,6 @@
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/main.h"
-#include "nvim/misc1.h"
#include "nvim/os/os.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 1daae85c5e..6227b08b26 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -76,6 +76,7 @@ return {
'QuickFixCmdPre', -- before :make, :grep etc.
'QuitPre', -- before :quit
'RemoteReply', -- upon string reception from a remote vim
+ 'SearchWrapped', -- after the search wrapped around
'SessionLoadPost', -- after loading a session file
'ShellCmdPost', -- after ":!cmd"
'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd".
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 0248230e15..3780cad1d6 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -15,7 +15,6 @@
#include "nvim/ex_docmd.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/regexp.h"
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 297d9743df..89baea83f8 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -57,7 +57,6 @@
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 96fbaa9166..1dbbfff024 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -19,7 +19,6 @@
#include "nvim/indent_c.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/plines.h"
@@ -1863,3 +1862,289 @@ void del_lines(long nlines, bool undo)
// adjust marks, mark the buffer as changed and prepare for displaying
deleted_lines_mark(first, n);
}
+
+/// Returns the length in bytes of the prefix of the given string which introduces a comment.
+///
+/// If this string is not a comment then 0 is returned.
+/// When "flags" is not NULL, it is set to point to the flags of the recognized comment leader.
+/// "backward" must be true for the "O" command.
+/// If "include_space" is set, include trailing whitespace while calculating the length.
+int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_space)
+{
+ int i, j;
+ int result;
+ int got_com = false;
+ int found_one;
+ char_u part_buf[COM_MAX_LEN]; // buffer for one option part
+ char_u *string; // pointer to comment string
+ char_u *list;
+ int middle_match_len = 0;
+ char_u *prev_list;
+ char_u *saved_flags = NULL;
+
+ result = i = 0;
+ while (ascii_iswhite(line[i])) { // leading white space is ignored
+ i++;
+ }
+
+ // Repeat to match several nested comment strings.
+ while (line[i] != NUL) {
+ // scan through the 'comments' option for a match
+ found_one = false;
+ for (list = curbuf->b_p_com; *list;) {
+ // Get one option part into part_buf[]. Advance "list" to next
+ // one. Put "string" at start of string.
+ if (!got_com && flags != NULL) {
+ *flags = list; // remember where flags started
+ }
+ prev_list = list;
+ (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
+ string = vim_strchr(part_buf, ':');
+ if (string == NULL) { // missing ':', ignore this part
+ continue;
+ }
+ *string++ = NUL; // isolate flags from string
+
+ // If we found a middle match previously, use that match when this
+ // is not a middle or end.
+ if (middle_match_len != 0
+ && vim_strchr(part_buf, COM_MIDDLE) == NULL
+ && vim_strchr(part_buf, COM_END) == NULL) {
+ break;
+ }
+
+ // When we already found a nested comment, only accept further
+ // nested comments.
+ if (got_com && vim_strchr(part_buf, COM_NEST) == NULL) {
+ continue;
+ }
+
+ // When 'O' flag present and using "O" command skip this one.
+ if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL) {
+ continue;
+ }
+
+ // Line contents and string must match.
+ // When string starts with white space, must have some white space
+ // (but the amount does not need to match, there might be a mix of
+ // TABs and spaces).
+ if (ascii_iswhite(string[0])) {
+ if (i == 0 || !ascii_iswhite(line[i - 1])) {
+ continue; // missing white space
+ }
+ while (ascii_iswhite(string[0])) {
+ string++;
+ }
+ }
+ for (j = 0; string[j] != NUL && string[j] == line[i + j]; j++) {
+ }
+ if (string[j] != NUL) {
+ continue; // string doesn't match
+ }
+ // When 'b' flag used, there must be white space or an
+ // end-of-line after the string in the line.
+ if (vim_strchr(part_buf, COM_BLANK) != NULL
+ && !ascii_iswhite(line[i + j]) && line[i + j] != NUL) {
+ continue;
+ }
+
+ // We have found a match, stop searching unless this is a middle
+ // comment. The middle comment can be a substring of the end
+ // comment in which case it's better to return the length of the
+ // end comment and its flags. Thus we keep searching with middle
+ // and end matches and use an end match if it matches better.
+ if (vim_strchr(part_buf, COM_MIDDLE) != NULL) {
+ if (middle_match_len == 0) {
+ middle_match_len = j;
+ saved_flags = prev_list;
+ }
+ continue;
+ }
+ if (middle_match_len != 0 && j > middle_match_len) {
+ // Use this match instead of the middle match, since it's a
+ // longer thus better match.
+ middle_match_len = 0;
+ }
+
+ if (middle_match_len == 0) {
+ i += j;
+ }
+ found_one = true;
+ break;
+ }
+
+ if (middle_match_len != 0) {
+ // Use the previously found middle match after failing to find a
+ // match with an end.
+ if (!got_com && flags != NULL) {
+ *flags = saved_flags;
+ }
+ i += middle_match_len;
+ found_one = true;
+ }
+
+ // No match found, stop scanning.
+ if (!found_one) {
+ break;
+ }
+
+ result = i;
+
+ // Include any trailing white space.
+ while (ascii_iswhite(line[i])) {
+ i++;
+ }
+
+ if (include_space) {
+ result = i;
+ }
+
+ // If this comment doesn't nest, stop here.
+ got_com = true;
+ if (vim_strchr(part_buf, COM_NEST) == NULL) {
+ break;
+ }
+ }
+ return result;
+}
+
+/// Return the offset at which the last comment in line starts. If there is no
+/// comment in the whole line, -1 is returned.
+///
+/// When "flags" is not null, it is set to point to the flags describing the
+/// recognized comment leader.
+int get_last_leader_offset(char_u *line, char_u **flags)
+{
+ int result = -1;
+ int i, j;
+ int lower_check_bound = 0;
+ char_u *string;
+ char_u *com_leader;
+ char_u *com_flags;
+ char_u *list;
+ int found_one;
+ char_u part_buf[COM_MAX_LEN]; // buffer for one option part
+
+ // Repeat to match several nested comment strings.
+ i = (int)STRLEN(line);
+ while (--i >= lower_check_bound) {
+ // scan through the 'comments' option for a match
+ found_one = false;
+ for (list = curbuf->b_p_com; *list;) {
+ char_u *flags_save = list;
+
+ // Get one option part into part_buf[]. Advance list to next one.
+ // put string at start of string.
+ (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
+ string = vim_strchr(part_buf, ':');
+ if (string == NULL) { // If everything is fine, this cannot actually
+ // happen.
+ continue;
+ }
+ *string++ = NUL; // Isolate flags from string.
+ com_leader = string;
+
+ // Line contents and string must match.
+ // When string starts with white space, must have some white space
+ // (but the amount does not need to match, there might be a mix of
+ // TABs and spaces).
+ if (ascii_iswhite(string[0])) {
+ if (i == 0 || !ascii_iswhite(line[i - 1])) {
+ continue;
+ }
+ while (ascii_iswhite(*string)) {
+ string++;
+ }
+ }
+ for (j = 0; string[j] != NUL && string[j] == line[i + j]; j++) {
+ // do nothing
+ }
+ if (string[j] != NUL) {
+ continue;
+ }
+
+ // When 'b' flag used, there must be white space or an
+ // end-of-line after the string in the line.
+ if (vim_strchr(part_buf, COM_BLANK) != NULL
+ && !ascii_iswhite(line[i + j]) && line[i + j] != NUL) {
+ continue;
+ }
+
+ if (vim_strchr(part_buf, COM_MIDDLE) != NULL) {
+ // For a middlepart comment, only consider it to match if
+ // everything before the current position in the line is
+ // whitespace. Otherwise we would think we are inside a
+ // comment if the middle part appears somewhere in the middle
+ // of the line. E.g. for C the "*" appears often.
+ for (j = 0; j <= i && ascii_iswhite(line[j]); j++) {
+ }
+ if (j < i) {
+ continue;
+ }
+ }
+
+ // We have found a match, stop searching.
+ found_one = true;
+
+ if (flags) {
+ *flags = flags_save;
+ }
+ com_flags = flags_save;
+
+ break;
+ }
+
+ if (found_one) {
+ char_u part_buf2[COM_MAX_LEN]; // buffer for one option part
+ int len1, len2, off;
+
+ result = i;
+ // If this comment nests, continue searching.
+ if (vim_strchr(part_buf, COM_NEST) != NULL) {
+ continue;
+ }
+
+ lower_check_bound = i;
+
+ // Let's verify whether the comment leader found is a substring
+ // of other comment leaders. If it is, let's adjust the
+ // lower_check_bound so that we make sure that we have determined
+ // the comment leader correctly.
+
+ while (ascii_iswhite(*com_leader)) {
+ com_leader++;
+ }
+ len1 = (int)STRLEN(com_leader);
+
+ for (list = curbuf->b_p_com; *list;) {
+ char_u *flags_save = list;
+
+ (void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
+ if (flags_save == com_flags) {
+ continue;
+ }
+ string = vim_strchr(part_buf2, ':');
+ string++;
+ while (ascii_iswhite(*string)) {
+ string++;
+ }
+ len2 = (int)STRLEN(string);
+ if (len2 == 0) {
+ continue;
+ }
+
+ // Now we have to verify whether string ends with a substring
+ // beginning the com_leader.
+ for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;) {
+ off--;
+ if (!STRNCMP(string + off, com_leader, len2 - off)) {
+ if (i - off < lower_check_bound) {
+ lower_check_bound = i - off;
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index a662f3a951..cd5134fe5f 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -10,7 +10,6 @@
#include "nvim/event/socket.h"
#include "nvim/fileio.h"
#include "nvim/lua/executor.h"
-#include "nvim/misc1.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/os/shell.h"
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index eb0903b594..599d662993 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -21,7 +21,6 @@
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/os_unix.h"
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 4e1d7f9d78..6e2c6232d7 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -14,7 +14,6 @@
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/plines.h"
#include "nvim/screen.h"
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 1f8acd8c79..0233b3a5ab 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -29,7 +29,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
@@ -39,6 +38,7 @@
#include "nvim/screen.h"
#include "nvim/strings.h"
#include "nvim/undo.h"
+#include "nvim/ui.h"
#include "nvim/vim.h"
#include "nvim/window.h"
#include "xdiff/xdiff.h"
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index d1dd9b8309..8eda173cac 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -20,7 +20,6 @@
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/normal.h"
#include "nvim/os/input.h"
#include "nvim/screen.h"
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 9bfb8a9d4a..2135d0bcd2 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -35,7 +35,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
@@ -832,6 +831,16 @@ static int insert_execute(VimState *state, int key)
return insert_handle_key(s);
}
+
+/// Return true when need to go to Insert mode because of 'insertmode'.
+///
+/// Don't do this when still processing a command or a mapping.
+/// Don't do this when inside a ":normal" command.
+bool goto_im(void)
+{
+ return p_im && stuff_empty() && typebuf_typed();
+}
+
static int insert_handle_key(InsertState *s)
{
// The big switch to handle a character in insert mode.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d45aa8194c..86384bc5b2 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -35,7 +35,6 @@
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/option.h"
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 33ca4016cf..5252c940f7 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -33,12 +33,12 @@
#include "nvim/if_cscope.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
+#include "nvim/input.h"
#include "nvim/lua/executor.h"
#include "nvim/macros.h"
#include "nvim/mark.h"
#include "nvim/math.h"
#include "nvim/memline.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index dfb2500b49..11bbaaed9c 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -32,8 +32,6 @@
#include "nvim/pos.h"
#include "nvim/types.h"
#include "nvim/vim.h"
-// TODO(ZyX-I): Move line_breakcheck out of misc1
-#include "nvim/misc1.h" // For line_breakcheck
#include "nvim/os/fileio.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 9478a8441b..eb241eb8ae 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -17,7 +17,6 @@
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
-#include "nvim/misc1.h"
#include "nvim/os/input.h"
#include "nvim/regexp.h"
#include "nvim/search.h"
diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c
index 755307781c..3c43d1f98d 100644
--- a/src/nvim/event/rstream.c
+++ b/src/nvim/event/rstream.c
@@ -13,7 +13,6 @@
#include "nvim/log.h"
#include "nvim/memory.h"
#include "nvim/main.h"
-#include "nvim/misc1.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index f95fe84f69..c0cb17fa61 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -39,6 +39,7 @@
#include "nvim/getchar.h"
#include "nvim/highlight.h"
#include "nvim/indent.h"
+#include "nvim/input.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/mark.h"
@@ -46,7 +47,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 2dc098df8c..33f9477608 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -35,7 +35,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/ops.h"
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4c040bff7f..9f0f8d93a3 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -39,6 +39,7 @@
#include "nvim/globals.h"
#include "nvim/hardcopy.h"
#include "nvim/if_cscope.h"
+#include "nvim/input.h"
#include "nvim/keymap.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
@@ -48,7 +49,6 @@
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 475f22d061..ba2238ace2 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -48,7 +48,6 @@
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/ops.h"
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index f80a63560c..a37cad9f2d 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -28,7 +28,6 @@
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/keymap.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 5953a574f3..d31021b3ef 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -57,7 +57,6 @@
#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 24428c2d9a..f8cf341836 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -30,12 +30,12 @@
#include "nvim/getchar.h"
#include "nvim/hashtab.h"
#include "nvim/iconv.h"
+#include "nvim/input.h"
#include "nvim/mbyte.h"
#include "nvim/memfile.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 7806d3eada..b1d4321d4c 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -28,7 +28,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/option.h"
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 27e8cb36af..05c38a5233 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -29,6 +29,7 @@
#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
+#include "nvim/input.h"
#include "nvim/keymap.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
@@ -36,7 +37,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/ops.h"
@@ -458,6 +458,15 @@ void flush_buffers(flush_buffers_T flush_typeahead)
}
}
+/// flush map and typeahead buffers and give a warning for an error
+void beep_flush(void)
+{
+ if (emsg_silent == 0) {
+ flush_buffers(FLUSH_MINIMAL);
+ vim_beep(BO_ERROR);
+ }
+}
+
/*
* The previous contents of the redo buffer is kept in old_redobuffer.
* This is used for the CTRL-O <.> command in insert mode.
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 938e9c7db7..dfbc80066e 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -202,7 +202,6 @@ EXTERN bool msg_did_scroll INIT(= false);
EXTERN char_u *keep_msg INIT(= NULL); // msg to be shown after redraw
EXTERN int keep_msg_attr INIT(= 0); // highlight attr for keep_msg
-EXTERN bool keep_msg_more INIT(= false); // keep_msg was set by msgmore()
EXTERN bool need_fileinfo INIT(= false); // do fileinfo() after redraw
EXTERN int msg_scroll INIT(= false); // msg_start() will scroll
EXTERN bool msg_didout INIT(= false); // msg_outstr() was used in line
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index f49aff6643..8cc5bc2436 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -17,7 +17,6 @@
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/plines.h"
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 3e3e07e9d6..faa9b38cf7 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -8,7 +8,6 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
-#include "nvim/misc1.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/edit.h"
diff --git a/src/nvim/input.c b/src/nvim/input.c
new file mode 100644
index 0000000000..2f7c5c2c16
--- /dev/null
+++ b/src/nvim/input.c
@@ -0,0 +1,255 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+// input.c: high level functions for prompting the user or input
+// like yes/no or number prompts.
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "nvim/func_attr.h"
+#include "nvim/getchar.h"
+#include "nvim/mbyte.h"
+#include "nvim/memory.h"
+#include "nvim/input.h"
+#include "nvim/mouse.h"
+#include "nvim/os/input.h"
+#include "nvim/ui.h"
+#include "nvim/vim.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "input.c.generated.h"
+#endif
+
+/// Ask for a reply from the user, 'y' or 'n'
+///
+/// No other characters are accepted, the message is repeated until a valid
+/// reply is entered or <C-c> is hit.
+///
+/// @param[in] str Prompt: question to ask user. Is always followed by
+/// " (y/n)?".
+/// @param[in] direct Determines what function to use to get user input. If
+/// true then ui_inchar() will be used, otherwise vgetc().
+/// I.e. when direct is true then characters are obtained
+/// directly from the user without buffers involved.
+///
+/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt.
+int ask_yesno(const char *const str, const bool direct)
+{
+ const int save_State = State;
+
+ no_wait_return++;
+ State = CONFIRM; // Mouse behaves like with :confirm.
+ setmouse(); // Disable mouse in xterm.
+ no_mapping++;
+
+ int r = ' ';
+ while (r != 'y' && r != 'n') {
+ // Same highlighting as for wait_return.
+ smsg_attr(HL_ATTR(HLF_R), "%s (y/n)?", str);
+ if (direct) {
+ r = get_keystroke(NULL);
+ } else {
+ r = plain_vgetc();
+ }
+ if (r == Ctrl_C || r == ESC) {
+ r = 'n';
+ }
+ msg_putchar(r); // Show what you typed.
+ ui_flush();
+ }
+ no_wait_return--;
+ State = save_State;
+ setmouse();
+ no_mapping--;
+
+ return r;
+}
+
+/// Get a key stroke directly from the user.
+///
+/// Ignores mouse clicks and scrollbar events, except a click for the left
+/// button (used at the more prompt).
+/// Doesn't use vgetc(), because it syncs undo and eats mapped characters.
+/// Disadvantage: typeahead is ignored.
+/// Translates the interrupt character for unix to ESC.
+int get_keystroke(MultiQueue *events)
+{
+ char_u *buf = NULL;
+ int buflen = 150;
+ int maxlen;
+ int len = 0;
+ int n;
+ int save_mapped_ctrl_c = mapped_ctrl_c;
+ int waited = 0;
+
+ mapped_ctrl_c = 0; // mappings are not used here
+ for (;;) {
+ // flush output before waiting
+ ui_flush();
+ // Leave some room for check_termcode() to insert a key code into (max
+ // 5 chars plus NUL). And fix_input_buffer() can triple the number of
+ // bytes.
+ maxlen = (buflen - 6 - len) / 3;
+ if (buf == NULL) {
+ buf = xmalloc((size_t)buflen);
+ } else if (maxlen < 10) {
+ // Need some more space. This might happen when receiving a long
+ // escape sequence.
+ buflen += 100;
+ buf = xrealloc(buf, (size_t)buflen);
+ maxlen = (buflen - 6 - len) / 3;
+ }
+
+ // First time: blocking wait. Second time: wait up to 100ms for a
+ // terminal code to complete.
+ n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0, events);
+ if (n > 0) {
+ // Replace zero and CSI by a special key code.
+ n = fix_input_buffer(buf + len, n);
+ len += n;
+ waited = 0;
+ } else if (len > 0) {
+ waited++; // keep track of the waiting time
+ }
+ if (n > 0) { // found a termcode: adjust length
+ len = n;
+ }
+ if (len == 0) { // nothing typed yet
+ continue;
+ }
+
+ // Handle modifier and/or special key code.
+ n = buf[0];
+ if (n == K_SPECIAL) {
+ n = TO_SPECIAL(buf[1], buf[2]);
+ if (buf[1] == KS_MODIFIER
+ || n == K_IGNORE
+ || (is_mouse_key(n) && n != K_LEFTMOUSE)) {
+ if (buf[1] == KS_MODIFIER) {
+ mod_mask = buf[2];
+ }
+ len -= 3;
+ if (len > 0) {
+ memmove(buf, buf + 3, (size_t)len);
+ }
+ continue;
+ }
+ break;
+ }
+ if (MB_BYTE2LEN(n) > len) {
+ // more bytes to get.
+ continue;
+ }
+ buf[len >= buflen ? buflen - 1 : len] = NUL;
+ n = utf_ptr2char(buf);
+ break;
+ }
+ xfree(buf);
+
+ mapped_ctrl_c = save_mapped_ctrl_c;
+ return n;
+}
+
+/// Get a number from the user.
+/// When "mouse_used" is not NULL allow using the mouse.
+///
+/// @param colon allow colon to abort
+int get_number(int colon, int *mouse_used)
+{
+ int n = 0;
+ int c;
+ int typed = 0;
+
+ if (mouse_used != NULL) {
+ *mouse_used = false;
+ }
+
+ // When not printing messages, the user won't know what to type, return a
+ // zero (as if CR was hit).
+ if (msg_silent != 0) {
+ return 0;
+ }
+
+ no_mapping++;
+ for (;;) {
+ ui_cursor_goto(msg_row, msg_col);
+ c = safe_vgetc();
+ if (ascii_isdigit(c)) {
+ n = n * 10 + c - '0';
+ msg_putchar(c);
+ typed++;
+ } else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H) {
+ if (typed > 0) {
+ msg_puts("\b \b");
+ typed--;
+ }
+ n /= 10;
+ } else if (mouse_used != NULL && c == K_LEFTMOUSE) {
+ *mouse_used = true;
+ n = mouse_row + 1;
+ break;
+ } else if (n == 0 && c == ':' && colon) {
+ stuffcharReadbuff(':');
+ if (!exmode_active) {
+ cmdline_row = msg_row;
+ }
+ skip_redraw = true; // skip redraw once
+ do_redraw = false;
+ break;
+ } else if (c == Ctrl_C || c == ESC || c == 'q') {
+ n = 0;
+ break;
+ } else if (c == CAR || c == NL) {
+ break;
+ }
+ }
+ no_mapping--;
+ return n;
+}
+
+/// Ask the user to enter a number.
+///
+/// When "mouse_used" is not NULL allow using the mouse and in that case return
+/// the line number.
+int prompt_for_number(int *mouse_used)
+{
+ int i;
+ int save_cmdline_row;
+ int save_State;
+
+ // When using ":silent" assume that <CR> was entered.
+ if (mouse_used != NULL) {
+ msg_puts(_("Type number and <Enter> or click with the mouse "
+ "(q or empty cancels): "));
+ } else {
+ msg_puts(_("Type number and <Enter> (q or empty cancels): "));
+ }
+
+ // Set the state such that text can be selected/copied/pasted and we still
+ // get mouse events.
+ save_cmdline_row = cmdline_row;
+ cmdline_row = 0;
+ save_State = State;
+ State = ASKMORE; // prevents a screen update when using a timer
+ // May show different mouse shape.
+ setmouse();
+
+ i = get_number(true, mouse_used);
+ if (KeyTyped) {
+ // don't call wait_return() now
+ if (msg_row > 0) {
+ cmdline_row = msg_row - 1;
+ }
+ need_wait_return = false;
+ msg_didany = false;
+ msg_didout = false;
+ } else {
+ cmdline_row = save_cmdline_row;
+ }
+ State = save_State;
+ // May need to restore mouse shape.
+ setmouse();
+
+ return i;
+}
diff --git a/src/nvim/input.h b/src/nvim/input.h
new file mode 100644
index 0000000000..7975f21215
--- /dev/null
+++ b/src/nvim/input.h
@@ -0,0 +1,9 @@
+#ifndef NVIM_INPUT_H
+#define NVIM_INPUT_H
+
+#include "nvim/vim.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "input.h.generated.h"
+#endif
+#endif // NVIM_INPUT_H
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index a899ca63ac..b09d133495 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -31,7 +31,6 @@
#include "nvim/map.h"
#include "nvim/memline.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/os/os.h"
#include "nvim/screen.h"
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index b5553060a1..b746e03625 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -34,7 +34,6 @@
#include "nvim/map.h"
#include "nvim/memline.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/os/os.h"
#include "nvim/regexp.h"
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 29510e26ff..cbd1f53727 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -39,7 +39,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 42117bc762..ce44f6c619 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -42,13 +42,13 @@
#include "nvim/eval.h"
#include "nvim/fileio.h"
#include "nvim/func_attr.h"
+#include "nvim/getchar.h"
#include "nvim/iconv.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 40da4b48f8..08521c0dc3 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -51,6 +51,7 @@
#include "nvim/fileio.h"
#include "nvim/func_attr.h"
#include "nvim/getchar.h"
+#include "nvim/input.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
@@ -58,7 +59,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 3d621ebbb7..677ff8f522 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -17,7 +17,6 @@
#include "nvim/memfile.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/sign.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index d596b31062..ac4d52c392 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -22,7 +22,6 @@
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/screen.h"
#include "nvim/state.h"
#include "nvim/strings.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index eaf7e2622a..befca8c76b 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -23,12 +23,12 @@
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
+#include "nvim/input.h"
#include "nvim/keymap.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/normal.h"
#include "nvim/ops.h"
@@ -76,6 +76,8 @@ static int msg_hist_len = 0;
static FILE *verbose_fd = NULL;
static int verbose_did_open = FALSE;
+bool keep_msg_more = false; // keep_msg was set by msgmore()
+
/*
* When writing messages to the screen, there are many different situations.
* A number of variables is used to remember the current state:
@@ -1298,6 +1300,49 @@ void set_keep_msg(char *s, int attr)
keep_msg_attr = attr;
}
+void msgmore(long n)
+{
+ long pn;
+
+ if (global_busy // no messages now, wait until global is finished
+ || !messaging()) { // 'lazyredraw' set, don't do messages now
+ return;
+ }
+
+ // We don't want to overwrite another important message, but do overwrite
+ // a previous "more lines" or "fewer lines" message, so that "5dd" and
+ // then "put" reports the last action.
+ if (keep_msg != NULL && !keep_msg_more) {
+ return;
+ }
+
+ if (n > 0) {
+ pn = n;
+ } else {
+ pn = -n;
+ }
+
+ if (pn > p_report) {
+ if (n > 0) {
+ vim_snprintf(msg_buf, MSG_BUF_LEN,
+ NGETTEXT("%ld more line", "%ld more lines", pn),
+ pn);
+ } else {
+ vim_snprintf(msg_buf, MSG_BUF_LEN,
+ NGETTEXT("%ld line less", "%ld fewer lines", pn),
+ pn);
+ }
+ if (got_int) {
+ xstrlcat(msg_buf, _(" (Interrupted)"), MSG_BUF_LEN);
+ }
+ if (msg(msg_buf)) {
+ set_keep_msg(msg_buf, 0);
+ keep_msg_more = true;
+ }
+ }
+}
+
+
void msg_ext_set_kind(const char *msg_kind)
{
// Don't change the label of an existing batch:
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
deleted file mode 100644
index 3873a5c49a..0000000000
--- a/src/nvim/misc1.c
+++ /dev/null
@@ -1,912 +0,0 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
-/*
- * misc1.c: functions that didn't seem to fit elsewhere
- */
-
-#include <assert.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include "nvim/ascii.h"
-#include "nvim/buffer.h"
-#include "nvim/buffer_updates.h"
-#include "nvim/charset.h"
-#include "nvim/cursor.h"
-#include "nvim/diff.h"
-#include "nvim/edit.h"
-#include "nvim/eval.h"
-#include "nvim/event/stream.h"
-#include "nvim/ex_cmds.h"
-#include "nvim/ex_docmd.h"
-#include "nvim/ex_getln.h"
-#include "nvim/fileio.h"
-#include "nvim/fold.h"
-#include "nvim/func_attr.h"
-#include "nvim/garray.h"
-#include "nvim/getchar.h"
-#include "nvim/indent.h"
-#include "nvim/indent_c.h"
-#include "nvim/main.h"
-#include "nvim/mbyte.h"
-#include "nvim/memline.h"
-#include "nvim/memory.h"
-#include "nvim/message.h"
-#include "nvim/misc1.h"
-#include "nvim/mouse.h"
-#include "nvim/move.h"
-#include "nvim/option.h"
-#include "nvim/os/input.h"
-#include "nvim/os/os.h"
-#include "nvim/os/shell.h"
-#include "nvim/os/signal.h"
-#include "nvim/os/time.h"
-#include "nvim/os_unix.h"
-#include "nvim/quickfix.h"
-#include "nvim/regexp.h"
-#include "nvim/screen.h"
-#include "nvim/search.h"
-#include "nvim/state.h"
-#include "nvim/strings.h"
-#include "nvim/tag.h"
-#include "nvim/ui.h"
-#include "nvim/undo.h"
-#include "nvim/vim.h"
-#include "nvim/window.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "misc1.c.generated.h"
-#endif
-// All user names (for ~user completion as done by shell).
-static garray_T ga_users = GA_EMPTY_INIT_VALUE;
-
-/*
- * get_leader_len() returns the length in bytes of the prefix of the given
- * string which introduces a comment. If this string is not a comment then
- * 0 is returned.
- * When "flags" is not NULL, it is set to point to the flags of the recognized
- * comment leader.
- * "backward" must be true for the "O" command.
- * If "include_space" is set, include trailing whitespace while calculating the
- * length.
- */
-int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_space)
-{
- int i, j;
- int result;
- int got_com = FALSE;
- int found_one;
- char_u part_buf[COM_MAX_LEN]; // buffer for one option part
- char_u *string; // pointer to comment string
- char_u *list;
- int middle_match_len = 0;
- char_u *prev_list;
- char_u *saved_flags = NULL;
-
- result = i = 0;
- while (ascii_iswhite(line[i])) { // leading white space is ignored
- ++i;
- }
-
- /*
- * Repeat to match several nested comment strings.
- */
- while (line[i] != NUL) {
- /*
- * scan through the 'comments' option for a match
- */
- found_one = FALSE;
- for (list = curbuf->b_p_com; *list;) {
- // Get one option part into part_buf[]. Advance "list" to next
- // one. Put "string" at start of string.
- if (!got_com && flags != NULL) {
- *flags = list; // remember where flags started
- }
- prev_list = list;
- (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
- string = vim_strchr(part_buf, ':');
- if (string == NULL) { // missing ':', ignore this part
- continue;
- }
- *string++ = NUL; // isolate flags from string
-
- // If we found a middle match previously, use that match when this
- // is not a middle or end.
- if (middle_match_len != 0
- && vim_strchr(part_buf, COM_MIDDLE) == NULL
- && vim_strchr(part_buf, COM_END) == NULL) {
- break;
- }
-
- // When we already found a nested comment, only accept further
- // nested comments.
- if (got_com && vim_strchr(part_buf, COM_NEST) == NULL) {
- continue;
- }
-
- // When 'O' flag present and using "O" command skip this one.
- if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL) {
- continue;
- }
-
- // Line contents and string must match.
- // When string starts with white space, must have some white space
- // (but the amount does not need to match, there might be a mix of
- // TABs and spaces).
- if (ascii_iswhite(string[0])) {
- if (i == 0 || !ascii_iswhite(line[i - 1])) {
- continue; // missing white space
- }
- while (ascii_iswhite(string[0])) {
- ++string;
- }
- }
- for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) {
- }
- if (string[j] != NUL) {
- continue; // string doesn't match
- }
- // When 'b' flag used, there must be white space or an
- // end-of-line after the string in the line.
- if (vim_strchr(part_buf, COM_BLANK) != NULL
- && !ascii_iswhite(line[i + j]) && line[i + j] != NUL) {
- continue;
- }
-
- // We have found a match, stop searching unless this is a middle
- // comment. The middle comment can be a substring of the end
- // comment in which case it's better to return the length of the
- // end comment and its flags. Thus we keep searching with middle
- // and end matches and use an end match if it matches better.
- if (vim_strchr(part_buf, COM_MIDDLE) != NULL) {
- if (middle_match_len == 0) {
- middle_match_len = j;
- saved_flags = prev_list;
- }
- continue;
- }
- if (middle_match_len != 0 && j > middle_match_len) {
- // Use this match instead of the middle match, since it's a
- // longer thus better match.
- middle_match_len = 0;
- }
-
- if (middle_match_len == 0) {
- i += j;
- }
- found_one = TRUE;
- break;
- }
-
- if (middle_match_len != 0) {
- // Use the previously found middle match after failing to find a
- // match with an end.
- if (!got_com && flags != NULL) {
- *flags = saved_flags;
- }
- i += middle_match_len;
- found_one = TRUE;
- }
-
- // No match found, stop scanning.
- if (!found_one) {
- break;
- }
-
- result = i;
-
- // Include any trailing white space.
- while (ascii_iswhite(line[i])) {
- ++i;
- }
-
- if (include_space) {
- result = i;
- }
-
- // If this comment doesn't nest, stop here.
- got_com = TRUE;
- if (vim_strchr(part_buf, COM_NEST) == NULL) {
- break;
- }
- }
- return result;
-}
-
-/*
- * Return the offset at which the last comment in line starts. If there is no
- * comment in the whole line, -1 is returned.
- *
- * When "flags" is not null, it is set to point to the flags describing the
- * recognized comment leader.
- */
-int get_last_leader_offset(char_u *line, char_u **flags)
-{
- int result = -1;
- int i, j;
- int lower_check_bound = 0;
- char_u *string;
- char_u *com_leader;
- char_u *com_flags;
- char_u *list;
- int found_one;
- char_u part_buf[COM_MAX_LEN]; // buffer for one option part
-
- /*
- * Repeat to match several nested comment strings.
- */
- i = (int)STRLEN(line);
- while (--i >= lower_check_bound) {
- /*
- * scan through the 'comments' option for a match
- */
- found_one = FALSE;
- for (list = curbuf->b_p_com; *list;) {
- char_u *flags_save = list;
-
- /*
- * Get one option part into part_buf[]. Advance list to next one.
- * put string at start of string.
- */
- (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
- string = vim_strchr(part_buf, ':');
- if (string == NULL) { // If everything is fine, this cannot actually
- // happen.
- continue;
- }
- *string++ = NUL; // Isolate flags from string.
- com_leader = string;
-
- /*
- * Line contents and string must match.
- * When string starts with white space, must have some white space
- * (but the amount does not need to match, there might be a mix of
- * TABs and spaces).
- */
- if (ascii_iswhite(string[0])) {
- if (i == 0 || !ascii_iswhite(line[i - 1])) {
- continue;
- }
- while (ascii_iswhite(*string)) {
- string++;
- }
- }
- for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) {
- // do nothing
- }
- if (string[j] != NUL) {
- continue;
- }
-
- /*
- * When 'b' flag used, there must be white space or an
- * end-of-line after the string in the line.
- */
- if (vim_strchr(part_buf, COM_BLANK) != NULL
- && !ascii_iswhite(line[i + j]) && line[i + j] != NUL) {
- continue;
- }
-
- if (vim_strchr(part_buf, COM_MIDDLE) != NULL) {
- // For a middlepart comment, only consider it to match if
- // everything before the current position in the line is
- // whitespace. Otherwise we would think we are inside a
- // comment if the middle part appears somewhere in the middle
- // of the line. E.g. for C the "*" appears often.
- for (j = 0; j <= i && ascii_iswhite(line[j]); j++) {
- }
- if (j < i) {
- continue;
- }
- }
-
- /*
- * We have found a match, stop searching.
- */
- found_one = TRUE;
-
- if (flags) {
- *flags = flags_save;
- }
- com_flags = flags_save;
-
- break;
- }
-
- if (found_one) {
- char_u part_buf2[COM_MAX_LEN]; // buffer for one option part
- int len1, len2, off;
-
- result = i;
- /*
- * If this comment nests, continue searching.
- */
- if (vim_strchr(part_buf, COM_NEST) != NULL) {
- continue;
- }
-
- lower_check_bound = i;
-
- // Let's verify whether the comment leader found is a substring
- // of other comment leaders. If it is, let's adjust the
- // lower_check_bound so that we make sure that we have determined
- // the comment leader correctly.
-
- while (ascii_iswhite(*com_leader)) {
- ++com_leader;
- }
- len1 = (int)STRLEN(com_leader);
-
- for (list = curbuf->b_p_com; *list;) {
- char_u *flags_save = list;
-
- (void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
- if (flags_save == com_flags) {
- continue;
- }
- string = vim_strchr(part_buf2, ':');
- ++string;
- while (ascii_iswhite(*string)) {
- ++string;
- }
- len2 = (int)STRLEN(string);
- if (len2 == 0) {
- continue;
- }
-
- // Now we have to verify whether string ends with a substring
- // beginning the com_leader.
- for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;) {
- --off;
- if (!STRNCMP(string + off, com_leader, len2 - off)) {
- if (i - off < lower_check_bound) {
- lower_check_bound = i - off;
- }
- }
- }
- }
- }
- }
- return result;
-}
-
-/// Ask for a reply from the user, 'y' or 'n'
-///
-/// No other characters are accepted, the message is repeated until a valid
-/// reply is entered or <C-c> is hit.
-///
-/// @param[in] str Prompt: question to ask user. Is always followed by
-/// " (y/n)?".
-/// @param[in] direct Determines what function to use to get user input. If
-/// true then ui_inchar() will be used, otherwise vgetc().
-/// I.e. when direct is true then characters are obtained
-/// directly from the user without buffers involved.
-///
-/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt.
-int ask_yesno(const char *const str, const bool direct)
-{
- const int save_State = State;
-
- no_wait_return++;
- State = CONFIRM; // Mouse behaves like with :confirm.
- setmouse(); // Disable mouse in xterm.
- no_mapping++;
-
- int r = ' ';
- while (r != 'y' && r != 'n') {
- // Same highlighting as for wait_return.
- smsg_attr(HL_ATTR(HLF_R), "%s (y/n)?", str);
- if (direct) {
- r = get_keystroke(NULL);
- } else {
- r = plain_vgetc();
- }
- if (r == Ctrl_C || r == ESC) {
- r = 'n';
- }
- msg_putchar(r); // Show what you typed.
- ui_flush();
- }
- no_wait_return--;
- State = save_State;
- setmouse();
- no_mapping--;
-
- return r;
-}
-
-/*
- * Return TRUE if "c" is a mouse key.
- */
-int is_mouse_key(int c)
-{
- return c == K_LEFTMOUSE
- || c == K_LEFTMOUSE_NM
- || c == K_LEFTDRAG
- || c == K_LEFTRELEASE
- || c == K_LEFTRELEASE_NM
- || c == K_MOUSEMOVE
- || c == K_MIDDLEMOUSE
- || c == K_MIDDLEDRAG
- || c == K_MIDDLERELEASE
- || c == K_RIGHTMOUSE
- || c == K_RIGHTDRAG
- || c == K_RIGHTRELEASE
- || c == K_MOUSEDOWN
- || c == K_MOUSEUP
- || c == K_MOUSELEFT
- || c == K_MOUSERIGHT
- || c == K_X1MOUSE
- || c == K_X1DRAG
- || c == K_X1RELEASE
- || c == K_X2MOUSE
- || c == K_X2DRAG
- || c == K_X2RELEASE;
-}
-
-/*
- * Get a key stroke directly from the user.
- * Ignores mouse clicks and scrollbar events, except a click for the left
- * button (used at the more prompt).
- * Doesn't use vgetc(), because it syncs undo and eats mapped characters.
- * Disadvantage: typeahead is ignored.
- * Translates the interrupt character for unix to ESC.
- */
-int get_keystroke(MultiQueue *events)
-{
- char_u *buf = NULL;
- int buflen = 150;
- int maxlen;
- int len = 0;
- int n;
- int save_mapped_ctrl_c = mapped_ctrl_c;
- int waited = 0;
-
- mapped_ctrl_c = 0; // mappings are not used here
- for (;;) {
- // flush output before waiting
- ui_flush();
- // Leave some room for check_termcode() to insert a key code into (max
- // 5 chars plus NUL). And fix_input_buffer() can triple the number of
- // bytes.
- maxlen = (buflen - 6 - len) / 3;
- if (buf == NULL) {
- buf = xmalloc((size_t)buflen);
- } else if (maxlen < 10) {
- // Need some more space. This might happen when receiving a long
- // escape sequence.
- buflen += 100;
- buf = xrealloc(buf, (size_t)buflen);
- maxlen = (buflen - 6 - len) / 3;
- }
-
- // First time: blocking wait. Second time: wait up to 100ms for a
- // terminal code to complete.
- n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0, events);
- if (n > 0) {
- // Replace zero and CSI by a special key code.
- n = fix_input_buffer(buf + len, n);
- len += n;
- waited = 0;
- } else if (len > 0) {
- ++waited; // keep track of the waiting time
- }
- if (n > 0) { // found a termcode: adjust length
- len = n;
- }
- if (len == 0) { // nothing typed yet
- continue;
- }
-
- // Handle modifier and/or special key code.
- n = buf[0];
- if (n == K_SPECIAL) {
- n = TO_SPECIAL(buf[1], buf[2]);
- if (buf[1] == KS_MODIFIER
- || n == K_IGNORE
- || (is_mouse_key(n) && n != K_LEFTMOUSE)) {
- if (buf[1] == KS_MODIFIER) {
- mod_mask = buf[2];
- }
- len -= 3;
- if (len > 0) {
- memmove(buf, buf + 3, (size_t)len);
- }
- continue;
- }
- break;
- }
- if (MB_BYTE2LEN(n) > len) {
- // more bytes to get.
- continue;
- }
- buf[len >= buflen ? buflen - 1 : len] = NUL;
- n = utf_ptr2char(buf);
- break;
- }
- xfree(buf);
-
- mapped_ctrl_c = save_mapped_ctrl_c;
- return n;
-}
-
-/// Get a number from the user.
-/// When "mouse_used" is not NULL allow using the mouse.
-///
-/// @param colon allow colon to abort
-int get_number(int colon, int *mouse_used)
-{
- int n = 0;
- int c;
- int typed = 0;
-
- if (mouse_used != NULL) {
- *mouse_used = FALSE;
- }
-
- // When not printing messages, the user won't know what to type, return a
- // zero (as if CR was hit).
- if (msg_silent != 0) {
- return 0;
- }
-
- no_mapping++;
- for (;;) {
- ui_cursor_goto(msg_row, msg_col);
- c = safe_vgetc();
- if (ascii_isdigit(c)) {
- n = n * 10 + c - '0';
- msg_putchar(c);
- ++typed;
- } else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H) {
- if (typed > 0) {
- msg_puts("\b \b");
- --typed;
- }
- n /= 10;
- } else if (mouse_used != NULL && c == K_LEFTMOUSE) {
- *mouse_used = TRUE;
- n = mouse_row + 1;
- break;
- } else if (n == 0 && c == ':' && colon) {
- stuffcharReadbuff(':');
- if (!exmode_active) {
- cmdline_row = msg_row;
- }
- skip_redraw = true; // skip redraw once
- do_redraw = false;
- break;
- } else if (c == Ctrl_C || c == ESC || c == 'q') {
- n = 0;
- break;
- } else if (c == CAR || c == NL) {
- break;
- }
- }
- no_mapping--;
- return n;
-}
-
-/*
- * Ask the user to enter a number.
- * When "mouse_used" is not NULL allow using the mouse and in that case return
- * the line number.
- */
-int prompt_for_number(int *mouse_used)
-{
- int i;
- int save_cmdline_row;
- int save_State;
-
- // When using ":silent" assume that <CR> was entered.
- if (mouse_used != NULL) {
- msg_puts(_("Type number and <Enter> or click with the mouse "
- "(q or empty cancels): "));
- } else {
- msg_puts(_("Type number and <Enter> (q or empty cancels): "));
- }
-
- /* Set the state such that text can be selected/copied/pasted and we still
- * get mouse events. */
- save_cmdline_row = cmdline_row;
- cmdline_row = 0;
- save_State = State;
- State = ASKMORE; // prevents a screen update when using a timer
- // May show different mouse shape.
- setmouse();
-
- i = get_number(TRUE, mouse_used);
- if (KeyTyped) {
- // don't call wait_return() now
- if (msg_row > 0) {
- cmdline_row = msg_row - 1;
- }
- need_wait_return = false;
- msg_didany = false;
- msg_didout = false;
- } else {
- cmdline_row = save_cmdline_row;
- }
- State = save_State;
- // May need to restore mouse shape.
- setmouse();
-
- return i;
-}
-
-void msgmore(long n)
-{
- long pn;
-
- if (global_busy // no messages now, wait until global is finished
- || !messaging()) { // 'lazyredraw' set, don't do messages now
- return;
- }
-
- // We don't want to overwrite another important message, but do overwrite
- // a previous "more lines" or "fewer lines" message, so that "5dd" and
- // then "put" reports the last action.
- if (keep_msg != NULL && !keep_msg_more) {
- return;
- }
-
- if (n > 0) {
- pn = n;
- } else {
- pn = -n;
- }
-
- if (pn > p_report) {
- if (n > 0) {
- vim_snprintf(msg_buf, MSG_BUF_LEN,
- NGETTEXT("%ld more line", "%ld more lines", pn),
- pn);
- } else {
- vim_snprintf(msg_buf, MSG_BUF_LEN,
- NGETTEXT("%ld line less", "%ld fewer lines", pn),
- pn);
- }
- if (got_int) {
- xstrlcat(msg_buf, _(" (Interrupted)"), MSG_BUF_LEN);
- }
- if (msg(msg_buf)) {
- set_keep_msg(msg_buf, 0);
- keep_msg_more = true;
- }
- }
-}
-
-/*
- * flush map and typeahead buffers and give a warning for an error
- */
-void beep_flush(void)
-{
- if (emsg_silent == 0) {
- flush_buffers(FLUSH_MINIMAL);
- vim_beep(BO_ERROR);
- }
-}
-
-// Give a warning for an error
-// val is one of the BO_ values, e.g., BO_OPER
-void vim_beep(unsigned val)
-{
- called_vim_beep = true;
-
- if (emsg_silent == 0) {
- if (!((bo_flags & val) || (bo_flags & BO_ALL))) {
- static int beeps = 0;
- static uint64_t start_time = 0;
-
- // Only beep up to three times per half a second,
- // otherwise a sequence of beeps would freeze Vim.
- if (start_time == 0 || os_hrtime() - start_time > 500000000u) {
- beeps = 0;
- start_time = os_hrtime();
- }
- beeps++;
- if (beeps <= 3) {
- if (p_vb) {
- ui_call_visual_bell();
- } else {
- ui_call_bell();
- }
- }
- }
-
- // When 'debug' contains "beep" produce a message. If we are sourcing
- // a script or executing a function give the user a hint where the beep
- // comes from.
- if (vim_strchr(p_debug, 'e') != NULL) {
- msg_source(HL_ATTR(HLF_W));
- msg_attr(_("Beep!"), HL_ATTR(HLF_W));
- }
- }
-}
-
-#if defined(EXITFREE)
-
-void free_users(void)
-{
- ga_clear_strings(&ga_users);
-}
-
-#endif
-
-/*
- * Find all user names for user completion.
- * Done only once and then cached.
- */
-static void init_users(void)
-{
- static int lazy_init_done = FALSE;
-
- if (lazy_init_done) {
- return;
- }
-
- lazy_init_done = TRUE;
-
- os_get_usernames(&ga_users);
-}
-
-/*
- * Function given to ExpandGeneric() to obtain an user names.
- */
-char_u *get_users(expand_T *xp, int idx)
-{
- init_users();
- if (idx < ga_users.ga_len) {
- return ((char_u **)ga_users.ga_data)[idx];
- }
- return NULL;
-}
-
-/*
- * Check whether name matches a user name. Return:
- * 0 if name does not match any user name.
- * 1 if name partially matches the beginning of a user name.
- * 2 is name fully matches a user name.
- */
-int match_user(char_u *name)
-{
- int n = (int)STRLEN(name);
- int result = 0;
-
- init_users();
- for (int i = 0; i < ga_users.ga_len; i++) {
- if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0) {
- return 2; // full match
- }
- if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0) {
- result = 1; // partial match
- }
- }
- return result;
-}
-
-/// os_call_shell() wrapper. Handles 'verbose', :profile, and v:shell_error.
-/// Invalidates cached tags.
-///
-/// @return shell command exit code
-int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
-{
- int retval;
- proftime_T wait_time;
-
- if (p_verbose > 3) {
- verbose_enter();
- smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd);
- msg_putchar('\n');
- verbose_leave();
- }
-
- if (do_profiling == PROF_YES) {
- prof_child_enter(&wait_time);
- }
-
- if (*p_sh == NUL) {
- emsg(_(e_shellempty));
- retval = -1;
- } else {
- // The external command may update a tags file, clear cached tags.
- tag_freematch();
-
- retval = os_call_shell(cmd, opts, extra_shell_arg);
- }
-
- set_vim_var_nr(VV_SHELL_ERROR, (varnumber_T)retval);
- if (do_profiling == PROF_YES) {
- prof_child_exit(&wait_time);
- }
-
- return retval;
-}
-
-/// Get the stdout of an external command.
-/// If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not
-/// NULL store the length there.
-///
-/// @param cmd command to execute
-/// @param infile optional input file name
-/// @param flags can be kShellOptSilent or 0
-/// @param ret_len length of the stdout
-///
-/// @return an allocated string, or NULL for error.
-char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags, size_t *ret_len)
-{
- char_u *buffer = NULL;
-
- if (check_secure()) {
- return NULL;
- }
-
- // get a name for the temp file
- char_u *tempname = vim_tempname();
- if (tempname == NULL) {
- emsg(_(e_notmp));
- return NULL;
- }
-
- // Add the redirection stuff
- char_u *command = make_filter_cmd(cmd, infile, tempname);
-
- /*
- * Call the shell to execute the command (errors are ignored).
- * Don't check timestamps here.
- */
- ++no_check_timestamps;
- call_shell(command, kShellOptDoOut | kShellOptExpand | flags, NULL);
- --no_check_timestamps;
-
- xfree(command);
-
- // read the names from the file into memory
- FILE *fd = os_fopen((char *)tempname, READBIN);
-
- if (fd == NULL) {
- semsg(_(e_notopen), tempname);
- goto done;
- }
-
- fseek(fd, 0L, SEEK_END);
- size_t len = (size_t)ftell(fd); // get size of temp file
- fseek(fd, 0L, SEEK_SET);
-
- buffer = xmalloc(len + 1);
- size_t i = fread((char *)buffer, 1, len, fd);
- fclose(fd);
- os_remove((char *)tempname);
- if (i != len) {
- semsg(_(e_notread), tempname);
- XFREE_CLEAR(buffer);
- } else if (ret_len == NULL) {
- // Change NUL into SOH, otherwise the string is truncated.
- for (i = 0; i < len; ++i) {
- if (buffer[i] == NUL) {
- buffer[i] = 1;
- }
- }
-
- buffer[len] = NUL; // make sure the buffer is terminated
- } else {
- *ret_len = len;
- }
-
-done:
- xfree(tempname);
- return buffer;
-}
-
-/*
- * Return TRUE when need to go to Insert mode because of 'insertmode'.
- * Don't do this when still processing a command or a mapping.
- * Don't do this when inside a ":normal" command.
- */
-int goto_im(void)
-{
- return p_im && stuff_empty() && typebuf_typed();
-}
diff --git a/src/nvim/misc1.h b/src/nvim/misc1.h
deleted file mode 100644
index 14ca361073..0000000000
--- a/src/nvim/misc1.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef NVIM_MISC1_H
-#define NVIM_MISC1_H
-
-#include "nvim/os/shell.h"
-#include "nvim/vim.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "misc1.h.generated.h"
-#endif
-#endif // NVIM_MISC1_H
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 386094e509..5d007fb173 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -10,7 +10,6 @@
#include "nvim/diff.h"
#include "nvim/fold.h"
#include "nvim/memline.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/os_unix.h"
@@ -31,6 +30,32 @@
static linenr_T orig_topline = 0;
static int orig_topfill = 0;
+/// Return true if "c" is a mouse key.
+bool is_mouse_key(int c)
+{
+ return c == K_LEFTMOUSE
+ || c == K_LEFTMOUSE_NM
+ || c == K_LEFTDRAG
+ || c == K_LEFTRELEASE
+ || c == K_LEFTRELEASE_NM
+ || c == K_MOUSEMOVE
+ || c == K_MIDDLEMOUSE
+ || c == K_MIDDLEDRAG
+ || c == K_MIDDLERELEASE
+ || c == K_RIGHTMOUSE
+ || c == K_RIGHTDRAG
+ || c == K_RIGHTRELEASE
+ || c == K_MOUSEDOWN
+ || c == K_MOUSEUP
+ || c == K_MOUSELEFT
+ || c == K_MOUSERIGHT
+ || c == K_X1MOUSE
+ || c == K_X1DRAG
+ || c == K_X1RELEASE
+ || c == K_X2MOUSE
+ || c == K_X2DRAG
+ || c == K_X2RELEASE;
+}
/// Move the cursor to the specified row and column on the screen.
/// Change current window if necessary. Returns an integer with the
/// CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
diff --git a/src/nvim/move.c b/src/nvim/move.c
index d80e63e79d..0a672000e4 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -23,9 +23,9 @@
#include "nvim/diff.h"
#include "nvim/edit.h"
#include "nvim/fold.h"
+#include "nvim/getchar.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/plines.h"
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index a1a1f0f8c0..299651ee97 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -24,7 +24,6 @@
#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 9332c55b5f..95a521c0d8 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -40,7 +40,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 52c382028e..9bc63477e9 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -38,7 +38,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 05929193b8..2ceb1bd992 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -55,7 +55,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index e9963516fc..24c7678633 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -21,7 +21,6 @@
#include "nvim/assert.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index fc9bbbc8b0..3790eba212 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -17,7 +17,6 @@
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/os/input.h"
#include "nvim/state.h"
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 6ef0aa1091..e618b2788b 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -12,6 +12,7 @@
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/rstream.h"
+#include "nvim/eval.h"
#include "nvim/ex_cmds.h"
#include "nvim/fileio.h"
#include "nvim/lib/kvec.h"
@@ -20,7 +21,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option_defs.h"
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
@@ -28,6 +28,7 @@
#include "nvim/screen.h"
#include "nvim/strings.h"
#include "nvim/types.h"
+#include "nvim/tag.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -681,6 +682,116 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args)
return exitcode;
}
+/// os_call_shell() wrapper. Handles 'verbose', :profile, and v:shell_error.
+/// Invalidates cached tags.
+///
+/// @return shell command exit code
+int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
+{
+ int retval;
+ proftime_T wait_time;
+
+ if (p_verbose > 3) {
+ verbose_enter();
+ smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd);
+ msg_putchar('\n');
+ verbose_leave();
+ }
+
+ if (do_profiling == PROF_YES) {
+ prof_child_enter(&wait_time);
+ }
+
+ if (*p_sh == NUL) {
+ emsg(_(e_shellempty));
+ retval = -1;
+ } else {
+ // The external command may update a tags file, clear cached tags.
+ tag_freematch();
+
+ retval = os_call_shell(cmd, opts, extra_shell_arg);
+ }
+
+ set_vim_var_nr(VV_SHELL_ERROR, (varnumber_T)retval);
+ if (do_profiling == PROF_YES) {
+ prof_child_exit(&wait_time);
+ }
+
+ return retval;
+}
+
+/// Get the stdout of an external command.
+/// If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not
+/// NULL store the length there.
+///
+/// @param cmd command to execute
+/// @param infile optional input file name
+/// @param flags can be kShellOptSilent or 0
+/// @param ret_len length of the stdout
+///
+/// @return an allocated string, or NULL for error.
+char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags, size_t *ret_len)
+{
+ char_u *buffer = NULL;
+
+ if (check_secure()) {
+ return NULL;
+ }
+
+ // get a name for the temp file
+ char_u *tempname = vim_tempname();
+ if (tempname == NULL) {
+ emsg(_(e_notmp));
+ return NULL;
+ }
+
+ // Add the redirection stuff
+ char_u *command = make_filter_cmd(cmd, infile, tempname);
+
+ // Call the shell to execute the command (errors are ignored).
+ // Don't check timestamps here.
+ no_check_timestamps++;
+ call_shell(command, kShellOptDoOut | kShellOptExpand | flags, NULL);
+ no_check_timestamps--;
+
+ xfree(command);
+
+ // read the names from the file into memory
+ FILE *fd = os_fopen((char *)tempname, READBIN);
+
+ if (fd == NULL) {
+ semsg(_(e_notopen), tempname);
+ goto done;
+ }
+
+ fseek(fd, 0L, SEEK_END);
+ size_t len = (size_t)ftell(fd); // get size of temp file
+ fseek(fd, 0L, SEEK_SET);
+
+ buffer = xmalloc(len + 1);
+ size_t i = fread((char *)buffer, 1, len, fd);
+ fclose(fd);
+ os_remove((char *)tempname);
+ if (i != len) {
+ semsg(_(e_notread), tempname);
+ XFREE_CLEAR(buffer);
+ } else if (ret_len == NULL) {
+ // Change NUL into SOH, otherwise the string is truncated.
+ for (i = 0; i < len; i++) {
+ if (buffer[i] == NUL) {
+ buffer[i] = 1;
+ }
+ }
+
+ buffer[len] = NUL; // make sure the buffer is terminated
+ } else {
+ *ret_len = len;
+ }
+
+done:
+ xfree(tempname);
+ return buffer;
+}
/// os_system - synchronously execute a command in the shell
///
/// example:
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index 0d125ec964..a8bf68a1a2 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -18,7 +18,6 @@
#include "nvim/main.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/os/signal.h"
#include "nvim/vim.h"
diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c
index 9952e2b387..e0ce3fec31 100644
--- a/src/nvim/os/users.c
+++ b/src/nvim/os/users.c
@@ -18,6 +18,9 @@
# include <lm.h>
#endif
+// All user names (for ~user completion as done by shell).
+static garray_T ga_users = GA_EMPTY_INIT_VALUE;
+
// Add a user name to the list of users in garray_T *users.
// Do nothing if user name is NULL or empty.
static void add_user(garray_T *users, char *user, bool need_copy)
@@ -157,3 +160,60 @@ char *os_get_user_directory(const char *name)
return NULL;
}
+
+#if defined(EXITFREE)
+
+void free_users(void)
+{
+ ga_clear_strings(&ga_users);
+}
+
+#endif
+
+/// Find all user names for user completion.
+///
+/// Done only once and then cached.
+static void init_users(void)
+{
+ static int lazy_init_done = false;
+
+ if (lazy_init_done) {
+ return;
+ }
+
+ lazy_init_done = true;
+
+ os_get_usernames(&ga_users);
+}
+
+/// Given to ExpandGeneric() to obtain an user names.
+char_u *get_users(expand_T *xp, int idx)
+{
+ init_users();
+ if (idx < ga_users.ga_len) {
+ return ((char_u **)ga_users.ga_data)[idx];
+ }
+ return NULL;
+}
+
+/// Check whether name matches a user name.
+///
+/// @return 0 if name does not match any user name.
+/// 1 if name partially matches the beginning of a user name.
+/// 2 is name fully matches a user name.
+int match_user(char_u *name)
+{
+ int n = (int)STRLEN(name);
+ int result = 0;
+
+ init_users();
+ for (int i = 0; i < ga_users.ga_len; i++) {
+ if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0) {
+ return 2; // full match
+ }
+ if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0) {
+ result = 1; // partial match
+ }
+ }
+ return result;
+}
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index 9396a5896a..1398dba0e4 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -20,7 +20,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 01ac88d537..674d67e21a 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -18,7 +18,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 6a192d148f..2204e2a62a 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -27,7 +27,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index aa8d1503fc..45e580dbee 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -64,7 +64,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/os/input.h"
#include "nvim/plines.h"
#include "nvim/garray.h"
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index be365d4ab8..1c04cb16b3 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -12,7 +12,6 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/lua/executor.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/os.h"
#include "nvim/runtime.h"
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 0d06c45229..a938a3b062 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -98,7 +98,6 @@
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
diff --git a/src/nvim/search.c b/src/nvim/search.c
index f45d709b91..906c9a6f47 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -14,6 +14,7 @@
#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
+#include "nvim/change.h"
#include "nvim/cursor.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
@@ -31,7 +32,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
@@ -1354,6 +1354,10 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
}
retval = 1; // pattern found
+ if (sia && sia->sa_wrapped) {
+ apply_autocmds(EVENT_SEARCHWRAPPED, NULL, NULL, false, NULL);
+ }
+
/*
* Add character and/or line offset
*/
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 85d1e139bf..bd31e98faa 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -94,12 +94,12 @@
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/hashtab.h"
+#include "nvim/input.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index c65fcc1180..42bb3c61a5 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -237,7 +237,6 @@
#include "nvim/fileio.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
@@ -4447,10 +4446,10 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
putc(SN_PREFCOND, fd); // <sectionID>
putc(SNF_REQUIRED, fd); // <sectionflags>
- size_t l = (size_t)write_spell_prefcond(NULL, &spin->si_prefcond);
+ size_t l = (size_t)write_spell_prefcond(NULL, &spin->si_prefcond, &fwv);
put_bytes(fd, l, 4); // <sectionlen>
- write_spell_prefcond(fd, &spin->si_prefcond);
+ write_spell_prefcond(fd, &spin->si_prefcond, &fwv);
}
// SN_REP: <repcount> <rep> ...
@@ -5794,7 +5793,7 @@ static int set_spell_finish(spelltab_T *new_st)
// Write the table with prefix conditions to the .spl file.
// When "fd" is NULL only count the length of what is written.
-static int write_spell_prefcond(FILE *fd, garray_T *gap)
+static int write_spell_prefcond(FILE *fd, garray_T *gap, size_t *fwv)
{
assert(gap->ga_len >= 0);
@@ -5802,8 +5801,7 @@ static int write_spell_prefcond(FILE *fd, garray_T *gap)
put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <prefcondcnt>
}
size_t totlen = 2 + (size_t)gap->ga_len; // <prefcondcnt> and <condlen> bytes
- size_t x = 1; // collect return value of fwrite()
- for (int i = 0; i < gap->ga_len; ++i) {
+ for (int i = 0; i < gap->ga_len; i++) {
// <prefcond> : <condlen> <condstr>
char_u *p = ((char_u **)gap->ga_data)[i];
if (p != NULL) {
@@ -5811,7 +5809,7 @@ static int write_spell_prefcond(FILE *fd, garray_T *gap)
if (fd != NULL) {
assert(len <= INT_MAX);
fputc((int)len, fd);
- x &= fwrite(p, len, 1, fd);
+ *fwv &= fwrite(p, len, 1, fd);
}
totlen += len;
} else if (fd != NULL) {
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 27f93fe4ce..e2a8108c45 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -31,7 +31,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/option.h"
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index a39f78b751..a9447165c2 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -32,7 +32,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 483d2df778..a10a2a0c32 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -25,11 +25,11 @@
#include "nvim/fold.h"
#include "nvim/garray.h"
#include "nvim/if_cscope.h"
+#include "nvim/input.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 2d32b6bac4..04068a3cb8 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -64,7 +64,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index aad72af025..1aadaf5c9d 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -23,7 +23,6 @@
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
@@ -300,6 +299,44 @@ void ui_busy_stop(void)
}
}
+/// Emit a bell or visualbell as a warning
+///
+/// val is one of the BO_ values, e.g., BO_OPER
+void vim_beep(unsigned val)
+{
+ called_vim_beep = true;
+
+ if (emsg_silent == 0) {
+ if (!((bo_flags & val) || (bo_flags & BO_ALL))) {
+ static int beeps = 0;
+ static uint64_t start_time = 0;
+
+ // Only beep up to three times per half a second,
+ // otherwise a sequence of beeps would freeze Vim.
+ if (start_time == 0 || os_hrtime() - start_time > 500000000u) {
+ beeps = 0;
+ start_time = os_hrtime();
+ }
+ beeps++;
+ if (beeps <= 3) {
+ if (p_vb) {
+ ui_call_visual_bell();
+ } else {
+ ui_call_bell();
+ }
+ }
+ }
+
+ // When 'debug' contains "beep" produce a message. If we are sourcing
+ // a script or executing a function give the user a hint where the beep
+ // comes from.
+ if (vim_strchr(p_debug, 'e') != NULL) {
+ msg_source(HL_ATTR(HLF_W));
+ msg_attr(_("Beep!"), HL_ATTR(HLF_W));
+ }
+ }
+}
+
void ui_attach_impl(UI *ui, uint64_t chanid)
{
if (ui_count == MAX_UI_COUNT) {
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 3e7eb6d01e..d18f35a43a 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -93,12 +93,12 @@
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/garray.h"
+#include "nvim/getchar.h"
#include "nvim/lib/kvec.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/window.c b/src/nvim/window.c
index be963d8374..c711f462d1 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -30,7 +30,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"