Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MANPAGER, :Man does not follow the correct section of a man page #11244

Closed
FueLee opened this issue Sep 28, 2022 · 9 comments
Closed

MANPAGER, :Man does not follow the correct section of a man page #11244

FueLee opened this issue Sep 28, 2022 · 9 comments
Labels

Comments

@FueLee
Copy link

FueLee commented Sep 28, 2022

Steps to reproduce

  1. vim -c MANPAGER -u NORC -i NONE - (set MANPAGER environment variable, without user config file)
  2. man 2 read
  3. scroll down to ERRORS where there is a "link" to open(2). (See open(2) for further details on...)
  4. Hit Shift + k = (K) on "open(2)"
  5. xdg-open(1) is opened, not open(2)

Expected behaviour

After "Shift+k" on "open(2)" the open(2) manual page should be opened.

Later, I modified the iskeyword value: set iskeyword+=(,)

in ...plugin/manpager.vim and finally moved this into ...ftplugin/man.vim and the correct man page was opened next time for those cases:

  • in terminal/console at bash: man 2 read
  • in vim as :Man 2 read

Version of Vim

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Sep 13 2022 09:35:02), Included patches: 1-3995, 4563, 4646, 4774, 4895, 4899, 4901, 4919

Environment

Ubuntu Linux 22.04.1 LTS
Virtual console (dev/tty) $TERM=linux, Virtual terminal $TERM=rxvt-unicode-256color
$SHELL=/bin/bash
$BASH_VERSION=5.1.16(1)-release

Logs and stack traces

No response

@FueLee FueLee added the bug label Sep 28, 2022
@lacygoill
Copy link

I can't reproduce this issue on my machine:
gif

When I press K on the open(2) token, the manpage for open(2) is opened, not the one for xdg-open(1).

Version of Vim

9.0 Included patches: 1-612

Environment

Operating system: Ubuntu 20.04.5 LTS
Terminal: XTerm(353)
Value of $TERM: xterm-256color
Shell: GNU bash, version 5.0.17

@brammool
Copy link
Contributor

brammool commented Sep 28, 2022 via email

@FueLee
Copy link
Author

FueLee commented Sep 28, 2022

Thanks for the suggestion! I checked the mapping.

I restored the original $VIMRUNTIME.../plugin/manpager.vim, $VIMRUNTIM.../ftplugin/man.vim of my installation (v8.2) and run the steps again in virtual terminal with man 2 read shell command.

The ":verbose map K" outputs this: "No mapping found". But I guess this is the result of the "-u NORC" in the MANPAGER environment variable. Checked the initialization with the ":scriptnames" command and it lists only the $VIMRUNTIME related paths, no plugins are loaded, just the system ones. Actually I do not use any plugin currently, just the built in stuffs (Ntree, matchit, less), so my ˜/.vim/ dir have only vimrc and viminfo files.

The ":set iskeyword?" outputs this "iskeyword=0,48-57,_,192-255,.,-,:", the $VIMRUNTIME...plugin/manpager.vim script add the colon char to the default value. When I hit K on:

  • the "open(2)" word and the cursor is on "o", it redirects to xgd-open(1), ok "(" , ")" is not part of the keyword definition and "man open" actually opens the first match, that is in section 1, xdg-open.
  • the "open(2)" word and the cursor is on "(", it says "No manual entry for 2", guess because the "(" char is not keyword, so it use the following char that is "2", and for sure, there is no such manual page. Same as "man 2" on command line.

If I update the iskeyword in this vim session with: "set iskeyword+=(,)" and hit K, the open(2) manual page is displayed, because now the search string is open(2) and not open.

What I would like to add is just that in version 8.2 the extension of "iskeyword" seems to me a good solution, but I did not install version 9 yet, but it should work differently according to the gif.

@lacygoill
Copy link

Try to reproduce on master. If the issue persists, execute this Ex command while your cursor is on open(2):

:debug normal K

Then, at the debug prompt, execute >step. What does Vim print then? FWIW, this is what I get:

Entering Debug mode.  Type "cont" to continue.
cmd: normal K
cmd: ! man 'open(2)'

Not sure it matters here, but what's the value of $MANSECT?


Also, you should be able to specify the desired manual section by prefixing the normal K command with a count. For example, pressing 2K should only look inside section 2 (where open(2) can be found, but not xdg-open(1)).

@FueLee
Copy link
Author

FueLee commented Sep 29, 2022

What a nice internals! :) I tried this :debug normal K and when the iskeyword did not contain (,) it returned back with "open", but with (,) it gave me "open(2)", but just to mention again, I tried this on version 8.2.

If you mean master on the latest and greatest vim, I did not install it so far, so I could not test it, but I belive it works in versino 9.x, so I close this, thanks!

@FueLee FueLee closed this as completed Sep 29, 2022
@lacygoill
Copy link

There is a known issue which causes :Man to load a man page from a wrong section if MANSECT is set to a non-empty value. This is caused by a bug in man-db which was fixed recently. You need version 2.10.0 or higher to get the fix.


In any case, the way 'iskeyword' is set could be improved.

First, there is no reason to set it in 3 different locations:

" Is this useful? Should allow for using K on word with a colon.
setlocal iskeyword+=:

setlocal iskeyword+=: filetype=man

" allow dot and dash in manual page name.
setlocal iskeyword+=\.,-

Second, += seems unreliable; = might be better to be sure which characters are allowed in the name of a man page.

Third, some special characters are missing, like @ and + (as well as parentheses for references). Those characters can be found with this shell command:

$ apropos . | /tmp/awk.awk

Where /tmp/awk.awk contains this code:

#!/usr/bin/awk -f

BEGIN {
    print "unmatched man pages:\n"
}

{ $0 = $1 }

/[^a-zA-Z_0-9:.@+-]/ { print $0 }

/-/ { hyphen++ }
/:/ { colon++ }
/\./ { dot++ }
/@/ { at++ }
/+/ { plus++ }

END {
    print "\n============\n"
    printf "hyphen:\t%4d\n", hyphen
    printf "colon:\t%4d\n", colon
    printf "dot:\t%4d\n", dot
    printf "at:\t%4d\n", at
    printf "plus:\t%4d\n", plus
}

On my machine, the output is:

unmatched man pages:

[

============

hyphen: 1868
colon:  1068
dot:     481
at:       15
plus:      9

As a suggestion, here is a patch:

diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 0f6d36c2d..98fd6f6e0 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -23,8 +23,9 @@ let s:cpo_save = &cpo
 set cpo-=C
 
 if &filetype == "man"
-  " allow dot and dash in manual page name.
-  setlocal iskeyword+=\.,-
+  " Allow hyphen, plus, colon, dot, and commercial at in manual page name.
+  " Allow parentheses for references.
+  setlocal iskeyword=48-57,_,a-z,A-Z,-,+,:,.,@-@,(,)
   let b:undo_ftplugin = "setlocal iskeyword<"
 
   " Add mappings, unless the user didn't want this.
diff --git a/runtime/plugin/manpager.vim b/runtime/plugin/manpager.vim
index 24338ca8a..4fd709246 100644
--- a/runtime/plugin/manpager.vim
+++ b/runtime/plugin/manpager.vim
@@ -18,9 +18,6 @@ function s:ManPager()
   " Make this an unlisted, readonly scratch buffer
   setlocal buftype=nofile noswapfile bufhidden=hide nobuflisted readonly
 
-  " Is this useful?  Should allow for using K on word with a colon.
-  setlocal iskeyword+=:
-
   " Ensure text width matches window width
   setlocal foldcolumn& nofoldenable nonumber norelativenumber
 
@@ -44,6 +41,6 @@ function s:ManPager()
   setlocal nomodified nomodifiable
 
   " Set filetype to man even if ftplugin is disabled
-  setlocal iskeyword+=: filetype=man
+  setlocal filetype=man
   runtime ftplugin/man.vim
 endfunction

@FueLee
Copy link
Author

FueLee commented Sep 30, 2022

Thanks for the detailed answer, I'll apply it locally!

I was playing with colon case a bit. I could not find a man page that was using single colon, but please have a look on this (or any other from 1068 on your machine):
man XML::Parser -> XML::Parser - A perl module for parsing XML documents (3pm)

This man page references in the description section the XML::Parser::Expat. The iskeyword already contains a colon and the Shift+k on the XML::Parser::Expat jumps to the correct man page! One minor remark is that the keyword is not highlighted. Ok, in the source of man page there is no RB/BR command/tag (or something like this, I do not know much about groff,troff) but would it be possible to do it via ...syntax/man.vim?

@brammool
Copy link
Contributor

I can include the patch. I wonder if Enno Nagel is seeing this.

@lacygoill
Copy link

One minor remark is that the keyword is not highlighted. Ok, in the source of man page there is no RB/BR command/tag (or something like this, I do not know much about groff,troff) but would it be possible to do it via ...syntax/man.vim?

If the groff/troff source code does not contain any macro to add control characters inside the man page, then there's not much Vim can do. Here, I don't see macros surrounding XML::Parse::Expat in the DESCRIPTION section. This is what I have in /usr/share/man/man3/XML::Parser.3pm.gz:

.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This module provides ways to parse \s-1XML\s0 documents. It is built on top of
XML::Parser::Expat, which is a lower level interface to James Clark's
expat library. Each call to one of the parsing methods creates a new
instance of XML::Parser::Expat which is then used to parse the document.
Expat options may be provided when the XML::Parser object is created.
These options are then passed on to the Expat object on each parse call.
They can also be given as extra arguments to the parse methods, in which
case they override options given at XML::Parser creation time.
.PP
The behavior of the parser is controlled either by \f(CW"STYLES"\fR and/or
\&\f(CW"HANDLERS"\fR options, or by \*(L"setHandlers\*(R" method. These all provide
mechanisms for XML::Parser to set the handlers needed by XML::Parser::Expat.
If neither \f(CW\*(C`Style\*(C'\fR nor \f(CW\*(C`Handlers\*(C'\fR are specified, then parsing just
checks the document for being well-formed.
.PP
When underlying handlers get called, they receive as their first parameter
the \fIExpat\fR object, not the Parser object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants