Closed mcepl closed 4 years ago
can't reproduce on ubuntu, but I don't have mandoc
installed. cc @bobrippling
I'm afraid I'm also unable to reproduce. Is there anything about your environment that's mandoc-specific? And are you able to reproduce this bug on commit 53b025887e28888f8dba78ff57afc001d1a6428b or prior, by any chance? I'm wondering if the change is the 'tagfunc'
work or whether it's the code that parses man output and wrangles paths.
Guessing this is related to https://github.com/neovim/neovim/issues/9631#issuecomment-465660416
Though in this report :Man
is being used instead of invoking as MANPAGER.
mandoc
is buggy. Not going to spend time on this. Send a PR if you find a fix.
@justinmk @bobrippling Would it help anything if I told that I cannot reproduce this bug when I reverse commit c6afad7 on autoload/man.vim
? autoload/man.vim is the edited version I have.
neovim-mandoc-log.txt is the output of -V20
when running just :Man SSL_read
with the original autoload/man.vim
from 14a8b3b98. What seem interesting to me that the last function calling any external command (s:verify_exists
) seems to exit correctly and it seems to return exactly the same list as when running with man-db
man (i.e., ['3ssl', 'SSL_peek', '/usr/share/man/man3/SSL_peek.3ssl.gz']
).
Mandoc maintainer speaking here. To help investigation, i have (locally, on my machine, of course not globally for all OpenBSD users) updated the OpenBSD neovim port to v0.5.0-350-g14a8b3b98 and run it under ktrace(1) -i, then typed ":Man bash". This stands out in the ktrace shortly before nvim gives up:
91859 nvim CALL execve(0x1b92dfb83580,0x1b9273f356c0,0x1b928d47b400)
91859 nvim NAMI "/usr/bin/man"
91859 nvim ARGS
[0] = "/usr/bin/man"
[1] = "-w"
91859 man NAMI "/usr/libexec/ld.so"
So it appears something calls "man -w" without any further argument, which agrees with this part from mcepl's neovim-mandoc-log.txt:
man.vim: command error (6)
man -w: usage: man [-acfhklw] [-C file] [-M path] [-m path] [-S subsection]
[[-s] section] name ...
Indeed the "name" on the man(1) command line is not optional, so it seems correct to me that "man -w" fails. The question is why that command gets executed...
Well, considering which implementation of man(1)
is the correct one is above my pay-grade, but it is true, that man-db man has an undocumented behaviour when running man -w
:
~@milic$ man -w
/usr/share/man:/home/matej/.local/share/man
~@milic$
It apparently prints list of directories where manpages are located. I don’t know if there is more official standard for man(1)
behaviour, so I cannot say whether neovim has right to rely on such.
Interesting. I can confirm this man -w
behaviour and I think man.vim
shouldn't be relying on it.
This does mean we'd have to hardcode the man-path as something like /usr/share/man:/usr/local/man:/usr/local/share/man:~/.local/share/man
, since we can't get it from man
any more.
We'd then have to remove s:find_arg
and replace it with code that would a) assume the man-path and b) manually search for the man pages themselves under said man path. We'd also need to handle man
on SunOS 5, going off the code here.
Unfortunately I'm short on time at the moment but may be able to resume this later down the line.
This does mean we'd have to hardcode the man-path as something like /usr/share/man:/usr/local/man:/usr/local/share/man:~/.local/share/man, since we can't get it from man any more.
@ischwarze know of an alternative way to get this info ?
We'd then have to remove
s:find_arg
and replace it with code that would a) assume the man-path and b) manually search for the man pages themselves under said man path. We'd also need to handleman
on SunOS 5, going off the code here.
Or at least when the call to man -w
fails, then we should default to something (and yes, we should check the content of the environment variable $MANPATH
as well, I guess).
@bobrippling @justinmk Why do you need the manpath at all, what do you want to do with it? (Sorry for not finding the file man.vim particularly readable.) When application programs manually inspect the manpath, that smells like a design error to me.
Manually searching for manual pages in the manpath is certainly a terrible idea. At least the following aspects differ among operating systems:
You are supposed to use the man(1) program to locate and format manual pages on any given operating system. That program will know all the above specifics for its own platform. You can capture the output from commands like "man nvim" and display that inside the editor, but i doubt the wisdom of trying to second-guess the man(1) program itself.
Sure, the user interface of man(1) differs considerably among operating systems (for example, commercial Solaris man(1) does not have any -w option at all, and -l means something totally different there compared to man-db and mandoc; or with mandoc, -w implies -a while with man-db, it does not, and so on) - but the man(1) user interface still doesn't vary nearly as much as the internal organization of manual page directories.
It hardly looks reasonable (nor even feasible) to me to try and re-implement all that inside a mere text editor, for each and every operating system on the planet... :-( Getting all of that right isn't simple even for one single system, and for most systems, the rules keep evolving over time.
All that said, i'm not necessarily totally opposed to making "man -w" without arguments in mandoc compatible with the behaviour of man-db, it might be feasible and acceptable, but i'd still prefer to also understand what your goal is when using it.
You are supposed to use the man(1) program to locate and format manual pages on any given operating system. That program will know all the above specifics for its own platform.
Agreed - I suppose the question is why neovim displays man pages like this, which is primarily to do with disabling shelling out to a subcommand (I imagine).
I think we have two options here, since the existing man.vim
logic seems too tied to a specific man
implementation.
man
itself rather that performing the lookup as we currently do, then parse the output of man and format it into a buffer.
man
in a terminal buffer and allow man
to take care of everything.
I'm afraid I only added tagfunc
support to man.vim
, I'm not really clued up on how the rest of it works. @nhooyr - are you the current maintainer?
I am the current maintainer, I'll look at this over the weekend.
The reason we need the list of paths is for completion.
The problem is tagfunc calling this function, it should only be completion.
I didn't review any of those PRs so I don't know how/why but it looks like it's getting called in #open_page which is causing the error to be thrown. That's why @mcepl cannot reproduce before https://github.com/neovim/neovim/commit/c6afad78d39aa77a4d372759336018ef6e101dab
Can we remove the call to s:get_paths in https://github.com/neovim/neovim/blob/31614d3eb0b6e563eab9a76acf6e33c725b92e60/runtime/autoload/man.vim#L387-L413 @bobrippling?
Can we remove the call to s:get_paths in
Is this the reason why I cannot even follow man hyperlink in the displayed manpage (e.g., SEE ALSO section in most manpages)?
man.vim: command error (9) man -w: usage: man [-acfhklw] [-C file] [-M path] [-m path] [-S su
bsection]
[[-s] section] name ...
Chyba při zpracování function man#goto_tag:
řádek 6:
E714: List required
Press ENTER or type command to continue
I don’t understand why Man.vim needs for following vi(1)
anything else than call man -c 1 vi
.
Hi,
so i'm now supporting bare "man -w" in the HEAD version of mandoc, and it will be in the next mandoc release:
https://cvsweb.bsd.lv/mandoc/main.c#rev1.343
https://cvsweb.bsd.lv/mandoc/man.1.diff?r1=1.36&r2=1.37
Even though it is then supported by man-1.6, man-db, and mandoc (i.e. essentially Linux and OpenBSD), many operating systems still don't support it, in particular not FreeBSD (using its own man implementation written in sh(1)), NetBSD (still using traditional BSD CSRG man), DragonFly BSD (using FreeBSD man), Minix (using NetBSD man), Illumos (using modified CSRG/NetBSD man), Oracle Solaris, and i have serious doubts about commercial systems like AIX, HP-UX, and MacOS.
If you want to use it for autocompletion, you should probably make sure that you have some fallback or just disable autocompletion when it doesn't work, rather than becoming unable to view manual pages at all.
Regarding tagging, the mandoc implementation of man(1) already has tagging support built in and uses markup in the mdoc(7) and man(7) source code to set reasonable tags. That's almost certainly better tagging than whatever you might be able to guess from the formatted manual page. Then again, man-1.6, man-db, FreeBSD man, NetBSD man and so on can't do this because they format the page first (typically with groff, or some with mandoc), and then, when they come to the point where they might decide about tags, the source information has already been lost.
By the way, the mandoc implementation also supports automatic generation of a table of contents (-O toc), but only in -T html output mode. It isn't enabled by default because some OpenBSD developers dislike it. We do not support it for terminal output because generating hyperlinks wouldn't work there, so it wouldn't really be useful. But with mandoc installed and enabled as man(1), try something like:
MANPAGER="lynx -force_html" man -T html -O toc pf.conf
then move the cursor to one of the lines in the table of contents and hit the "ENTER" key. Not sure how you could leverage that in neovim, though. Using man(1) directly will inevitably be much more powerful than calling it from inside nvim(1), i guess.
The problem is tagfunc calling this function, it should only be completion. [...] it looks like it's getting called in #open_page which is causing the error to be thrown. That's why @mcepl cannot reproduce before c6afad7
Thanks for looking into this @nhooyr - I think the best approach in this case is for the tag completion just to work with what it's given, instead of trying to guess at further man page paths then. Essentially the solution we use for when 'cscopetag'
is enabled, with a little less magic.
I think as part of this fix, I'll also add error handling so we don't entirely bail out if man -w
gives us back an error.
Is this the reason why I cannot even follow man hyperlink in the displayed manpage
Most likely, yes.
so i'm now supporting bare "man -w" in the HEAD version of mandoc
Thanks for your work and the potential autocompletion support this could provide. The tagging support could also be useful, however for now I'm going to revert man.vim
back to a more basic state, and then we'll see what feedback we get on how useful it would be to have such extra functionality.
Ok sounds good, feel free to tag me for review in the PR.
I think the best approach in this case is for the tag completion just to work with what it's given,
what's wrong with a "best effort" attempt? Certainly we shouldn't fail if man -w
doesn't give us what we want, but if we can also discover more options for autocomplete, that's strictly a good thing.
Just to give you an idea how different things are: On systems using the mandoc implementation of man(1), you would only find a fraction of the possible manual page names that could be used for autocompletion by looking through the file system. The full set of names and the name-to-file mapping is only contained in https://man.openbsd.org/mandoc.db files. On such a system, you could find the full list of names starting with "nv" with this command:
$ man -k Nm~^nv | sed 's/ -.*//'
nvim(1)
vlc, cvlc, nvlc, qvlc, rvlc, svlc(1)
gre, egre, mgre, nvgre(4)
nv(4)
nviic(4)
nvme(4)
nvram(4/amd64)
nvram(4/i386)
nvt(4)
While that is of course much more efficient than iterating the file system, it won't work at all with the man-db or man-1.6 implementations of man(1).
I don't think supporting that should be anywhere near the top of your list of priorities, but it might be instructive to see that not all man(1) programs have the same features.
@ischwarze thanks, that's helpful. Certainly we can implement more strategies to discover manpages. The feature is inherently a "best effort" attempt.
so i'm now supporting bare "man -w" in the HEAD version of mandoc, and it will be in the next mandoc release:
https://cvsweb.bsd.lv/mandoc/main.c#rev1.343 https://cvsweb.bsd.lv/mandoc/man.1.diff?r1=1.36&r2=1.37
@ischwarze When do you plan to do next release of mandoc? It is really difficult dissect just this one patch (git-deps shows me approx 60 commits dependent on this one).
what's wrong with a "best effort" attempt?
I was mainly concerned about introducing more bugs, with all the different man
implementations out there. I suppose we can fallback to the more basic approach on errors though
I was mainly concerned about introducing more bugs, with all the different
man
implementations out there. I suppose we can fallback to the more basic approach on errors though
sure, I just mean we should not remove the current behavior. If the -w
hack works then let's continue to use it, if it actually improves the completion results.
let's continue to use it, if it actually improves the completion results
Yeah, sounds like a good approach. I believe I have a fix in #11918, I've been testing by manually throwing an exception in place of s:system(["man", ...])
, but would appreciate if you'd mind trying out my fix @mcepl, and @nhooyr feel free to let me know what you think of the changes.
And thanks everyone for the above discussion, I feel it was productive in determining the correct fix to make.
:smiley:
Yeah, sounds like a good approach. I believe I have a fix in #11918, I've been testing by manually throwing an exception in place of
s:system(["man", ...])
, but would appreciate if you'd mind trying out my fix @mcepl, and @nhooyr feel free to let me know what you think of the changes.
Seems to work for me, even with man
before the change mentioned above I have now working :Man
command again.
nvim --version
: own build from 01ff9db63 on openSUSE/Tumbleweedvim -u DEFAULTS
(version: ) behaves differently? yes, that works correctly (vim-8.2.0119-1.1.x86_64)$TERM
: xterm-256colorSteps to reproduce using
nvim -u NORC
Start
LANG=en_GB nvim -u NORC
run
:Man bash
Actual behaviour
Error message:
Expected behaviour
Displayed man page of
bash(1)