From 632a069eed54f3912c799b5497ece78d4e8a42d0 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Tue, 23 Nov 2010 01:58:33 +0100 Subject: Document browser improvements, and Racket using them We have a new "manual lookup" command, and Racket now displays a doc browser buffer for help with a button activating it. In the process, we've cleaned-up a little mess in geiser-eval.el and geiser-doc.el, and refactored the affected Racket modules. Next in line is providing manual lookup for Guile. --- doc/cheat.texi | 3 + doc/img/geiser-mode.png | Bin 62445 -> 37636 bytes doc/img/repl-mod.png | Bin 29938 -> 30503 bytes doc/parens.texi | 33 ++++++--- doc/repl.texi | 40 +++++------ elisp/geiser-completion.el | 11 +-- elisp/geiser-doc.el | 168 ++++++++++++++++++++++++++------------------- elisp/geiser-eval.el | 20 +++--- elisp/geiser-mode.el | 2 + 9 files changed, 166 insertions(+), 111 deletions(-) diff --git a/doc/cheat.texi b/doc/cheat.texi index 108d5a2..f6e1924 100644 --- a/doc/cheat.texi +++ b/doc/cheat.texi @@ -137,6 +137,9 @@ @item C-c C-d C-d @tab geiser-doc-symbol-at-point @tab See documentation for symbol at point +@item C-c C-d C-i +@tab geiser-doc-lookup-manual +@tab Lookup manual for symbol at point @item C-c C-d C-m @tab geiser-repl--doc-module @tab See documentation for module diff --git a/doc/img/geiser-mode.png b/doc/img/geiser-mode.png index 6e6e564..799745c 100644 Binary files a/doc/img/geiser-mode.png and b/doc/img/geiser-mode.png differ diff --git a/doc/img/repl-mod.png b/doc/img/repl-mod.png index 9814b7e..1fee5f0 100644 Binary files a/doc/img/repl-mod.png and b/doc/img/repl-mod.png differ diff --git a/doc/parens.texi b/doc/parens.texi index 439e56c..c4aa228 100644 --- a/doc/parens.texi +++ b/doc/parens.texi @@ -278,10 +278,10 @@ controls how the current argument position is highlighted. @subsubheading Other documentation commands -Sometimes, autodoc won't provide enough information for you to -understand what a function does. In those cases, you can ask Geiser to -ask the running Scheme for further information on a given identifier or -module. +@anchor{doc-browser}Sometimes, autodoc won't provide enough information +for you to understand what a function does. In those cases, you can ask +Geiser to ask the running Scheme for further information on a given +identifier or module. @cindex documentation for symbol @cindex docstrings, maybe @@ -301,14 +301,29 @@ navigation commands available in that buffer, which you can discover by means of its menu or via the good old @kbd{C-h m} command. For Racket, which does not support docstrings out of the box, this -command will invoke Racket's @code{help} procedure, thereby opening your -configured web browser with the corresponding manual page for you to -peruse. +command will provide less information, but the documentation browser +will display the corresponding contract when it's available. You can also ask Geiser to display information about a module, in the form of a list of its exported identifiers, using @kbd{C-c C-d C-m}, -exactly as you would do @ref{repl-mod,,in the REPL}. This commands works -with all supported Schemes, no strings attached. +exactly as you would do @ref{repl-mod,,in the REPL}. + +In both cases, the documentation browser will show a couple of buttons +giving you access to further documentation. First, you'll see a button +named @i{source}: pressing it you'll jump to the symbol's definition. +The second button, dubbed @i{manual}, will open the scheme +implementation's manual page for the symbol at hand. For Racket, that +will open your web browser displaying the corresponding reference's page +(using Emacs' @code{browser-url} command), while in Guile a lookup will +be performed in the texinfo manual. + +@cindex opening manual pages +You can also jump directly to the manual page for the symbol at point +with the command @code{geiser-doc-lookup-manual}, bound to @kbd{C-c C-d +i}. + +See also our @xref{Documentation browser,,cheat-sheet} for a list of +navigation commands available in the documentation browser. @node To eval or not to eval, To err perchance to debug, Documentation helpers, Between the parens @section To eval or not to eval diff --git a/doc/repl.texi b/doc/repl.texi index ffb733b..a87c547 100644 --- a/doc/repl.texi +++ b/doc/repl.texi @@ -217,11 +217,26 @@ argument is a keyword argument, its name has ``#:'' as a prefix. @cindex help on identifier If that's not enough documentation for you, @kbd{C-c C-d d} will open a -separate documentation buffer with help on the symbol at point. For some -implementations (e.g. Racket), this separate buffer will actually be a -web page displaying the corresponding page in the manual, while for -implementations supporting docstrings (e.g. (you guessed it) Guile) -it'll be a real Emacs buffer displaying that information. +separate documentation buffer with help on the symbol at point. This +buffer will contain implementation-specific information about the +identifier (e.g., its docstring for Guile, or its contract, if any, for +Racket), and a handy button to open the corresponding manual entry for +the symbol, which will open an HTML page (for Racket) or the texinfo +manual (for Guile). + +@cindex module exports +@anchor{repl-mod} Geiser can also produce for you a list, classified by +kind, of the identifiers exported by a given module: all you need to do +is press @kbd{C-c C-d m}, and type or complete the desired module's +name. + +@imgc{repl-mod} + +The list of exported bindings is shown, again, in a buffer belonging to +Geiser's documentation browser, where you have at your disposal a bunch +of navigation commands listed in @xref{Documentation browser,,our +cheat-sheet}. We'll have a bit more to say about the documentation +browser in @xref{doc-browser,,a later section}. @cindex jump, at the REPL If that's still not enough, Geiser can jump, via @kbd{M-.}, to the @@ -232,21 +247,6 @@ will see, these commands are also available in scheme buffers. @kbd{M-.} also works for modules: if your point is on an unambiguous module name, the file where it's defined will be opened for you. -@cindex module exports -@anchor{repl-mod} -Finally, Geiser can produce for you a list, classified by kind, of the -identifiers exported by a given module: all you need to do is press -@kbd{C-c C-d m}, and type or complete the desired module's name. - -@imgc{repl-mod} - -The list of exported bindings is shown in a buffer belonging to Geiser's -documentation browser, of which more details are given in forthcoming -sections (but just perusing its associated key bindings, by any of the -methods we've already mentioned, will give you enough information to use -it). Racketeers will be pleased (i hope) to note that contracts are part -of the information displayed. - @node Customization and tips, , Autodoc and friends, The REPL @section Customization and tips diff --git a/elisp/geiser-completion.el b/elisp/geiser-completion.el index bf0f036..d462308 100644 --- a/elisp/geiser-completion.el +++ b/elisp/geiser-completion.el @@ -175,11 +175,12 @@ terminates a current completion." (defun geiser-completion--read-symbol (prompt &optional default history) (let ((minibuffer-local-completion-map geiser-completion--minibuffer-map)) - (completing-read prompt - geiser-completion--symbol-list-func - nil nil nil - (or history geiser-completion--symbol-history) - (or default (symbol-at-point))))) + (make-symbol (completing-read prompt + geiser-completion--symbol-list-func + nil nil nil + (or history + geiser-completion--symbol-history) + (or default (symbol-at-point)))))) (defvar geiser-completion--module-history nil) diff --git a/elisp/geiser-doc.el b/elisp/geiser-doc.el index 1606dc4..67e46dd 100644 --- a/elisp/geiser-doc.el +++ b/elisp/geiser-doc.el @@ -40,6 +40,15 @@ (geiser-custom--defface doc-button 'button geiser-doc "buttons in documentation buffers") + +;;; Implementation +(geiser-impl--define-caller geiser-doc--external-help external-help + (symbol module) + "By default, Geiser will display help about an identifier in a +help buffer, after collecting the associated signature and +docstring. You can provide an alternative function for displaying +help (e.g. browse an HTML page) implementing this method.") + ;;; Documentation browser history: @@ -108,7 +117,8 @@ (with--geiser-implementation impl (if (null target) (geiser-doc-module module impl) - (geiser-doc-symbol target module impl)))))) + (let ((geiser-eval--get-module-function (lambda (x) module))) + (geiser-doc-symbol target module impl))))))) (make-variable-buffer-local (defvar geiser-doc--buffer-link nil)) @@ -146,9 +156,13 @@ (module (geiser-doc--link-module geiser-doc--buffer-link)) (impl (geiser-doc--link-impl geiser-doc--buffer-link))) (with--geiser-implementation impl - (if (eq kind 'source) - (if target (geiser-edit-symbol target nil (point-marker)) - (geiser-edit-module module))))))) + (cond ((eq kind 'source) + (if target (geiser-edit-symbol target nil (point-marker)) + (geiser-edit-module module))) + ((eq kind 'manual) + (geiser-doc--external-help impl + (or target module) + module))))))) (define-button-type 'geiser-doc--xbutton 'action 'geiser-doc--xbutton-action @@ -160,27 +174,25 @@ :type 'geiser-doc--xbutton 'x-kind (if manual 'manual 'source))) -(defun geiser-doc--insert-xbuttons () +(defun geiser-doc--insert-xbuttons (impl) + (when (geiser-impl--method 'external-help impl) + (geiser-doc--insert-xbutton t) + (insert " ")) (geiser-doc--insert-xbutton)) -(defun geiser-doc--insert-footer () - (newline 3) - (when (geiser-doc--history-previous-p) - (insert-text-button "[back]" - 'action '(lambda (b) (geiser-doc-previous)) - 'face 'geiser-font-lock-doc-button - 'follow-link t) - (insert " ")) - (when (geiser-doc--history-next-p) - (insert-text-button "[forward]" - 'action '(lambda (b) (geiser-doc-next)) - 'face 'geiser-font-lock-doc-button - 'follow-link t))) - ;;; Auxiliary functions: -(defun geiser-doc--insert-title (title &optional top) +(defun geiser-doc--manual-available-p () + (geiser-impl--method 'external-help geiser-impl--implementation)) + +(defun geiser-doc--module (&optional mod impl) + (let* ((impl (or (geiser-doc--link-impl geiser-doc--buffer-link))) + (method (geiser-impl--method 'find-module impl)) + (mod (or mod (geiser-doc--link-module geiser-doc--buffer-link)))) + (funcall method mod))) + +(defun geiser-doc--insert-title (title) (let ((p (point))) (if (not (listp title)) (insert (format "%s" title)) @@ -189,12 +201,6 @@ (insert " " (if (eq a :rest) "." (format "%s" a)))) (insert ")")) (put-text-property p (point) 'face 'geiser-font-lock-doc-title) - (when top - (let ((len (max 1 (- (window-width) - (- (point) (line-beginning-position)) - 10)))) - (insert (make-string len ?\ )) - (geiser-doc--insert-xbuttons))) (newline))) (defun geiser-doc--insert-list (title lst module impl) @@ -213,45 +219,61 @@ (newline))) (newline))) +(defun geiser-doc--insert-footer (impl) + (newline 2) + (geiser-doc--insert-xbuttons impl) + (let* ((prev (and (geiser-doc--history-previous-p) 8)) + (nxt (and (geiser-doc--history-next-p) 10)) + (len (max 1 (- (window-width) + (- (point) (line-beginning-position)) + (or prev 0) + (or nxt 0))))) + (when (or prev nxt) + (insert (make-string len ?\ ))) + (when (geiser-doc--history-previous-p) + (insert-text-button "[back]" + 'action '(lambda (b) (geiser-doc-previous)) + 'face 'geiser-font-lock-doc-button + 'follow-link t) + (insert " ")) + (when (geiser-doc--history-next-p) + (insert-text-button "[forward]" + 'action '(lambda (b) (geiser-doc-next)) + 'face 'geiser-font-lock-doc-button + 'follow-link t)))) + ;;; Commands: -(geiser-impl--define-caller geiser-doc--external-help display-help - (symbol module) - "By default, Geiser will display help about an identifier in a -help buffer, after collecting the associated signature and -docstring. You can provide an alternative function for displaying -help (e.g. browse an HTML page) implementing this method.") - (defun geiser-doc--get-docstring (symbol module) (geiser-eval--send/result `(:eval (:ge symbol-documentation ',symbol) ,module))) (defun geiser-doc--get-module-exports (module) (geiser-eval--send/result - `(:eval (:ge module-exports '(:module ,module))))) + `(:eval (:ge module-exports '(:module ,module)) :f))) (defun geiser-doc-symbol (symbol &optional module impl) - (let ((module (or module (geiser-eval--get-module))) - (impl (or impl geiser-impl--implementation))) - (unless (geiser-doc--external-help impl symbol module) - (let ((ds (geiser-doc--get-docstring symbol module))) - (if (or (not ds) (not (listp ds))) - (message "No documentation available for '%s'" symbol) - (geiser-doc--with-buffer - (erase-buffer) - (geiser-doc--insert-title - (geiser-autodoc--str (list (symbol-name symbol) 0) - (cdr (assoc 'signature ds))) - t) - (newline) - (insert (or (cdr (assoc 'docstring ds)) "")) - (setq geiser-doc--buffer-link - (geiser-doc--history-push - (geiser-doc--make-link symbol module impl))) - (geiser-doc--insert-footer) - (goto-char (point-min))) - (geiser-doc--pop-to-buffer)))))) + (let* ((impl (or impl geiser-impl--implementation)) + (module (geiser-doc--module (or module (geiser-eval--get-module)) + impl))) + (let ((ds (geiser-doc--get-docstring symbol module))) + (if (or (not ds) (not (listp ds))) + (message "No documentation available for '%s'" symbol) + (geiser-doc--with-buffer + (erase-buffer) + (geiser-doc--insert-title + (geiser-autodoc--str (list (symbol-name symbol) 0) + (cdr (assoc 'signature ds)))) + (newline) + (insert (or (cdr (assoc 'docstring ds)) "")) + (setq geiser-doc--buffer-link + (geiser-doc--history-push (geiser-doc--make-link symbol + module + impl))) + (geiser-doc--insert-footer impl) + (goto-char (point-min))) + (geiser-doc--pop-to-buffer))))) (defun geiser-doc-symbol-at-point (&optional arg) "Get docstring for symbol at point. @@ -262,6 +284,18 @@ With prefix argument, ask for symbol (with completion)." (symbol-at-point))))) (when symbol (geiser-doc-symbol symbol)))) +(defun geiser-doc-lookup-manual (&optional arg) + "Lookup manual for symbol at point. +With prefix argument, ask for the lookup symbol (with completion)." + (interactive "P") + (unless (geiser-doc--manual-available-p) + (error "No manual available")) + (let ((symbol (or (and (not arg) (symbol-at-point)) + (geiser-completion--read-symbol "Symbol: ")))) + (geiser-doc--external-help geiser-impl--implementation + symbol + (geiser-eval--get-module)))) + (defconst geiser-doc--sections '(("Procedures:" procs) ("Syntax:" syntax) ("Variables:" vars) @@ -273,17 +307,19 @@ With prefix argument, ask for symbol (with completion)." (defun geiser-doc-module (&optional module impl) "Display information about a given module." (interactive) - (let* ((module (or module (geiser-completion--read-module))) + (let* ((impl (or impl geiser-impl--implementation)) + (module (geiser-doc--module (or module + (geiser-completion--read-module)) + impl)) (msg (format "Retrieving documentation for %s ..." module)) (exports (progn (message "%s" msg) - (geiser-doc--get-module-exports module))) - (impl (or impl geiser-impl--implementation))) + (geiser-doc--get-module-exports module)))) (if (not exports) (message "No information available for %s" module) (geiser-doc--with-buffer (erase-buffer) - (geiser-doc--insert-title (format "%s" module) t) + (geiser-doc--insert-title (format "%s" module)) (newline) (dolist (g geiser-doc--sections) (geiser-doc--insert-list (car g) @@ -293,7 +329,7 @@ With prefix argument, ask for symbol (with completion)." (setq geiser-doc--buffer-link (geiser-doc--history-push (geiser-doc--make-link nil module impl))) - (geiser-doc--insert-footer) + (geiser-doc--insert-footer impl) (goto-char (point-min))) (message "%s done" msg) (geiser-doc--pop-to-buffer)))) @@ -301,9 +337,9 @@ With prefix argument, ask for symbol (with completion)." (defun geiser-doc-next-section () "Move to next section in this page." (interactive) - (next-line) + (forward-line) (re-search-forward geiser-doc--sections-re nil t) - (previous-line)) + (forward-line -1)) (defun geiser-doc-previous-section () "Move to previous section in this page." @@ -350,12 +386,6 @@ With prefix, the current page is deleted from history." ;;; Documentation browser and mode: -(defsubst geiser-doc--module () - (geiser-impl--call-method - 'find-module - (geiser-doc--implementation) - (geiser-doc--link-module geiser-doc--buffer-link))) - (defun geiser-doc-edit-symbol-at-point () "Open definition of symbol at point." (interactive) @@ -364,8 +394,7 @@ With prefix, the current page is deleted from history." (unless (and impl module) (error "I don't know what module this buffer refers to.")) (with--geiser-implementation impl - (let ((geiser-eval--get-module-function (lambda (&rest x) module))) - (geiser-edit-symbol-at-point))))) + (geiser-edit-symbol-at-point)))) (defvar geiser-doc-mode-map nil) (setq geiser-doc-mode-map @@ -413,6 +442,7 @@ With prefix, the current page is deleted from history." (set-syntax-table scheme-mode-syntax-table) (setq mode-name "Geiser Doc") (setq major-mode 'geiser-doc-mode) + (setq geiser-eval--get-module-function 'geiser-doc--module) (setq buffer-read-only t)) (geiser-popup--define doc "*Geiser documentation*" geiser-doc-mode) diff --git a/elisp/geiser-eval.el b/elisp/geiser-eval.el index 64b36ee..2ca20b4 100644 --- a/elisp/geiser-eval.el +++ b/elisp/geiser-eval.el @@ -23,19 +23,23 @@ ;;; Plug-able functions: -(defvar geiser-eval--get-module-function nil) +(make-variable-buffer-local + (defvar geiser-eval--get-module-function nil)) +(set-default 'geiser-eval--get-module-function nil) +(defvar geiser-eval--get-impl-module) (geiser-impl--register-local-method - 'geiser-eval--get-module-function 'find-module '(lambda (&rest) nil) + 'geiser-eval--get-impl-module 'find-module '(lambda (&rest) nil) "Function used to obtain the module for current buffer. It takes an optional argument, for cases where we want to force its value.") -(defsubst geiser-eval--get-module (&optional module) - (and geiser-eval--get-module-function - (funcall geiser-eval--get-module-function module))) +(defun geiser-eval--get-module (&optional module) + (if geiser-eval--get-module-function + (funcall geiser-eval--get-module-function module) + (funcall geiser-eval--get-impl-module module))) -(defvar geiser-eval--geiser-procedure-function nil) +(defvar geiser-eval--geiser-procedure-function) (geiser-impl--register-local-method 'geiser-eval--geiser-procedure-function 'marshall-procedure 'identity "Function to translate a bare procedure symbol to one executable @@ -86,9 +90,9 @@ module-exports, autodoc, callers, callees and generic-methods.") (defsubst geiser-eval--module (code) (geiser-eval--scheme-str (cond ((or (null code) (eq code :t) (eq code :buffer)) - (funcall geiser-eval--get-module-function)) + (geiser-eval--get-module)) ((or (eq code :repl) (eq code :f)) :f) - (t (funcall geiser-eval--get-module-function code))))) + (t (geiser-eval--get-module code))))) (defsubst geiser-eval--ge (proc args) (apply 'geiser-eval--form (cons proc diff --git a/elisp/geiser-mode.el b/elisp/geiser-mode.el index fe7936f..f755540 100644 --- a/elisp/geiser-mode.el +++ b/elisp/geiser-mode.el @@ -282,6 +282,8 @@ interacting with the Geiser REPL is at your disposal. ("Symbol documentation" ("\C-c\C-d\C-d" "\C-c\C-dd") geiser-doc-symbol-at-point :enable (symbol-at-point)) ("Module documentation" ("\C-c\C-d\C-m" "\C-c\C-dm") geiser-doc-module) + ("Symbol manual lookup" ("\C-c\C-d\C-i" "\C-c\C-di") + geiser-doc-lookup-manual :enable (geiser-doc--manual-available-p)) (mode "Autodoc mode" ("\C-c\C-d\C-a" "\C-c\C-da") geiser-autodoc-mode) -- ("Compile buffer" "\C-c\C-k" geiser-compile-current-buffer) -- cgit v1.2.3