[Backport release-0.8] feat(docs): remove old AWK scripts, update HTML generator (#20587)

* feat(docs): nested lists in HTML, update :help parser

- Docs HTML: improvements in https://github.com/neovim/tree-sitter-vimdoc
  allow us to many hacks in `gen_help_html.lua`.
- Docs HTML: support nested lists.
- Docs HTML: avoid extra newlines (too much whitespace) in old
  (preformatted) layout.
- Docs HTML: disable golden-grid for narrow viewport.
- Workaround for https://github.com/neovim/neovim/issues/20404

closes https://github.com/neovim/neovim/issues/20404

(cherry picked from commit 088abbeb6e)

* feat(gen_help_html.lua): remove old AWK scripts

These files are no longer needed since gen_help_html.lua is working
fairly well.

ref https://github.com/neovim/neovim/pull/11967

(cherry picked from commit 03bc23de36)

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
github-actions[bot] 2022-10-11 04:19:38 -07:00 committed by GitHub
parent 00ce3d6e7a
commit 47cd3cf852
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 111 additions and 932 deletions

View File

@ -210,8 +210,8 @@ set(TREESITTER_LUA_SHA256 564594fe0ffd2f2fb3578a15019b723e1bc94ac82cb6a0103a6b3b
set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz)
set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501)
set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.1.0.tar.gz)
set(TREESITTER_HELP_SHA256 4c0ef80c6dc09acab362478950ec6be58a4ab1cbf2d95754b8fbb566e4c647a1)
set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/c27e3e21a54f6d90dfb791f37d90eab5b28de971.tar.gz)
set(TREESITTER_HELP_SHA256 54a6a5b52a395097775f06f96ac1e1c9efdab10243550a467e1198a286b8c59c)
set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz)
set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e)

View File

@ -75,8 +75,10 @@ add_custom_command(OUTPUT ${GENERATED_HELP_TAGS}
)
# TODO: This doesn't work. wait for "nvim -l" to land?
add_custom_target(doc_html
COMMAND make html
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
-V1 -es --clean -c "lua require('scripts.gen_help_html').gen('./build/runtime/doc', './build/doc_html', nil, 'todo_commit_id')" -c "0cq"
DEPENDS
${GENERATED_HELP_TAGS}
WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}/doc"

View File

@ -1,40 +0,0 @@
#
# Makefile for the Vim documentation on Unix
#
# If you get "don't know how to make scratch", first run make in the source
# directory. Or remove the include below.
AWK = awk
DOCS = $(wildcard *.txt)
HTMLS = $(DOCS:.txt=.html)
.SUFFIXES:
.SUFFIXES: .c .o .txt .html
# Awk version of .txt to .html conversion.
html: noerrors vimindex.html $(HTMLS)
@if test -f errors.log; then cat errors.log; fi
noerrors:
-rm -f errors.log
$(HTMLS): tags.ref
.txt.html:
$(AWK) -f makehtml.awk $< >$@
# index.html is the starting point for HTML, but for the help files it is
# help.txt. Therefore use vimindex.html for index.txt.
index.html: help.txt
$(AWK) -f makehtml.awk help.txt >index.html
vimindex.html: index.txt
$(AWK) -f makehtml.awk index.txt >vimindex.html
tags.ref tags.html: tags
$(AWK) -f maketags.awk tags >tags.html
clean:
-rm -f *.html tags.ref $(HTMLS) errors.log tags

View File

@ -434,7 +434,7 @@ its config is non-empty: >
if vim.api.nvim_win_get_config(window_id).relative ~= '' then
-- window with this window_id is floating
end
>
<
Buffer text can be highlighted by typical mechanisms (syntax highlighting,
|api-highlights|). The |hl-NormalFloat| group highlights normal text;
@ -456,7 +456,7 @@ Example: create a float with scratch buffer: >
let win = nvim_open_win(buf, 0, opts)
" optional: change highlight, otherwise Pmenu is used
call nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight')
>
<
==============================================================================
Extended marks *api-extended-marks* *extmarks*
@ -500,8 +500,8 @@ Let's set an extmark at the first row (row=0) and third column (column=2).
01 2345678
0 ex|ample..
< ^ extmark position
>
^ extmark position
let g:mark_ns = nvim_create_namespace('myplugin')
let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 2, {})
<
@ -520,8 +520,8 @@ use |nvim_buf_del_extmark()|. Deleting "x" in our example: >
0 12345678
0 e|ample..
< ^ extmark position
>
^ extmark position
echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id, {})
=> [0, 1]
<

View File

@ -7718,7 +7718,7 @@ sqrt({expr}) *sqrt()*
:echo sqrt(100)
< 10.0 >
:echo sqrt(-4.01)
< str2float('nan')
< str2float("nan")
NaN may be different, it depends on system libraries.
Can also be used as a |method|: >

View File

@ -21,6 +21,7 @@ For a list of Vim variables see |vim-variable|.
tag char action in Insert mode ~
-----------------------------------------------------------------------
|i_CTRL-@| CTRL-@ insert previously inserted text and stop
insert
|i_CTRL-A| CTRL-A insert previously inserted text
@ -184,6 +185,7 @@ note: 1 = cursor movement command; 2 = can be undone/redone
tag char note action in Normal mode ~
------------------------------------------------------------------------------
CTRL-@ not used
|CTRL-A| CTRL-A 2 add N to number at/after cursor
|CTRL-B| CTRL-B 1 scroll N screens Backwards
@ -469,6 +471,7 @@ These can be used after an operator or in Visual mode to select an object.
tag command action in op-pending and Visual mode ~
------------------------------------------------------------------------------
|v_aquote| a" double quoted string
|v_a'| a' single quoted string
|v_a(| a( same as ab
@ -511,6 +514,7 @@ tag command action in op-pending and Visual mode ~
tag command action in Normal mode ~
------------------------------------------------------------------------------
|CTRL-W_CTRL-B| CTRL-W CTRL-B same as "CTRL-W b"
|CTRL-W_CTRL-C| CTRL-W CTRL-C same as "CTRL-W c"
|CTRL-W_CTRL-D| CTRL-W CTRL-D same as "CTRL-W d"
@ -609,6 +613,7 @@ tag command action in Normal mode ~
tag char note action in Normal mode ~
------------------------------------------------------------------------------
|[_CTRL-D| [ CTRL-D jump to first #define found in current and
included files matching the word under the
cursor, start searching at beginning of
@ -699,6 +704,7 @@ tag char note action in Normal mode ~
tag char note action in Normal mode ~
------------------------------------------------------------------------------
g_CTRL-A g CTRL-A dump a memory profile
|g_CTRL-G| g CTRL-G show information about current cursor
position
@ -802,6 +808,7 @@ g_CTRL-A g CTRL-A dump a memory profile
tag char note action in Normal mode ~
------------------------------------------------------------------------------
|z<CR>| z<CR> redraw, cursor line to top of window,
cursor on first non-blank
|zN<CR>| z{height}<CR> redraw, make window {height} lines high
@ -876,6 +883,7 @@ These can be used after an operator, but before a {motion} has been entered.
tag char action in Operator-pending mode ~
-----------------------------------------------------------------------
|o_v| v force operator to work charwise
|o_V| V force operator to work linewise
|o_CTRL-V| CTRL-V force operator to work blockwise
@ -888,6 +896,7 @@ here are those that are different.
tag command note action in Visual mode ~
------------------------------------------------------------------------------
|v_CTRL-\_CTRL-N| CTRL-\ CTRL-N stop Visual mode
|v_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to Normal mode
|v_CTRL-A| CTRL-A 2 add N to number in highlighted text
@ -1008,6 +1017,7 @@ file names, tags, commands etc. as appropriate.
tag command action in Command-line editing mode ~
------------------------------------------------------------------------------
CTRL-@ not used
|c_CTRL-A| CTRL-A do completion on the pattern in front of the
cursor and insert all matches
@ -1118,6 +1128,7 @@ The commands are sorted on the non-optional part of their name.
tag command action ~
------------------------------------------------------------------------------
|:| : nothing
|:range| :{range} go to last line in {range}
|:!| :! filter lines or execute an external command

View File

@ -61,7 +61,7 @@ other words, this section describes which tokens are valid, how they can be
combined, and what their combinations mean.
The language constructs will be explained using the usual extended BNF
notation, in which { `a` } means 0 or more `a`'s, and [ `a` ] means an optional `a`.
notation, in which `{ a }` means 0 or more `a`'s, and `[ a ]` means an optional `a`.
==============================================================================
2.1 Lexical Conventions *luaref-langLexConv*

View File

@ -1,788 +0,0 @@
BEGIN {
# some initialization variables
asciiart="no";
wasset="no";
lineset=0;
sample="no";
while ( getline ti <"tags.ref" > 0 ) {
nf=split(ti,tag," ");
# as help.txt renders into index.html and index.txt -> vimindex.html,
# this hack is needed to get the links right to those pages.
if ( tag[2] == "index.txt" ) {
tag[2] = "vimindex.txt"
} else if ( tag[2] == "help.txt" ) {
tag[2] = "index.txt"
}
tagkey[tag[1]]="yes";tagref[tag[1]]=tag[2];
}
skip_word["and"]="yes";
skip_word["backspace"]="yes";
skip_word["beep"]="yes";
skip_word["bugs"]="yes";
skip_word["da"]="yes";
skip_word["end"]="yes";
skip_word["ftp"]="yes";
skip_word["go"]="yes";
skip_word["help"]="yes";
skip_word["home"]="yes";
skip_word["news"]="yes";
skip_word["index"]="yes";
skip_word["insert"]="yes";
skip_word["into"]="yes";
skip_word["put"]="yes";
skip_word["reference"]="yes";
skip_word["section"]="yes";
skip_word["space"]="yes";
skip_word["starting"]="yes";
skip_word["toggle"]="yes";
skip_word["various"]="yes";
skip_word["version"]="yes";
skip_word["is"]="yes";
}
#
# protect special chars
#
/[><&á]/ {gsub(/&/,"\\&amp;");gsub(/>/,"\\&gt;");gsub(/</,"\\&lt;");gsub("á","\\&aacute;");}
#
# end of sample lines by non-blank in first column
#
sample == "yes" && substr($0,1,4) == "&lt;" { sample = "no"; gsub(/^&lt;/, " "); }
sample == "yes" && substr($0,1,1) != " " && substr($0,1,1) != " " && length($0) > 0 { sample = "no" }
#
# sample lines printed bold unless empty...
#
sample == "yes" && $0 =="" { print ""; next; }
sample == "yes" && $0 !="" { print "<B>" $0 "</B>"; next; }
#
# start of sample lines in next line
#
$0 == "&gt;" { sample = "yes"; print ""; next; }
substr($0,length($0)-4,5) == " &gt;" { sample = "yes"; gsub(/ &gt;$/, ""); }
#
# header lines printed bold, colored
#
substr($0,length($0),1) == "~" { print "<B><FONT COLOR=\"PURPLE\">" substr($0,1,length($0)-1) "</FONT></B>"; next; }
#
#ad hoc code
#
/^"\|& / {gsub(/\|/,"\\&#124;"); }
/ = b / {gsub(/ b /," \\&#98; "); }
#
# one letter tag
#
/[ ]\*.\*[ ]/ {gsub(/\*/,"ZWWZ"); }
#
# isolated "*"
#
/[ ]\*[ ]/ {gsub(/ \* /," \\&#42; ");
gsub(/ \* /," \\&#42; ");
gsub(/ \* /," \\&#42; ");
gsub(/ \* /," \\&#42; "); }
#
# tag start
#
/[ ]\*[^ ]/ {gsub(/ \*/," ZWWZ");gsub(/ \*/," ZWWZ");}
/^\*[^ ]/ {gsub(/^\*/,"ZWWZ");}
#
# tag end
#
/[^ ]\*$/ {gsub(/\*$/,"ZWWZ");}
/[^ \/ ]\*[ ]/ {gsub(/\*/,"ZWWZ");}
#
# isolated "|"
#
/[ ]\|[ ]/ {gsub(/ \| /," \\&#124; ");
gsub(/ \| /," \\&#124; ");
gsub(/ \| /," \\&#124; ");
gsub(/ \| /," \\&#124; "); }
/'\|'/ { gsub(/'\|'/,"'\\&#124;'"); }
/\^V\|/ {gsub(/\^V\|/,"^V\\&#124;");}
/ \\\| / {gsub(/\|/,"\\&#124;");}
#
# one letter pipes and "||" false pipe (digraphs)
#
/[ ]\|.\|[ ]/ && asciiart == "no" {gsub(/\|/,"YXXY"); }
/^\|.\|[ ]/ {gsub(/\|/,"YXXY"); }
/\|\|/ {gsub(/\|\|/,"\\&#124;\\&#124;"); }
/^shellpipe/ {gsub(/\|/,"\\&#124;"); }
#
# pipe start
#
/[ ]\|[^ ]/ && asciiart == "no" {gsub(/ \|/," YXXY");
gsub(/ \|/," YXXY");}
/^\|[^ ]/ {gsub(/^\|/,"YXXY");}
#
# pipe end
#
/[^ ]\|$/ && asciiart == "no" {gsub(/\|$/,"YXXY");}
/[^ ]\|[s ,.); ]/ && asciiart == "no" {gsub(/\|/,"YXXY");}
/[^ ]\|]/ && asciiart == "no" {gsub(/\|/,"YXXY");}
#
# various
#
/'"/ {gsub(/'"/,"\\&#39;\\&#34;'");}
/"/ {gsub(/"/,"\\&quot;");}
/%/ {gsub(/%/,"\\&#37;");}
NR == 1 { nf=split(FILENAME,f,".")
print "<HTML>";
print "<HEAD>"
if ( FILENAME == "mbyte.txt" ) {
# needs utf-8 as uses many languages
print "<META HTTP-EQUIV=\"Content-type\" content=\"text/html; charset=UTF-8\">";
} else {
# common case - Latin1
print "<META HTTP-EQUIV=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">";
}
print "<TITLE>Nvim documentation: " f[1] "</TITLE>";
print "</HEAD>";
print "<BODY BGCOLOR=\"#ffffff\">";
print "<H1>Nvim documentation: " f[1] "</H1>";
print "<A NAME=\"top\"></A>";
if ( FILENAME != "help.txt" ) {
print "<A HREF=\"index.html\">main help file</A>\n";
}
print "<HR>";
print "<PRE>";
filename=f[1]".html";
}
# set to a low value to test for few lines of text
# NR == 99999 { exit; }
# ignore underlines and tags
substr($0,1,5) == " vim:" { next; }
substr($0,1,4) == "vim:" { next; }
# keep just whole lines of "-", "="
substr($0,1,3) == "===" && substr($0,75,1) != "=" { next; }
substr($0,1,3) == "---" && substr($0,75,1) != "-" { next; }
{
nstar = split($0,s,"ZWWZ");
for ( i=2 ; i <= nstar ; i=i+2 ) {
nbla=split(s[i],blata,"[ ]");
if ( nbla > 1 ) {
gsub("ZWWZ","*");
nstar = split($0,s,"ZWWZ");
}
}
npipe = split($0,p,"YXXY");
for ( i=2 ; i <= npipe ; i=i+2 ) {
nbla=split(p[i],blata,"[ ]");
if ( nbla > 1 ) {
gsub("YXXY","|");
ntabs = split($0,p,"YXXY");
}
}
}
FILENAME == "gui.txt" && asciiart == "no" \
&& $0 ~ /\+----/ && $0 ~ /----\+/ {
asciiart= "yes";
asciicnt=0;
}
FILENAME == "usr_20.txt" && asciiart == "no" \
&& $0 ~ /an empty line at the end:/ {
asciiart= "yes";
asciicnt=0;
}
asciiart == "yes" && $0=="" { asciicnt++; }
asciiart == "yes" && asciicnt == 2 { asciiart = "no"; }
asciiart == "yes" { npipe = 1; }
# { print NR " <=> " asciiart; }
#
# line contains "*"
#
nstar > 2 && npipe < 3 {
printf("\n");
for ( i=1; i <= nstar ; i=i+2 ) {
this=s[i];
put_this();
ii=i+1;
nbla = split(s[ii],blata," ");
if ( ii <= nstar ) {
if ( nbla == 1 && substr(s[ii],length(s[ii]),1) != " " ) {
printf("*<A NAME=\"%s\"></A>",s[ii]);
printf("<B>%s</B>*",s[ii]);
} else {
printf("*%s*",s[ii]);
}
}
}
printf("\n");
next;
}
#
# line contains "|"
#
npipe > 2 && nstar < 3 {
if ( npipe%2 == 0 ) {
for ( i=1; i < npipe ; i++ ) {
gsub("ZWWZ","*",p[i]);
printf("%s|",p[i]);
}
printf("%s\n",p[npipe]);
next;
}
for ( i=1; i <= npipe ; i++ )
{
if ( i % 2 == 1 ) {
gsub("ZWWZ","*",p[i]);
this=p[i];
put_this();
}
else {
nfn=split(p[i],f,".");
if ( nfn == 1 || f[2] == "" || f[1] == "" || length(f[2]) < 3 ) {
find_tag1();
}
else {
if ( f[1] == "index" ) {
printf "|<A HREF=\"vimindex.html\">" p[i] "</A>|";
} else {
if ( f[1] == "help" ) {
printf "|<A HREF=\"index.html\">" p[i] "</A>|";
} else {
printf "|<A HREF=\"" f[1] ".html\">" p[i] "</A>|";
}
}
}
}
}
printf("\n");
next;
}
#
# line contains both "|" and "*"
#
npipe > 2 && nstar > 2 {
printf("\n");
for ( j=1; j <= nstar ; j=j+2 ) {
npipe = split(s[j],p,"YXXY");
if ( npipe > 1 ) {
for ( np=1; np<=npipe; np=np+2 ) {
this=p[np];
put_this();
i=np+1;find_tag1();
}
} else {
this=s[j];
put_this();
}
jj=j+1;
nbla = split(s[jj],blata," ");
if ( jj <= nstar && nbla == 1 && s[jj] != "" ) {
printf("*<A NAME=\"%s\"></A>",s[jj]);
printf("<B>%s</B>*",s[jj]);
} else {
if ( s[jj] != "" ) {
printf("*%s*",s[jj]);
}
}
}
printf("\n");
next;
}
#
# line contains e-mail address john.doe@some.place.edu
#
$0 ~ /@/ && $0 ~ /[a-zA-Z0-9]@[a-z]/ \
{
nemail=split($0,em," ");
if ( substr($0,1,1) == " " ) { printf(" "); }
for ( i=1; i <= nemail; i++ ) {
if ( em[i] ~ /@/ ) {
if ( substr(em[i],2,3) == "lt;" && substr(em[i],length(em[i])-2,3) == "gt;" ) {
mailaddr=substr(em[i],5,length(em[i])-8);
printf("<A HREF=\"mailto:%s\">&lt;%s&gt;</A> ",mailaddr,mailaddr);
} else {
if ( substr(em[i],2,3) == "lt;" && substr(em[i],length(em[i])-3,3) == "gt;" ) {
mailaddr=substr(em[i],5,length(em[i])-9);
printf("<A HREF=\"mailto:%s\">&lt;%s&gt;</A>%s ",mailaddr,mailaddr,substr(em[i],length(em[i]),1));
} else {
printf("<A HREF=\"mailto:%s\">%s</A> ",em[i],em[i]);
}
}
} else {
printf("%s ",em[i]);
}
}
#print "*** " NR " " FILENAME " - possible mail ref";
printf("\n");
next;
}
#
# line contains http / ftp reference
#
$0 ~ /http:\/\// || $0 ~ /ftp:\/\// {
gsub("URL:","");
gsub("&lt;","");
gsub("&gt;","");
gsub("\\(","");
gsub("\\)","");
nemail=split($0,em," ");
for ( i=1; i <= nemail; i++ ) {
if ( substr(em[i],1,5) == "http:" ||
substr(em[i],1,4) == "ftp:" ) {
if ( substr(em[i],length(em[i]),1) != "." ) {
printf(" <A HREF=\"%s\">%s</A>",em[i],em[i]);
} else {
em[i]=substr(em[i],1,length(em[i])-1);
printf(" <A HREF=\"%s\">%s</A>.",em[i],em[i]);
}
} else {
printf(" %s",em[i]);
}
}
#print "*** " NR " " FILENAME " - possible http ref";
printf("\n");
next;
}
#
# some lines contains just one "almost regular" "*"...
#
nstar == 2 {
this=s[1];
put_this();
printf("*");
this=s[2];
put_this();
printf("\n");
next;
}
#
# regular line
#
{ ntabs = split($0,tb," ");
for ( i=1; i < ntabs ; i++) {
this=tb[i];
put_this();
printf(" ");
}
this=tb[ntabs];
put_this();
printf("\n");
}
asciiart == "yes" && $0 ~ /\+-\+--/ \
&& $0 ~ "scrollbar" { asciiart = "no"; }
END {
topback();
print "</PRE>\n</BODY>\n\n\n</HTML>"; }
#
# as main we keep index.txt (by default)
#
function topback () {
if ( FILENAME != "tags" ) {
if ( FILENAME != "help.txt" ) {
printf("<A HREF=\"#top\">top</A> - ");
printf("<A HREF=\"index.html\">main help file</A>\n");
} else {
printf("<A HREF=\"#top\">top</A>\n");
}
}
}
function find_tag1() {
if ( p[i] == "" ) { return; }
if ( tagkey[p[i]] == "yes" ) {
which=tagref[p[i]];
put_href();
return;
}
# if not found, then we have a problem
print "============================================" >>"errors.log";
print FILENAME ", line " NR ", pointer: >>" p[i] "<<" >>"errors.log";
print $0 >>"errors.log";
which="intro.html";
put_href();
}
function see_tag() {
# ad-hoc code:
if ( atag == "\"--" || atag == "--\"" ) { return; }
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
allow_one_char="no";
find_tag2();
if ( done == "yes" ) { return; }
rightchar=substr(atag,length(atag),1);
if ( rightchar == "." \
|| rightchar == "," \
|| rightchar == ":" \
|| rightchar == ";" \
|| rightchar == "!" \
|| rightchar == "?" \
|| rightchar == ")" ) {
atag=substr(atag,1,length(atag)-1);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
find_tag2();
if ( done == "yes" ) { printf("%s",rightchar);return; }
leftchar=substr(atag,1,1);
lastbut1=substr(atag,length(atag),1);
if ( leftchar == "'" && lastbut1 == "'" ) {
allow_one_char="yes";
atag=substr(atag,2,length(atag)-2);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
printf("%s",leftchar);
aword=substr(atag,1,length(atag))""lastbut1""rightchar;
find_tag2();
if ( done == "yes" ) { printf("%s%s",lastbut1,rightchar);return; }
}
}
atag=aword;
leftchar=substr(atag,1,1);
if ( leftchar == "'" && rightchar == "'" ) {
allow_one_char="yes";
atag=substr(atag,2,length(atag)-2);
if ( atag == "<" ) { printf(" |%s|%s| ",atag,p[2]); }
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
printf("%s",leftchar);
find_tag2();
if ( done == "yes" ) { printf("%s",rightchar);return; }
printf("%s%s",atag,rightchar);
return;
}
last2=substr(atag,length(atag)-1,2);
first2=substr(atag,1,2);
if ( first2 == "('" && last2 == "')" ) {
allow_one_char="yes";
atag=substr(atag,3,length(atag)-4);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
printf("%s",first2);
find_tag2();
if ( done == "yes" ) { printf("%s",last2);return; }
printf("%s%s",atag,last2);
return;
}
if ( last2 == ".)" ) {
atag=substr(atag,1,length(atag)-2);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
find_tag2();
if ( done == "yes" ) { printf("%s",last2);return; }
printf("%s%s",atag,last2);
return;
}
if ( last2 == ")." ) {
atag=substr(atag,1,length(atag)-2);
find_tag2();
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
if ( done == "yes" ) { printf("%s",last2);return; }
printf("%s%s",atag,last2);
return;
}
first6=substr(atag,1,6);
last6=substr(atag,length(atag)-5,6);
if ( last6 == atag ) {
printf("%s",aword);
return;
}
last6of7=substr(atag,length(atag)-6,6);
if ( first6 == "&quot;" && last6of7 == "&quot;" && length(atag) > 12 ) {
allow_one_char="yes";
atag=substr(atag,7,length(atag)-13);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
printf("%s",first6);
find_tag2();
if ( done == "yes" ) { printf("&quot;%s",rightchar); return; }
printf("%s&quot;%s",atag,rightchar);
return;
}
if ( first6 == "&quot;" && last6 != "&quot;" ) {
allow_one_char="yes";
atag=substr(atag,7,length(atag)-6);
if ( atag == "[" ) { printf("&quot;%s",atag); return; }
if ( atag == "." ) { printf("&quot;%s",atag); return; }
if ( atag == ":" ) { printf("&quot;%s",atag); return; }
if ( atag == "a" ) { printf("&quot;%s",atag); return; }
if ( atag == "A" ) { printf("&quot;%s",atag); return; }
if ( atag == "g" ) { printf("&quot;%s",atag); return; }
if_already();
if ( already == "yes" ) {
printf("&quot;%s",atag);
return;
}
printf("%s",first6);
find_tag2();
if ( done == "yes" ) { return; }
printf("%s",atag);
return;
}
if ( last6 == "&quot;" && first6 == "&quot;" ) {
allow_one_char="yes";
atag=substr(atag,7,length(atag)-12);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
printf("%s",first6);
find_tag2();
if ( done == "yes" ) { printf("%s",last6);return; }
printf("%s%s",atag,last6);
return;
}
last6of7=substr(atag,length(atag)-6,6);
if ( last6of7 == "&quot;" && first6 == "&quot;" ) {
allow_one_char="yes";
atag=substr(atag,7,length(atag)-13);
#printf("\natag=%s,aword=%s\n",atag,aword);
if_already();
if ( already == "yes" ) {
printf("%s",aword);
return;
}
printf("%s",first6);
find_tag2();
if ( done == "yes" ) { printf("%s%s",last6of7,rightchar);return; }
printf("%s%s%s",atag,last6of7,rightchar);
return;
}
printf("%s",aword);
}
function find_tag2() {
done="no";
# no blanks present in a tag...
ntags=split(atag,blata,"[ ]");
if ( ntags > 1 ) { return; }
if ( ( allow_one_char == "no" ) && \
( index("!#$%&'()+,-./0:;=?@ACINX\\[\\]^_`at\\{\\}~",atag) !=0 ) ) {
return;
}
if ( skip_word[atag] == "yes" ) { return; }
if ( wasset == "yes" && lineset == NR ) {
wasset="no";
see_opt();
if ( done_opt == "yes" ) {return;}
}
if ( wasset == "yes" && lineset != NR ) {
wasset="no";
}
if ( atag == ":set" ) {
wasset="yes";
lineset=NR;
}
if ( tagkey[atag] == "yes" ) {
which=tagref[atag];
put_href2();
done="yes";
}
}
function find_tag3() {
done="no";
# no blanks present in a tag...
ntags=split(btag,blata,"[ ]");
if ( ntags > 1 ) { return; }
if ( ( allow_one_char == "no" ) && \
( index("!#$%&'()+,-./0:;=?@ACINX\\[\\]^_`at\\{\\}~",btag) !=0 ) ) {
return;
}
if ( skip_word[btag] == "yes" ) { return; }
if ( tagkey[btag] == "yes" ) {
which=tagref[btag];
put_href3();
done="yes";
}
}
function put_href() {
if ( p[i] == "" ) { return; }
if ( which == FILENAME ) {
printf("|<A HREF=\"#%s\">%s</A>|",p[i],p[i]);
}
else {
nz=split(which,zz,".");
if ( zz[2] == "txt" || zz[1] == "tags" ) {
printf("|<A HREF=\"%s.html#%s\">%s</A>|",zz[1],p[i],p[i]);
}
else {
printf("|<A HREF=\"intro.html#%s\">%s</A>|",p[i],p[i]);
}
}
}
function put_href2() {
if ( atag == "" ) { return; }
if ( which == FILENAME ) {
printf("<A HREF=\"#%s\">%s</A>",atag,atag);
}
else {
nz=split(which,zz,".");
if ( zz[2] == "txt" || zz[1] == "tags" ) {
printf("<A HREF=\"%s.html#%s\">%s</A>",zz[1],atag,atag);
}
else {
printf("<A HREF=\"intro.html#%s\">%s</A>",atag,atag);
}
}
}
function put_href3() {
if ( btag == "" ) { return; }
if ( which == FILENAME ) {
printf("<A HREF=\"#%s\">%s</A>",btag,btag2);
}
else {
nz=split(which,zz,".");
if ( zz[2] == "txt" || zz[1] == "tags" ) {
printf("<A HREF=\"%s.html#%s\">%s</A>",zz[1],btag,btag2);
}
else {
printf("<A HREF=\"intro.html#%s\">%s</A>",btag,btag2);
}
}
}
function put_this() {
ntab=split(this,ta," ");
for ( nta=1 ; nta <= ntab ; nta++ ) {
ata=ta[nta];
lata=length(ata);
aword="";
for ( iata=1 ; iata <=lata ; iata++ ) {
achar=substr(ata,iata,1);
if ( achar != " " ) { aword=aword""achar; }
else {
if ( aword != "" ) { atag=aword;
see_tag();
aword="";
printf(" "); }
else {
printf(" ");
}
}
}
if ( aword != "" ) { atag=aword;
see_tag();
}
if ( nta != ntab ) { printf(" "); }
}
}
function if_already() {
already="no";
if ( npipe < 2 ) { return; }
if ( atag == ":au" && p[2] == ":autocmd" ) { already="yes";return; }
for ( npp=2 ; npp <= npipe ; npp=npp+2 ) {
if ( ( (index(p[npp],atag)) != 0 \
&& length(p[npp]) > length(atag) \
&& length(atag) >= 1 \
) \
|| (p[npp] == atag) \
) {
# printf("p=|%s|,tag=|%s| ",p[npp],atag);
already="yes"; return; }
}
}
function see_opt() {
done_opt="no";
stag=atag;
nfields = split(atag,tae,"=");
if ( nfields > 1 ) {
btag="'"tae[1]"'";
btag2=tae[1];
find_tag3();
if (done == "yes") {
for ( ntae=2 ; ntae <= nfields ; ntae++ ) {
printf("=%s",tae[ntae]);
}
atag=stag;
done_opt="yes";
return;
}
btag=tae[1];
btag2=tae[1];
find_tag3();
if ( done=="yes" ) {
for ( ntae=2 ; ntae <= nfields ; ntae++ ) {
printf("=%s",tae[ntae]);
}
atag=stag;
done_opt="yes";
return;
}
}
nfields = split(atag,tae,"&quot;");
if ( nfields > 1 ) {
btag="'"tae[1]"'";
btag2=tae[1];
find_tag3();
if (done == "yes") {
printf("&quot;");
atag=stag;
done_opt="yes";
return;
}
btag=tae[1];
btag2=tae[1];
find_tag3();
if (done == "yes") {
printf("&quot;");
atag=stag;
done_opt="yes";
return;
}
}
btag="'"tae[1]"'";
btag2=tae[1];
find_tag3();
if (done == "yes") {
atag=stag;
done_opt="yes";
return;
}
btag=tae[1];
btag2=tae[1];
find_tag3();
if (done == "yes") {
atag=stag;
done_opt="yes";
return;
}
atag=stag;
}

View File

@ -1,42 +0,0 @@
BEGIN { FS=" "; }
NR == 1 { nf=split(FILENAME,f,".")
print "<HTML>";
print "<HEAD><TITLE>" f[1] "</TITLE></HEAD>";
print "<BODY BGCOLOR=\"#ffffff\">";
print "<H1>Vim Documentation: " f[1] "</H1>";
print "<A NAME=\"top\"></A>";
print "<HR>";
print "<PRE>";
}
{
#
# protect special chars
#
gsub(/&/,"\\&amp;");
gsub(/>/,"\\&gt;");
gsub(/</,"\\&lt;");
gsub(/"/,"\\&quot;");
gsub(/%/,"\\&#37;");
nf=split($0,tag," ");
tagkey[t]=tag[1];tagref[t]=tag[2];tagnum[t]=NR;
print $1 " " $2 " line " NR >"tags.ref"
n=split($2,w,".");
printf ("|<A HREF=\"%s.html#%s\">%s</A>| %s\n",w[1],$1,$1,$2);
}
END {
topback();
print "</PRE>\n</BODY>\n\n\n</HTML>";
}
#
# as main we keep index.txt (by default)
# other candidate, help.txt
#
function topback () {
printf("<A HREF=\"#top\">top</A> - ");
printf("<A HREF=\"help.html\">back to help</A>\n");
}

View File

@ -2782,7 +2782,7 @@ your browsing preferences. (see also: |netrw-settings|)
history are saved (as .netrwbook and
.netrwhist).
Netrw uses |expand()| on the string.
default: stdpath('data') (see |stdpath()|)
default: stdpath("data") (see |stdpath()|)
*g:netrw_keepdir* =1 (default) keep current directory immune from
the browsing directory.

View File

@ -471,7 +471,7 @@ flag when defining the function, it is not relevant when executing it. >
:set cpo-=C
<
*line-continuation-comment*
To add a comment in between the lines start with '"\ '. Notice the space
To add a comment in between the lines start with `'"\ '`. Notice the space
after the backslash. Example: >
let array = [
"\ first entry comment
@ -491,7 +491,7 @@ Rationale:
continuation lines to be part of the comment. Since it was like this
for a long time, when making it possible to add a comment halfway a
sequence of continuation lines, it was not possible to use \", since
that was a valid continuation line. Using '"\ ' comes closest, even
that was a valid continuation line. Using `'"\ '` comes closest, even
though it may look a bit weird. Requiring the space after the
backslash is to make it very unlikely this is a normal comment line.

View File

@ -1357,7 +1357,7 @@ LOG FILE *$NVIM_LOG_FILE* *E5430*
Besides 'debug' and 'verbose', Nvim keeps a general log file for internal
debugging, plugins and RPC clients. >
:echo $NVIM_LOG_FILE
By default, the file is located at stdpath('log')/log unless that path
By default, the file is located at stdpath("log")/log unless that path
is inaccessible or if $NVIM_LOG_FILE was set before |startup|.

View File

@ -67,7 +67,7 @@ local exclude_invalid = {
["v:_null_string"] = "builtin.txt",
["vim.lsp.buf_request()"] = "lsp.txt",
["vim.lsp.util.get_progress_messages()"] = "lsp.txt",
["vim.treesitter.start()"] = "treesitter.txt"
["vim.treesitter.start()"] = "treesitter.txt",
}
local function tofile(fname, text)
@ -96,11 +96,6 @@ local function url_encode(s)
'g')
end
-- Removes the ">" and "<" chars that delineate a codeblock in Vim :help files.
local function trim_gt_lt(s)
return s:gsub('^%s*>%s*\n', ''):gsub('\n<', '')
end
local function expandtabs(s)
return s:gsub('\t', (' '):rep(8))
end
@ -123,15 +118,29 @@ local function basename_noext(f)
end
local function is_blank(s)
return not not s:find('^%s*$')
return not not s:find([[^[\t ]*$]])
end
local function trim(s)
return vim.trim(s)
local function trim(s, dir)
return vim.fn.trim(s, '\r\t\n ', dir or 0)
end
local function trim_bullet(s)
return s:gsub('^%s*[-*•]%s', '')
-- Remove common punctuation from URLs.
--
-- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc
--
-- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
local function fix_url(url)
local removed_chars = ''
local fixed_url = url
-- Remove up to one of each char from end of the URL, in this order.
for _, c in ipairs({ '.', ')', }) do
if fixed_url:sub(-1) == c then
removed_chars = c .. removed_chars
fixed_url = fixed_url:sub(1, -2)
end
end
return fixed_url, removed_chars
end
-- Checks if a given line is a "noise" line that doesn't look good in HTML form.
@ -357,7 +366,8 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
if node_name == 'help_file' then -- root node
return text
elseif node_name == 'url' then
return ('%s<a href="%s">%s</a>'):format(ws(), trimmed, trimmed)
local fixed_url, removed_chars = fix_url(trimmed)
return ('%s<a href="%s">%s</a>%s'):format(ws(), fixed_url, fixed_url, removed_chars)
elseif node_name == 'word' or node_name == 'uppercase_name' then
return html_esc(text)
elseif node_name == 'h1' or node_name == 'h2' or node_name == 'h3' then
@ -383,38 +393,37 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
return ''
end
if opt.old then
-- XXX: Treat old docs as preformatted; random indentation is used for layout there.
return ('<div class="old-help-para">%s</div>\n'):format(text)
-- XXX: Treat "old" docs as preformatted: they use indentation for layout.
-- Trim trailing newlines to avoid too much whitespace between divs.
return ('<div class="old-help-para">%s</div>\n'):format(trim(text, 2))
end
return string.format('<div class="help-para">\n%s\n</div>\n', text)
elseif node_name == 'line' then
local sib = root:prev_sibling()
local sib_last = sib and sib:named_child(sib:named_child_count() - 1)
local in_li = false
-- XXX: parser bug: (codeblock) without terminating "<" consumes first char of the next (line). Recover it here.
local recovered = (sib_last and sib_last:type() == 'codeblock') and node_text(root:prev_sibling()):sub(-1) or ''
recovered = recovered == '<' and '' or html_esc(recovered)
-- XXX: see if we are currently "in" a listitem.
while sib ~= nil and not in_li do
in_li = (sib:type() == 'line_li')
sib = sib:prev_sibling()
if parent ~= 'codeblock' and (is_blank(text) or is_noise(text, stats.noise_lines)) then
return '' -- Discard common "noise" lines.
end
-- Close the current listitem.
local close = (in_li and next_ ~= 'line') and '</div>' or ''
if is_blank(text) or is_noise(text, stats.noise_lines) then
return close -- Discard common "noise" lines.
end
local div = (root:child(0) and root:child(0):type() == 'column_heading') or close ~= ''
return string.format('%s%s%s%s', recovered, div and trim(text) or text, div and '' or '\n', close)
-- XXX: Avoid newlines (too much whitespace) after block elements in old (preformatted) layout.
local div = opt.old and root:child(0) and vim.tbl_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type())
return string.format('%s%s', div and trim(text) or text, div and '' or '\n')
elseif node_name == 'line_li' then
-- Close the listitem immediately if the next sibling is not a line.
local close = (next_ ~= 'line') and '</div>' or ''
return string.format('<div class="help-li">%s %s', trim_bullet(text), close)
local sib = root:prev_sibling()
local prev_li = sib and sib:type() == 'line_li'
if not prev_li then
opt.indent = 1
else
-- The previous listitem _sibling_ is _logically_ the _parent_ if it is indented less.
local parent_indent = get_indent(node_text(sib))
local this_indent = get_indent(node_text())
if this_indent > parent_indent then
opt.indent = opt.indent + 1
elseif this_indent < parent_indent then
opt.indent = math.max(1, opt.indent - 1)
end
end
local margin = opt.indent == 1 and '' or ('margin-left: %drem;'):format((1.5 * opt.indent))
return string.format('<div class="help-li" style="%s">%s</div>', margin, text)
elseif node_name == 'taglink' or node_name == 'optionlink' then
if root:has_error() then
return text
@ -429,7 +438,10 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
elseif node_name == 'argument' then
return ('%s<code>{%s}</code>'):format(ws(), text)
elseif node_name == 'codeblock' then
return ('<pre>%s</pre>'):format(html_esc(trim_indent(trim_gt_lt(text))))
if is_blank(text) then
return ''
end
return ('<pre>%s</pre>'):format(html_esc(trim(trim_indent(text), 2)))
elseif node_name == 'tag' then -- anchor
if root:has_error() then
return text
@ -630,7 +642,9 @@ local function gen_one(fname, to_fname, old, commit)
local main = ''
for _, tree in ipairs(lang_tree:trees()) do
main = main .. (visit_node(tree:root(), 0, tree, headings, { buf = buf, old = old, fname = fname, to_fname = to_fname }, stats))
main = main .. (visit_node(tree:root(), 0, tree, headings,
{ buf = buf, old = old, fname = fname, to_fname = to_fname, indent = 1, },
stats))
end
main = ([[
@ -718,6 +732,17 @@ local function gen_css(fname)
position: fixed;
left: 67%;
}
.golden-grid {
display: grid;
grid-template-columns: 65% auto;
grid-gap: 1em;
}
}
@media (max-width: 40em) {
.golden-grid {
/* Disable grid for narrow viewport (mobile phone). */
display: block;
}
}
@media (prefers-color-scheme: dark) {
:root {
@ -831,11 +856,6 @@ local function gen_css(fname)
color: gray;
font-size: smaller;
}
.golden-grid {
display: grid;
grid-template-columns: 65% auto;
grid-gap: 1em;
}
]]
tofile(fname, css)
end
@ -869,6 +889,22 @@ function M._test()
eq(5, get_indent(' a\n \n b\n c\n d\n e\n'))
eq('a\n \n b\n c\n d\n e\n', trim_indent(' a\n \n b\n c\n d\n e\n'))
local fixed_url, removed_chars = fix_url('https://example.com).')
eq('https://example.com', fixed_url)
eq(').', removed_chars)
fixed_url, removed_chars = fix_url('https://example.com.)')
eq('https://example.com.', fixed_url)
eq(')', removed_chars)
fixed_url, removed_chars = fix_url('https://example.com.')
eq('https://example.com', fixed_url)
eq('.', removed_chars)
fixed_url, removed_chars = fix_url('https://example.com)')
eq('https://example.com', fixed_url)
eq(')', removed_chars)
fixed_url, removed_chars = fix_url('https://example.com')
eq('https://example.com', fixed_url)
eq('', removed_chars)
print('all tests passed')
end

View File

@ -21,7 +21,7 @@ describe(':help docs', function()
ok(rv.helpfiles > 100, '>100 :help files', rv.helpfiles)
-- Check that parse errors did not increase wildly.
-- TODO: Fix all parse errors in :help files.
ok(rv.err_count < 250, '<250 parse errors', rv.err_count)
ok(rv.err_count < 280, '<280 parse errors', rv.err_count)
eq({}, rv.invalid_links, exec_lua([[return 'found invalid :help tag links:\n'..vim.inspect(...)]], rv.invalid_links))
end)