aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/help.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 22:40:31 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 22:40:31 +0000
commit339e2d15cc26fe86988ea06468d912a46c8d6f29 (patch)
treea6167fc8fcfc6ae2dc102f57b2473858eac34063 /src/nvim/help.c
parent067dc73729267c0262438a6fdd66e586f8496946 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-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.c136
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 {