diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 22:40:31 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 22:40:31 +0000 |
commit | 339e2d15cc26fe86988ea06468d912a46c8d6f29 (patch) | |
tree | a6167fc8fcfc6ae2dc102f57b2473858eac34063 /src/nvim/help.c | |
parent | 067dc73729267c0262438a6fdd66e586f8496946 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-339e2d15cc26fe86988ea06468d912a46c8d6f29.tar.gz rneovim-339e2d15cc26fe86988ea06468d912a46c8d6f29.tar.bz2 rneovim-339e2d15cc26fe86988ea06468d912a46c8d6f29.zip |
Merge remote-tracking branch 'upstream/master' into fix_repeatcmdline
Diffstat (limited to 'src/nvim/help.c')
-rw-r--r-- | src/nvim/help.c | 136 |
1 files changed, 67 insertions, 69 deletions
diff --git a/src/nvim/help.c b/src/nvim/help.c index bbc552fa4c..c23dc7fd9d 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -1,42 +1,46 @@ -// 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 - // help.c: functions for Vim help #include <stdbool.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/buffer.h" +#include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" +#include "nvim/extmark_defs.h" #include "nvim/fileio.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/help.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/option.h" +#include "nvim/option_vars.h" #include "nvim/optionstr.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/path.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/runtime.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/types.h" -#include "nvim/vim.h" +#include "nvim/types_defs.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -47,19 +51,12 @@ void ex_help(exarg_T *eap) { char *arg; - char *tag; FILE *helpfd; // file descriptor of help file - int n; - int i; win_T *wp; int num_matches; char **matches; - char *p; int empty_fnum = 0; int alt_fnum = 0; - buf_T *buf; - int len; - char *lang; const bool old_KeyTyped = KeyTyped; if (eap != NULL) { @@ -88,13 +85,13 @@ void ex_help(exarg_T *eap) } // remove trailing blanks - p = arg + strlen(arg) - 1; + char *p = arg + strlen(arg) - 1; while (p > arg && ascii_iswhite(*p) && p[-1] != '\\') { *p-- = NUL; } // Check for a specified language - lang = check_help_lang(arg); + char *lang = check_help_lang(arg); // When no argument given go to the index. if (*arg == NUL) { @@ -102,13 +99,13 @@ void ex_help(exarg_T *eap) } // Check if there is a match for the argument. - n = find_help_tags(arg, &num_matches, &matches, eap != NULL && eap->forceit); + int n = find_help_tags(arg, &num_matches, &matches, eap != NULL && eap->forceit); - i = 0; + int i = 0; if (n != FAIL && lang != NULL) { // Find first item with the requested language. for (i = 0; i < num_matches; i++) { - len = (int)strlen(matches[i]); + int len = (int)strlen(matches[i]); if (len > 3 && matches[i][len - 3] == '@' && STRICMP(matches[i] + len - 2, lang) == 0) { break; @@ -128,7 +125,7 @@ void ex_help(exarg_T *eap) } // The first match (in the requested language) is the best match. - tag = xstrdup(matches[i]); + char *tag = xstrdup(matches[i]); FreeWild(num_matches, matches); // Re-use an existing help window or open a new one. @@ -151,7 +148,7 @@ void ex_help(exarg_T *eap) // There is no help window yet. // Try to open the file specified by the "helpfile" option. if ((helpfd = os_fopen(p_hf, READBIN)) == NULL) { - smsg(_("Sorry, help file \"%s\" not found"), p_hf); + smsg(0, _("Sorry, help file \"%s\" not found"), p_hf); goto erret; } fclose(helpfd); @@ -199,7 +196,7 @@ void ex_help(exarg_T *eap) // may have jumped to another window, check that the buffer is not in a // window. if (empty_fnum != 0 && curbuf->b_fnum != empty_fnum) { - buf = buflist_findnr(empty_fnum); + buf_T *buf = buflist_findnr(empty_fnum); if (buf != NULL && buf->b_nwindows == 0) { wipe_buffer(buf, true); } @@ -259,11 +256,8 @@ char *check_help_lang(char *arg) int help_heuristic(char *matched_string, int offset, int wrong_case) FUNC_ATTR_PURE { - int num_letters; - char *p; - - num_letters = 0; - for (p = matched_string; *p; p++) { + int num_letters = 0; + for (char *p = matched_string; *p; p++) { if (ASCII_ISALNUM(*p)) { num_letters++; } @@ -298,11 +292,8 @@ int help_heuristic(char *matched_string, int offset, int wrong_case) /// that has been put after the tagname by find_tags(). static int help_compare(const void *s1, const void *s2) { - char *p1; - char *p2; - - p1 = *(char **)s1 + strlen(*(char **)s1) + 1; - p2 = *(char **)s2 + strlen(*(char **)s2) + 1; + char *p1 = *(char **)s1 + strlen(*(char **)s1) + 1; + char *p2 = *(char **)s2 + strlen(*(char **)s2) + 1; // Compare by help heuristic number first. int cmp = strcmp(p1, p2); @@ -320,8 +311,6 @@ static int help_compare(const void *s1, const void *s2) /// When "keep_lang" is true try keeping the language of the current buffer. int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep_lang) { - int i; - // Specific tags that either have a specific replacement or won't go // through the generic rules. static char *(except_tbl[][2]) = { @@ -379,7 +368,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep // When the string starting with "expr-" and containing '?' and matches // the table, it is taken literally (but ~ is escaped). Otherwise '?' // is recognized as a wildcard. - for (i = (int)ARRAY_SIZE(expr_table); --i >= 0;) { + for (int i = (int)ARRAY_SIZE(expr_table); --i >= 0;) { if (strcmp(arg + 5, expr_table[i]) == 0) { for (int si = 0, di = 0;; si++) { if (arg[si] == '~') { @@ -396,7 +385,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep } else { // Recognize a few exceptions to the rule. Some strings that contain // '*'are changed to "star", otherwise '*' is recognized as a wildcard. - for (i = 0; except_tbl[i][0] != NULL; i++) { + for (int i = 0; except_tbl[i][0] != NULL; i++) { if (strcmp(arg, except_tbl[i][0]) == 0) { STRCPY(d, except_tbl[i][1]); break; @@ -469,7 +458,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep // Replace "^x" by "CTRL-X". Don't do this for "^_" to make // ":help i_^_CTRL-D" work. // Insert '-' before and after "CTRL-X" when applicable. - if (*s < ' ' + if ((uint8_t)(*s) < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", (uint8_t)s[1]) != NULL))) { if (d > IObuff && d[-1] != '_' && d[-1] != '\\') { @@ -658,26 +647,23 @@ void prepare_help_buffer(void) /// highlighting is not used. void fix_help_buffer(void) { - linenr_T lnum; - char *line; - bool in_example = false; - // Set filetype to "help". if (strcmp(curbuf->b_p_ft, "help") != 0) { curbuf->b_ro_locked++; - set_option_value_give_err("ft", 0L, "help", OPT_LOCAL); + set_option_value_give_err("ft", STATIC_CSTR_AS_OPTVAL("help"), OPT_LOCAL); curbuf->b_ro_locked--; } if (!syntax_present(curwin)) { - for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { - line = ml_get_buf(curbuf, lnum, false); + bool in_example = false; + for (linenr_T lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { + char *line = ml_get_buf(curbuf, lnum); const size_t len = strlen(line); if (in_example && len > 0 && !ascii_iswhite(line[0])) { // End of example: non-white or '<' in first column. if (line[0] == '<') { // blank-out a '<' in the first column - line = ml_get_buf(curbuf, lnum, true); + line = ml_get_buf_mut(curbuf, lnum); line[0] = ' '; } in_example = false; @@ -685,12 +671,12 @@ void fix_help_buffer(void) if (!in_example && len > 0) { if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' ')) { // blank-out a '>' in the last column (start of example) - line = ml_get_buf(curbuf, lnum, true); + line = ml_get_buf_mut(curbuf, lnum); line[len - 1] = ' '; in_example = true; } else if (line[len - 1] == '~') { // blank-out a '~' at the end of line (header marker) - line = ml_get_buf(curbuf, lnum, true); + line = ml_get_buf_mut(curbuf, lnum); line[len - 1] = ' '; } } @@ -706,12 +692,14 @@ void fix_help_buffer(void) && ASCII_ISALPHA(fname[6]) && TOLOWER_ASC(fname[7]) == 'x' && fname[8] == NUL)) { - for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; lnum++) { - line = ml_get_buf(curbuf, lnum, false); + for (linenr_T lnum = 1; lnum < curbuf->b_ml.ml_line_count; lnum++) { + char *line = ml_get_buf(curbuf, lnum); if (strstr(line, "*local-additions*") == NULL) { continue; } + int lnum_start = lnum; + // Go through all directories in 'runtimepath', skipping // $VIMRUNTIME. char *p = p_rtp; @@ -722,9 +710,7 @@ void fix_help_buffer(void) && path_full_compare(rt, NameBuff, false, true) != kEqualFiles) { int fcount; char **fnames; - char *s; vimconv_T vc; - char *cp; // Find all "doc/ *.txt" files in this directory. if (!add_pathsep(NameBuff) @@ -740,6 +726,8 @@ void fix_help_buffer(void) if (gen_expand_wildcards(1, buff_list, &fcount, &fnames, EW_FILE|EW_SILENT) == OK && fcount > 0) { + char *s; + char *cp; // If foo.abx is found use it instead of foo.txt in // the same directory. for (int i1 = 0; i1 < fcount; i1++) { @@ -829,7 +817,7 @@ void fix_help_buffer(void) } convert_setup(&vc, NULL, NULL); - ml_append(lnum, cp, (colnr_T)0, false); + ml_append(lnum, cp, 0, false); if (cp != IObuff) { xfree(cp); } @@ -842,6 +830,11 @@ void fix_help_buffer(void) } xfree(rt); } + linenr_T appended = lnum - lnum_start; + if (appended) { + mark_adjust(lnum_start + 1, (linenr_T)MAXLNUM, appended, 0, kExtmarkUndo); + buf_redraw_changed_lines_later(curbuf, lnum_start + 1, lnum_start + 1, appended); + } break; } } @@ -874,7 +867,6 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool garray_T ga; int filecount; char **files; - char *p1, *p2; char *s; TriState utf8 = kNone; bool mix = false; // detected mixed encodings @@ -979,9 +971,9 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool } in_example = false; } - p1 = vim_strchr(IObuff, '*'); // find first '*' + char *p1 = vim_strchr(IObuff, '*'); // find first '*' while (p1 != NULL) { - p2 = strchr((const char *)p1 + 1, '*'); // Find second '*'. + char *p2 = strchr(p1 + 1, '*'); // Find second '*'. if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**". for (s = p1 + 1; s < p2; s++) { if (*s == ' ' || *s == '\t' || *s == '|') { @@ -1028,14 +1020,14 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool // Check for duplicates. for (int i = 1; i < ga.ga_len; i++) { - p1 = ((char **)ga.ga_data)[i - 1]; - p2 = ((char **)ga.ga_data)[i]; + char *p1 = ((char **)ga.ga_data)[i - 1]; + char *p2 = ((char **)ga.ga_data)[i]; while (*p1 == *p2) { if (*p2 == '\t') { *p2 = NUL; vim_snprintf(NameBuff, MAXPATHL, _("E154: Duplicate tag \"%s\" in file %s/%s"), - ((char_u **)ga.ga_data)[i], dir, p2 + 1); + ((char **)ga.ga_data)[i], dir, p2 + 1); emsg(NameBuff); *p2 = '\t'; break; @@ -1057,7 +1049,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool fputs(s, fd_tags); } else { fprintf(fd_tags, "%s\t/" "*", s); - for (p1 = s; *p1 != '\t'; p1++) { + for (char *p1 = s; *p1 != '\t'; p1++) { // insert backslash before '\\' and '/' if (*p1 == '\\' || *p1 == '/') { putc('\\', fd_tags); @@ -1080,7 +1072,6 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) FUNC_ATTR_NONNULL_ALL { - int len; garray_T ga; char lang[2]; char ext[5]; @@ -1090,7 +1081,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) // Get a list of all files in the help directory and in subdirectories. xstrlcpy(NameBuff, dirname, sizeof(NameBuff)); - if (!add_pathsep((char *)NameBuff) + if (!add_pathsep(NameBuff) || xstrlcat(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { emsg(_(e_fnametoolong)); return; @@ -1111,7 +1102,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) int j; ga_init(&ga, 1, 10); for (int i = 0; i < filecount; i++) { - len = (int)strlen(files[i]); + int len = (int)strlen(files[i]); if (len <= 4) { continue; } @@ -1160,24 +1151,30 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) ext[1] = fname[5]; ext[2] = fname[6]; } - helptags_one(dirname, (char *)ext, (char *)fname, add_help_tags, ignore_writeerr); + helptags_one(dirname, ext, fname, add_help_tags, ignore_writeerr); } ga_clear(&ga); FreeWild(filecount, files); } -static void helptags_cb(char *fname, void *cookie) +static bool helptags_cb(int num_fnames, char **fnames, bool all, void *cookie) FUNC_ATTR_NONNULL_ALL { - do_helptags(fname, *(bool *)cookie, true); + for (int i = 0; i < num_fnames; i++) { + do_helptags(fnames[i], *(bool *)cookie, true); + if (!all) { + return true; + } + } + + return num_fnames > 0; } /// ":helptags" void ex_helptags(exarg_T *eap) { expand_T xpc; - char *dirname; bool add_help_tags = false; // Check for ":helptags ++t {dir}". @@ -1187,11 +1184,12 @@ void ex_helptags(exarg_T *eap) } if (strcmp(eap->arg, "ALL") == 0) { - do_in_path(p_rtp, "doc", DIP_ALL + DIP_DIR, helptags_cb, &add_help_tags); + do_in_path(p_rtp, "", "doc", DIP_ALL + DIP_DIR, helptags_cb, &add_help_tags); } else { ExpandInit(&xpc); xpc.xp_context = EXPAND_DIRECTORIES; - dirname = ExpandOne(&xpc, eap->arg, NULL, WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); + char *dirname = + ExpandOne(&xpc, eap->arg, NULL, WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); if (dirname == NULL || !os_isdir(dirname)) { semsg(_("E150: Not a directory: %s"), eap->arg); } else { |