aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/help.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/help.c')
-rw-r--r--src/nvim/help.c126
1 files changed, 75 insertions, 51 deletions
diff --git a/src/nvim/help.c b/src/nvim/help.c
index 7c61a56785..bbc552fa4c 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -3,26 +3,39 @@
// help.c: functions for Vim help
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include "nvim/ascii.h"
#include "nvim/buffer.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/fileio.h"
#include "nvim/garray.h"
+#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/help.h"
+#include "nvim/macros.h"
+#include "nvim/mbyte.h"
+#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
+#include "nvim/os/os.h"
#include "nvim/path.h"
+#include "nvim/pos.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/window.h"
@@ -359,7 +372,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
"!=?", "!~?", "<=?", "<?", "==?", "=~?",
">=?", ">?", "is?", "isnot?"
};
- char *d = (char *)IObuff; // assume IObuff is long enough!
+ char *d = IObuff; // assume IObuff is long enough!
d[0] = NUL;
if (STRNICMP(arg, "expr-", 5) == 0) {
@@ -399,7 +412,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// And also "\_$" and "\_^".
if (arg[0] == '\\'
&& ((arg[1] != NUL && arg[2] == NUL)
- || (vim_strchr("%_z@", arg[1]) != NULL
+ || (vim_strchr("%_z@", (uint8_t)arg[1]) != NULL
&& arg[2] != NUL))) {
vim_snprintf(d, IOSIZE, "/\\\\%s", arg + 1);
// Check for "/\\_$", should be "/\\_\$"
@@ -458,7 +471,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// Insert '-' before and after "CTRL-X" when applicable.
if (*s < ' '
|| (*s == '^' && s[1]
- && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", s[1]) != NULL))) {
+ && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", (uint8_t)s[1]) != NULL))) {
if (d > IObuff && d[-1] != '_' && d[-1] != '\\') {
*d++ = '_'; // prepend a '_' to make x_CTRL-x
}
@@ -537,12 +550,12 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
if (keep_lang) {
flags |= TAG_KEEP_LANG;
}
- if (find_tags((char *)IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
+ if (find_tags(IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
&& *num_matches > 0) {
// Sort the matches found on the heuristic number that is after the
// tag name.
qsort((void *)(*matches), (size_t)(*num_matches),
- sizeof(char_u *), help_compare);
+ sizeof(char *), help_compare);
// Delete more than TAG_MANY to reduce the size of the listing.
while (*num_matches > TAG_MANY) {
xfree((*matches)[--*num_matches]);
@@ -557,7 +570,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
void cleanup_help_tags(int num_file, char **file)
{
char buf[4];
- char_u *p = (char_u *)buf;
+ char *p = buf;
if (p_hlg[0] != NUL && (p_hlg[0] != 'e' || p_hlg[1] != 'n')) {
*p++ = '@';
@@ -578,7 +591,7 @@ void cleanup_help_tags(int num_file, char **file)
for (j = 0; j < num_file; j++) {
if (j != i
&& (int)strlen(file[j]) == len + 3
- && STRNCMP(file[i], file[j], len + 1) == 0) {
+ && strncmp(file[i], file[j], (size_t)len + 1) == 0) {
break;
}
}
@@ -659,7 +672,7 @@ void fix_help_buffer(void)
if (!syntax_present(curwin)) {
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) {
line = ml_get_buf(curbuf, lnum, false);
- const size_t len = STRLEN(line);
+ 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] == '<') {
@@ -703,10 +716,10 @@ void fix_help_buffer(void)
// $VIMRUNTIME.
char *p = p_rtp;
while (*p != NUL) {
- copy_option_part(&p, (char *)NameBuff, MAXPATHL, ",");
+ copy_option_part(&p, NameBuff, MAXPATHL, ",");
char *const rt = vim_getenv("VIMRUNTIME");
if (rt != NULL
- && path_full_compare(rt, (char *)NameBuff, false, true) != kEqualFiles) {
+ && path_full_compare(rt, NameBuff, false, true) != kEqualFiles) {
int fcount;
char **fnames;
char *s;
@@ -714,7 +727,7 @@ void fix_help_buffer(void)
char *cp;
// Find all "doc/ *.txt" files in this directory.
- if (!add_pathsep((char *)NameBuff)
+ if (!add_pathsep(NameBuff)
|| xstrlcat(NameBuff, "doc/*.??[tx]", // NOLINT
sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
@@ -723,35 +736,33 @@ void fix_help_buffer(void)
// Note: We cannot just do `&NameBuff` because it is a statically sized array
// so `NameBuff == &NameBuff` according to C semantics.
- char *buff_list[1] = { (char *)NameBuff };
+ char *buff_list[1] = { NameBuff };
if (gen_expand_wildcards(1, buff_list, &fcount,
&fnames, EW_FILE|EW_SILENT) == OK
&& fcount > 0) {
// If foo.abx is found use it instead of foo.txt in
// the same directory.
for (int i1 = 0; i1 < fcount; i1++) {
- for (int i2 = 0; i2 < fcount; i2++) {
- if (i1 == i2) {
- continue;
- }
- if (fnames[i1] == NULL || fnames[i2] == NULL) {
+ const char *const f1 = fnames[i1];
+ const char *const t1 = path_tail(f1);
+ const char *const e1 = strrchr(t1, '.');
+ if (path_fnamecmp(e1, ".txt") != 0
+ && path_fnamecmp(e1, fname + 4) != 0) {
+ // Not .txt and not .abx, remove it.
+ XFREE_CLEAR(fnames[i1]);
+ continue;
+ }
+
+ for (int i2 = i1 + 1; i2 < fcount; i2++) {
+ const char *const f2 = fnames[i2];
+ if (f2 == NULL) {
continue;
}
- const char *const f1 = fnames[i1];
- const char *const f2 = fnames[i2];
- const char *const t1 = path_tail(f1);
const char *const t2 = path_tail(f2);
- const char *const e1 = strrchr(t1, '.');
const char *const e2 = strrchr(t2, '.');
if (e1 == NULL || e2 == NULL) {
continue;
}
- if (path_fnamecmp(e1, ".txt") != 0
- && path_fnamecmp(e1, fname + 4) != 0) {
- // Not .txt and not .abx, remove it.
- XFREE_CLEAR(fnames[i1]);
- continue;
- }
if (e1 - f1 != e2 - f2
|| path_fnamencmp(f1, f2, (size_t)(e1 - f1)) != 0) {
continue;
@@ -772,9 +783,9 @@ void fix_help_buffer(void)
if (fd == NULL) {
continue;
}
- vim_fgets((char_u *)IObuff, IOSIZE, fd);
+ vim_fgets(IObuff, IOSIZE, fd);
if (IObuff[0] == '*'
- && (s = vim_strchr((char *)IObuff + 1, '*'))
+ && (s = vim_strchr(IObuff + 1, '*'))
!= NULL) {
TriState this_utf = kNone;
// Change tag definition to a
@@ -788,7 +799,7 @@ void fix_help_buffer(void)
// The text is utf-8 when a byte
// above 127 is found and no
// illegal byte sequence is found.
- if ((char_u)(*s) >= 0x80 && this_utf != kFalse) {
+ if ((uint8_t)(*s) >= 0x80 && this_utf != kFalse) {
this_utf = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -807,13 +818,13 @@ void fix_help_buffer(void)
p_enc);
if (vc.vc_type == CONV_NONE) {
// No conversion needed.
- cp = (char *)IObuff;
+ cp = IObuff;
} else {
// Do the conversion. If it fails
// use the unconverted text.
- cp = string_convert(&vc, (char *)IObuff, NULL);
+ cp = string_convert(&vc, IObuff, NULL);
if (cp == NULL) {
- cp = (char *)IObuff;
+ cp = IObuff;
}
}
convert_setup(&vc, NULL, NULL);
@@ -869,7 +880,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
bool mix = false; // detected mixed encodings
// Find all *.txt files.
- size_t dirlen = STRLCPY(NameBuff, dir, sizeof(NameBuff));
+ size_t dirlen = xstrlcpy(NameBuff, dir, sizeof(NameBuff));
if (dirlen >= MAXPATHL
|| xstrlcat(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT
|| xstrlcat(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) {
@@ -879,7 +890,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Note: We cannot just do `&NameBuff` because it is a statically sized array
// so `NameBuff == &NameBuff` according to C semantics.
- char *buff_list[1] = { (char *)NameBuff };
+ char *buff_list[1] = { NameBuff };
const int res = gen_expand_wildcards(1, buff_list, &filecount, &files,
EW_FILE|EW_SILENT);
if (res == FAIL || filecount == 0) {
@@ -895,13 +906,13 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Open the tags file for writing.
// Do this before scanning through all the files.
memcpy(NameBuff, dir, dirlen + 1);
- if (!add_pathsep((char *)NameBuff)
+ if (!add_pathsep(NameBuff)
|| xstrlcat(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
return;
}
- FILE *const fd_tags = os_fopen((char *)NameBuff, "w");
+ FILE *const fd_tags = os_fopen(NameBuff, "w");
if (fd_tags == NULL) {
if (!ignore_writeerr) {
semsg(_("E152: Cannot open %s for writing"), NameBuff);
@@ -912,7 +923,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// If using the "++t" argument or generating tags for "$VIMRUNTIME/doc"
// add the "help-tags" tag.
- ga_init(&ga, (int)sizeof(char_u *), 100);
+ ga_init(&ga, (int)sizeof(char *), 100);
if (add_help_tags
|| path_full_compare("$VIMRUNTIME/doc", dir, false, true) == kEqualFiles) {
size_t s_len = 18 + strlen(tagfname);
@@ -930,13 +941,14 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
}
const char *const fname = files[fi] + dirlen + 1;
+ bool in_example = false;
bool firstline = true;
- while (!vim_fgets((char_u *)IObuff, IOSIZE, fd) && !got_int) {
+ while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) {
if (firstline) {
// Detect utf-8 file by a non-ASCII char in the first line.
TriState this_utf8 = kNone;
- for (s = (char *)IObuff; *s != NUL; s++) {
- if ((char_u)(*s) >= 0x80) {
+ for (s = IObuff; *s != NUL; s++) {
+ if ((uint8_t)(*s) >= 0x80) {
this_utf8 = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -960,7 +972,14 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
}
firstline = false;
}
- p1 = vim_strchr((char *)IObuff, '*'); // find first '*'
+ if (in_example) {
+ // skip over example; a non-white in the first column ends it
+ if (vim_strchr(" \t\n\r", (uint8_t)IObuff[0])) {
+ continue;
+ }
+ in_example = false;
+ }
+ p1 = vim_strchr(IObuff, '*'); // find first '*'
while (p1 != NULL) {
p2 = strchr((const char *)p1 + 1, '*'); // Find second '*'.
if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**".
@@ -975,11 +994,11 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// followed by a white character or end-of-line.
if (s == p2
&& (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
- && (vim_strchr(" \t\n\r", s[1]) != NULL
+ && (vim_strchr(" \t\n\r", (uint8_t)s[1]) != NULL
|| s[1] == '\0')) {
*p2 = '\0';
p1++;
- size_t s_len= (size_t)(p2 - p1) + strlen(fname) + 2;
+ size_t s_len = (size_t)(p2 - p1) + strlen(fname) + 2;
s = xmalloc(s_len);
GA_APPEND(char *, &ga, s);
snprintf(s, s_len, "%s\t%s", p1, fname);
@@ -990,6 +1009,11 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
}
p1 = p2;
}
+ size_t len = strlen(IObuff);
+ if ((len == 2 && strcmp(&IObuff[len - 2], ">\n") == 0)
+ || (len >= 3 && strcmp(&IObuff[len - 3], " >\n") == 0)) {
+ in_example = true;
+ }
line_breakcheck();
}
@@ -1009,10 +1033,10 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
while (*p1 == *p2) {
if (*p2 == '\t') {
*p2 = NUL;
- vim_snprintf((char *)NameBuff, MAXPATHL,
+ vim_snprintf(NameBuff, MAXPATHL,
_("E154: Duplicate tag \"%s\" in file %s/%s"),
((char_u **)ga.ga_data)[i], dir, p2 + 1);
- emsg((char *)NameBuff);
+ emsg(NameBuff);
*p2 = '\t';
break;
}
@@ -1028,7 +1052,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Write the tags into the file.
for (int i = 0; i < ga.ga_len; i++) {
s = ((char **)ga.ga_data)[i];
- if (STRNCMP(s, "help-tags\t", 10) == 0) {
+ if (strncmp(s, "help-tags\t", 10) == 0) {
// help-tags entry was added in formatted form
fputs(s, fd_tags);
} else {
@@ -1065,7 +1089,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr)
char **files;
// Get a list of all files in the help directory and in subdirectories.
- STRLCPY(NameBuff, dirname, sizeof(NameBuff));
+ xstrlcpy(NameBuff, dirname, sizeof(NameBuff));
if (!add_pathsep((char *)NameBuff)
|| xstrlcat(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
@@ -1074,7 +1098,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr)
// Note: We cannot just do `&NameBuff` because it is a statically sized array
// so `NameBuff == &NameBuff` according to C semantics.
- char *buff_list[1] = { (char *)NameBuff };
+ char *buff_list[1] = { NameBuff };
if (gen_expand_wildcards(1, buff_list, &filecount, &files,
EW_FILE|EW_SILENT) == FAIL
|| filecount == 0) {
@@ -1109,7 +1133,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr)
// Did we find this language already?
for (j = 0; j < ga.ga_len; j += 2) {
- if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0) {
+ if (strncmp(lang, ((char *)ga.ga_data) + j, 2) == 0) {
break;
}
}
@@ -1157,7 +1181,7 @@ void ex_helptags(exarg_T *eap)
bool add_help_tags = false;
// Check for ":helptags ++t {dir}".
- if (STRNCMP(eap->arg, "++t", 3) == 0 && ascii_iswhite(eap->arg[3])) {
+ if (strncmp(eap->arg, "++t", 3) == 0 && ascii_iswhite(eap->arg[3])) {
add_help_tags = true;
eap->arg = skipwhite(eap->arg + 3);
}