wilfred / helpful Goto Github PK
View Code? Open in Web Editor NEWA better Emacs *help* buffer
A better Emacs *help* buffer
I have essentially two problems with Helpful:
Every time I check a definition using it, Helpful create some persistent buffers (at least 2), one for the searched function source file and one for the Helpful buffer itself.
I think Helpful should use with-temp-buffer
instead of find-file
to visit the references (I found this article referencing this trade-off: http://ergoemacs.org/emacs/elisp_find-file_vs_with-temp-buffer.html), this way it wouldn't create a persistent buffer for the source file, and it would be faster.
I can't configure Helpful to play nice with Shackle.
This point probably spills over the first one (and that is why I didn't open two issues). Helpful is using switch-to-buffer
to show its content. Unfortunately, this function does not use the display-buffer-alist
and is harder to manage the window/buffers it creates. Also, if Helpful would use a function like display-buffer
instead, it would create a persistent buffer for itself.
The helpful-variable function should show the name of the variable it's describing.
the old describe-variable
function has this You can customize this variable.
part, if the variable is declared with defcustom
with a link to the customization buffer.
It would be nice to have something similar in helpful-variable
.
One suggestion for this (just my personal preference) is to make the value editable inside the helpful-buffer, a bit like wdired
or wgrep
.
Thanks for this great package.
I've grown very used to this in the regular help buffers.
Hi Wilfred,
great package and currently I am exploring the different functions helpful provide.
As an Emacs newbie myself it's sometimes hard to look at the source to discover the functionality of a package. So it would be nice to get some info about that in the README.
Especially stuff like how the different helpful functions could replace the builtins and how to do so in my emacs config file.
See cl-loop
for an example.
When using borg-queen, and binding C-h k
to helpful-key
, C-h k t
takes all my CPU and doesn't produce anything until I kill it with C-g
. M-x describe-key RET t
produces
Symbol’s function definition is void: borg-queen-mark-for-checkout-tag
which is correct as t
is bound to an unknown command.
The value of the variable shown is taken too late after it has potentially already been changed by helpful.
The easiest way for me to explain this is with an example: using describe-variable
on major-mode
shows the major mode for the buffer, e.g. lisp-interaction-mode
while using helpful-variable
shows helpful-mode
.
This isn't a valid code snippet. See eval-defun for an example:
If acting on a `defun' for FUNCTION, and the function was
instrumented, `Edebug: FUNCTION' is printed in the echo area. If not
instrumented, just FUNCTION is printed.
How about an more "helpful" implementation of apropos?
helpful-function
sometimes overwrites buffers with strange output. This seems to happen for functions that are newly-defined.
GNU Emacs 25.2.1 (x86_64-apple-darwin13.4.0, NS appkit-1265.21 Version 10.9.5 (Build 13F1911)) of 2017-04-21
helpful: 20171116.1425
Start Emacs with emacs -Q
and load helpful
(in the process of doing this, I also load use-package
).
Open a file called ~/bug-in-helpful.el
. Define and evaluate the following function:
(defun bug-in-helpful ()
"a bug in helpful.el"
5)
Save the file. The screen should look like this:
M-x helpful-function RET bug-in-helpful
. For me, this causes a new window to open with the same buffer (bug-in-helpful.el
). In the buffer (and hence in both windows), the text has been replaced with helpful-function
output which is missing most information (it only has the source code, and that is in the form of a lambda).Note that the buffer has been marked as having been changed.
C-h f bug-in-helpful
. This displays without any problems:help
window and repeat step 3. The strange behavior still occurs.Ideally it should automatically be autloaded.
When I do a lookup on certain functions I consistently get this error.
One example is org-edit-special
:
Debugger entered--Lisp error: (args-out-of-range 0 10)
replace-match(#("ffap" 0 4 (button (t) category helpful-describe-button-button symbol ffap)) t t "`ffap'" nil)
replace-regexp-in-string("`\\_<\\(?:.\\|\n\\)+?\\_>'" #f(compiled-function (it) #<bytecode 0x1fdcbab>) "Call a special editor for the element at point.\n\nWhen at a table, call the formula editor with `org-table-edit-formulas'.\nWhen in a source code block, call `org-edit-src-code'.\nWhen in a fixed-width region, call `org-edit-fixed-width-region'.\nWhen in an export block, call `org-edit-export-block'.\nWhen at an #+INCLUDE keyword, visit the included file.\nWhen at a footnote reference, call `org-edit-footnote-reference'\nOn a link, call `ffap' to visit the link at point.\nOtherwise, return a user error." t t)
helpful--format-docstring("Call a special editor for the element at point.\nWhen at a table, call the formula editor with `org-table-edit-formulas'.\nWhen in a source code block, call `org-edit-src-code'.\nWhen in a fixed-width region, call `org-edit-fixed-width-region'.\nWhen in an export block, call `org-edit-export-block'.\nWhen at an #+INCLUDE keyword, visit the included file.\nWhen at a footnote reference, call `org-edit-footnote-reference'\nOn a link, call `ffap' to visit the link at point.\nOtherwise, return a user error.")
helpful-update()
helpful-function(org-edit-special)
funcall-interactively(helpful-function org-edit-special)
call-interactively(helpful-function nil nil)
command-execute(helpful-function)
Could it be related to some function being byte-compiled? Or is this some obvious error?
Well this package seems nice.
Seeing as it is for Emacs Lisp reference, are you planning to put it into the GNU ELPA archive?
(originally at https://www.reddit.com/r/emacs/comments/6x2pnx/helpful_adding_contextual_help_to_emacs/dmddom3/ )
I'm not sure if this is a bug or just something that's impossible to do, but there's no location info on my-foo
when you do emacs -Q
and eval-buffer
on the below file:
(package-initialize)
(use-package counsel
:defer t
:config
(defun my-foo (x)
(with-ivy-window
(insert x))))
(require 'counsel)
(require 'helpful)
(helpful-function 'my-foo)
But if you do C-M-x on the defun, you will get location info.
Also, if you eval-buffer
twice, you'll also get location info. So presumably it's the eval-after-load
that doesn't bother with carrying around location, which makes sense.
Weird thing: If I remove the :defer t
, I don't get location info from helpful, but when I afterwards try plain C-h f, it shows the location, and then doing helpful-function after that shows the location.
Rather than make the user inject things into their config, add autoload tags to the interactive functions so it'll load as soon as the user tries to use it (and the commands will tab complete too).
For example, from paredit-backward-slurp-sexp
:
Key Bindings
paredit-mode-map <C-M-left>
paredit-mode-map C-(
paredit-mode-map ESC <C-left>
The third keybinding here is redundant.
See find-file
for an example.
For example for variables defined in C (e.g. helpful-function is failing currently for auto-fill-function
variable).
backward-up-list
isn't smart enough to see that an opening parenthesis is inside comments. That causes helpful-function' to fail for functions like
org-macro--collect-macros' as the source file contains comments with open parenthesis in them.
I am not sure how we can make sure that we stop moving up when we have reached the top-level as we cannot assume that a definition should always start at the zeroth column
Try to call helpful-variable
for variable system-type
.
It'll crash with the following error:
Debugger entered--Lisp error: (wrong-type-argument stringp C-source)
string-match("\\`src/\\(.*\\.\\(c\\|m\\)\\)\\'" C-source)
#f(compiled-function (symbol type library) "Search for SYMBOL's definition of type TYPE in LIBRARY.\nVisit the library in a buffer, and return a cons cell (BUFFER . POSITION),\nor just (BUFFER . nil) if the definition can't be found in the file.\n\nIf TYPE is nil, look for a function definition.\nOtherwise, TYPE specifies the kind of definition,\nand it is interpreted via `find-function-regexp-alist'.\nThe search is done in the source for library LIBRARY." #<bytecode>)(system-type defvar C-source)
ad-Advice-find-function-search-for-symbol(#f(compiled-function (symbol type library) "Search for SYMBOL's definition of type TYPE in LIBRARY.\nVisit the library in a buffer, and return a cons cell (BUFFER . POSITION),\nor just (BUFFER . nil) if the definition can't be found in the file.\n\nIf TYPE is nil, look for a function definition.\nOtherwise, TYPE specifies the kind of definition,\nand it is interpreted via `find-function-regexp-alist'.\nThe search is done in the source for library LIBRARY." #<bytecode>) system-type defvar C-source)
apply(ad-Advice-find-function-search-for-symbol #f(compiled-function (symbol type library) "Search for SYMBOL's definition of type TYPE in LIBRARY.\nVisit the library in a buffer, and return a cons cell (BUFFER . POSITION),\nor just (BUFFER . nil) if the definition can't be found in the file.\n\nIf TYPE is nil, look for a function definition.\nOtherwise, TYPE specifies the kind of definition,\nand it is interpreted via `find-function-regexp-alist'.\nThe search is done in the source for library LIBRARY." #<bytecode>) (system-type defvar C-source))
find-function-search-for-symbol(system-type defvar C-source)
find-variable-noselect(system-type C-source)
helpful--definition(system-type nil)
helpful--source(system-type nil)
helpful-update()
helpful-variable(system-type)
funcall-interactively(helpful-variable system-type)
call-interactively(helpful-variable)
hydra--call-interactively-remap-maybe(helpful-variable)
(progn (setq this-command 'helpful-variable) (hydra--call-interactively-remap-maybe (function helpful-variable)))
hydra-describe/helpful-variable-and-exit()
funcall-interactively(hydra-describe/helpful-variable-and-exit)
call-interactively(hydra-describe/helpful-variable-and-exit nil nil)
command-execute(hydra-describe/helpful-variable-and-exit)
When looking up variable information using describe-variable
, both the current, and original assigned values are shown.
When using helpful-variable
, only the current variable is shown.
I think helpful should follow the behavior in describe-variable
and show both past and present values.
Currently, the helpful help function cause the whole window to be occupied by the helpful-mode buffer which isn't the case with original help functions.
When using helpful-function
the buffer does not show that the function is an alias of another one. For example M-x helpful-function RET yes-or-no-p RET
does not say that it is an alias of y-or-n-p
. I only saw a message in the echo area.
Allow jumping to various sections in helpful buffers using imenu.
Using helpful-function
on an autoloaded function results in the following error:
helpful--format-argument: Wrong type argument: symbolp, 91
Helpful looks very nice.
I've noticed a problem. In the screenshots and in the description it states that: We solve the text-quoting-style debate by removing superfluous puncuation entirely.
But I see it is still there when I invoke it. If via M-x helpful-command
+ query-replace-regexp
, you look at one example paragraph:
If ‘replace-regexp-lax-whitespace’ is non-nil, a space or spaces in the regexp
to be replaced will match a sequence of whitespace chars defined by the
regexp in ‘search-whitespace-regexp’.
Was this expected to be highlighted and not quoted?
The 3 functions behave differently:
helpful-function
shows many function containing the string "use-package" but not the macro itselfhelpful-macro
only shows the use-package
macrohelpful-command
shows only use-package-install-deferred-package
and use-package-jump-to-package-form
Unless I'm missing something, the variable value is not currently shown.
Please add a function that replaces describe-key
and shows helpful-function
for the pressed key.
Using spacemacs, a self-compiled emacs26 and helpful 20170829.1620.
Stacktrace:
Debugger entered--Lisp error: (error "Unexpected error whilst reading ~/Documents/git/emacs/src/data.c position 809: (invalid-read-syntax #)")
signal(error ("Unexpected error whilst reading ~/Documents/git/emacs/src/data.c position 809: (invalid-read-syntax #)"))
error("Unexpected error whilst reading %s position %s: %s" "~/Documents/git/emacs/src/data.c" 809 (invalid-read-syntax "#"))
elisp-refs--read-all-buffer-forms(#<buffer *refs-/home/a/Documents/git/emacs/src/data.c*-456857>)
elisp-refs--read-and-find(#<buffer *refs-/home/a/Documents/git/emacs/src/data.c*-456857> not elisp-refs--function-p)
#f(compiled-function (buf) #<bytecode>)(#<buffer *refs-/home/a/Documents/git/emacs/src/data.c*-456857>)
elisp-refs--search-1((#<buffer *refs-/home/a/Documents/git/emacs/src/data.c*-456857>) #f(compiled-function (buf) #<bytecode>))
helpful--reference-positions(not t #<buffer *refs-/home/a/Documents/git/emacs/src/data.c*-456857>)
helpful-update()
helpful-at-point()
funcall-interactively(helpful-at-point)
call-interactively(helpful-at-point nil nil)
command-execute(helpful-at-point)
E.g. see eval-defun.
Currently, we just say 'is advised'. See eval-defun
for an example.
This allows multiple buffers to coexist, and it's clearer. It's currently only mentioned at the top of the buffer.
*helpful macro: defun*
would be another possibility.
Followup to #28. @Townk @Wilfred @dakra.
I can still reproduce the issue with M-x helpful-variable RET shell-file-name
.
emacs-26
branchfind-function-C-source-directory
is properly setM-x describe-variable RET shell-file-name
works fine and I can click on the "C source code" linkmaster
branchCurrently the buffer is created and only afterwards helpful-mode
is activated. This makes it impossible to use popwin with helpful.
Hello,
helpful version 0.1 (current release) uses not defined function elisp-refs--search-1
from elisp-refs version 1.1 (current release).
Would it be possible to provide a command that could be used instead of C-h f
(describe-function
)? The command would show a list of all functions in the system with a default for the function at point.
See flycheck-mode
for an example.
For example, position-bytes
has more information in the manual than in its docstring. The manual mentions that it's one-indexed.
It would be an improvement if the links generated by "All references" jumped to the line of code where the reference is, something like how grep would behave. In fact, I'd like the interface to behave something like emacs's grep, where there are keybindings that allow you to quickly hop between all the calling instances.
The default describe-function
lists macros, so in order to replace it with helpful-function
it should also list them.
When I type M-x helpful-function RET shell-quote-argument
, I don't get the documentation of the function, except through it's source code. Is that expected? I would like a properly formatted documentation of each function so I can use helpful-function as a drop-in replacement for C-h f
.
This is an Emacs convention for avoiding hyperlinks: https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html
We could maybe fontify it though.
See -map-indexed
in the most recent dash.el as an example.
M-: (helpful-variable 'magit-branch-popup)
Debugger entered--Lisp error: (scan-error "Containing expression ends prematurely" 2 2)
scan-sexps(4 -1)
forward-sexp(-1)
calculate-lisp-indent((1 2 13 nil nil nil 0 nil nil (2) nil))
lisp-indent-line()
cl--do-prettyprint()
cl-prettyprint((:variable magit-branch-arguments :man-page "git-branch" :variables #f(compiled-function () #<bytecode 0x1b1dbe1>) :actions ((98 "Checkout" magit-branch-or-checkout) nil (67 "Configure..." magit-branch-config-popup) (108 "Checkout local branch" magit-branch-checkout) (115 "Create new spin-off" magit-branch-spinoff) (109 "Rename" magit-branch-rename) (99 "Checkout new branch" magit-branch-and-checkout) (110 "Create new branch" magit-branch) (120 "Reset" magit-branch-reset) (119 "Checkout new worktree" magit-worktree-checkout) (87 "Create new worktree" magit-worktree-branch) (107 "Delete" magit-branch-delete) (106 "Create branch from jira" magit-create-branch-from-jira-issue)) :default-action magit-checkout :max-action-columns 3 :setup-function magit-branch-popup-setup))
helpful--pretty-print((:variable magit-branch-arguments :man-page "git-branch" :variables #f(compiled-function () #<bytecode 0x1b1dbe1>) :actions ((98 "Checkout" magit-branch-or-checkout) nil (67 "Configure..." magit-branch-config-popup) (108 "Checkout local branch" magit-branch-checkout) (115 "Create new spin-off" magit-branch-spinoff) (109 "Rename" magit-branch-rename) (99 "Checkout new branch" magit-branch-and-checkout) (110 "Create new branch" magit-branch) (120 "Reset" magit-branch-reset) (119 "Checkout new worktree" magit-worktree-checkout) (87 "Create new worktree" magit-worktree-branch) (107 "Delete" magit-branch-delete) (106 "Create branch from jira" magit-create-branch-from-jira-issue)) :default-action magit-checkout :max-action-columns 3 :setup-function magit-branch-popup-setup))
helpful-update()
helpful-variable(magit-branch-popup)
eval((helpful-variable 'magit-branch-popup) nil)
eval-expression((helpful-variable 'magit-branch-popup) nil nil 127)
funcall-interactively(eval-expression (helpful-variable 'magit-branch-popup) nil nil 127)
call-interactively(eval-expression nil nil)
command-execute(eval-expression)
C-h S
(info-lookup-symbol
) is for searching Info manual base on the Major mode, for helpful-mode
, since it's related to Emacs, C-h S
should search Emacs-related info manuals, like help-mode
.
Not sure about the correct way, but I found the following works for me.
(info-lookup-maybe-add-help
:mode 'helpful-mode
:regexp "[^][()`'‘’,:\" \t\n]+"
:other-modes '(emacs-lisp-mode))
(info-lookup-maybe-add-help
:mode 'elisp-refs-mode
:regexp "[^][()`'‘’,:\" \t\n]+"
:other-modes '(emacs-lisp-mode))
changed from (in the end of info-look.el
)
(info-lookup-maybe-add-help
:mode 'help-mode
:regexp "[^][()`'‘’,:\" \t\n]+"
:other-modes '(emacs-lisp-mode))
Currently when I use find-function
, the default parameter is the current function under the point. This way I can call find-function
and immediately press RET
to describe the function under the point.
I think helpful
should also assume the default to be the current word under the point ( but obviously let the user type a different argument if the wish ).
Also, thanks for the awsome pacakge. I'm very excited to hopefully fix the few remaining issues so that I can start using this package full time.
See, for example, cl-defstruct
.
There's currently no imenu support. Below is an option, but relies on identifying headings by checking face and case. Not ideal, but does the job?
(defun helpful--create-imenu-index ()
"Create an `imenu' index for helpful."
(beginning-of-buffer)
(let ((imenu-items '()))
(while (progn
(beginning-of-line)
;; Not great, but determine if looking at heading:
;; 1. if it has bold face.
;; 2. if it is capitalized.
(when (and (eq 'bold (face-at-point))
(string-match-p
"[A-Z]"
(buffer-substring (line-beginning-position)
(line-end-position))))
(add-to-list 'imenu-items
(cons (buffer-substring (line-beginning-position)
(line-end-position))
(line-beginning-position))))
(= 0 (forward-line 1))))
imenu-items))
(defun helpful-mode-hook-function ()
"A hook function for `helpful-mode'."
(setq imenu-create-index-function #'helpful--create-imenu-index))
(add-hook 'helpful-mode-hook
#'helpful-mode-hook-function)
Calling (org-store-link) in a normal buffer stores the link to the help buffer.
Would be nice if helpful would support this too.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.