unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Improving the help interface
@ 2004-05-07 15:11 Andy Wingo
  2004-08-09 20:47 ` Marius Vollmer
  2004-08-09 20:47 ` Marius Vollmer
  0 siblings, 2 replies; 4+ messages in thread
From: Andy Wingo @ 2004-05-07 15:11 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 2527 bytes --]

Hey folks,

I've been working a bit on the (help ...) interface. I'll explain why
changes are needed, and what my proposed solution does.

I have an app that has a command-line interface and a graphical
interface. The graphical interface has a repl in it, as well as some
other things. One part of the graphical interface is a help browser[0].
It's a traditional tree-on-left, docs-on-right browser that can import
texinfo. In addition to that, it can show help for modules by putting
the commentary (which can have texinfo markup) on top, and individual
help for variables, functions, etc following that. The
object-documentation of the variables can be normal text, texinfo, or my
own ghetto sexp markup, which is nice for programmatic doc construction.

[0] Pretty nifty screenshot:
http://ambient.2y.net/soundscrape/shots/17-dec-2003.png

The problem is that you want (help myvar) to show text in the
command-line mode, and to open the help window to the appropriate node
in graphical mode. It might need to convert the object-documentation to
normal text for the command-line mode.

Furthermore, particular packages might have their own ways of
documenting things; GOOPS objects should be documented using `describe',
for instance.

In conclusion, the help system needs points of extensibility. There are
two points at which customization would be nice: processing the
unevaluated input to `help', and documenting a value (found in a module,
for instance). This patch deals with the latter point.

The attached patch implements "value help handlers" (as opposed to the
former "variable help handlers" or such). A value help handler is a proc
that takes a value. If it returns #f, help keeps looking for
documentation, perhaps falling back on its normal behavior. If it
returns a string, that string is taken to be its help. If it returns #t,
it means that the help has been handled in some other way (graphically,
perhaps), and `help' has nothing else to do. Value help handlers are
added with `add-value-help-handler!', and removed in a similar way.

Thoughts? I'd like this in sometime soon. In the meantime I'm throwing
it in my branch of guile-lib, with handlers for texinfo and stext in
(text structured help). This mechanism could be a way to enable more
literate programming, with the docstrings for scheme code already marked
up as texinfo, and presented in whatever format is appropriate. At
least, that's what I do with it.

ps. It's small, but I don't have papers in for Guile.
-- 
Andy Wingo <wingo@pobox.com>

[-- Attachment #2: session.scm.diff --]
[-- Type: text/x-patch, Size: 5912 bytes --]

--- src/scheme/session.scm	2004-05-07 14:50:23.000000000 +0100
+++ /usr/share/guile/1.6/ice-9/session.scm	2003-08-29 21:26:15.000000000 +0100
@@ -1,4 +1,4 @@
-;;;; 	Copyright (C) 1997, 2000, 2001, 2004 Free Software Foundation, Inc.
+;;;; 	Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc.
 ;;;;
 ;;;; This program is free software; you can redistribute it and/or modify
 ;;;; it under the terms of the GNU General Public License as published by
@@ -45,35 +45,12 @@
   :use-module (ice-9 documentation)
   :use-module (ice-9 regex)
   :use-module (ice-9 rdelim)
-  :export (help add-value-help-handler! remove-value-help-handler!
-           apropos apropos-internal apropos-fold apropos-fold-accessible
-           apropos-fold-exported apropos-fold-all source arity
-           system-module))
+  :export (help apropos apropos-internal apropos-fold
+	   apropos-fold-accessible apropos-fold-exported apropos-fold-all
+	   source arity system-module))
 
 \f
 
-(define *value-help-handlers* '())
-
-(define (add-value-help-handler! proc)
-  "Adds a handler for performing `help' on a value.
-
-`proc' will be called with the value as an argument. `proc' should
-return #t to indicate that it has performed help, a string to override
-the default object documentation, or #f to try the other handlers,
-potentially falling back on the normal behavior for `help'."
-  (set! *value-help-handlers* (cons proc *value-help-handlers*)))
-
-(define (remove-value-help-handler! proc)
-  "Removes a handler for performing `help' on a value.
-
-See the documentation for `add-value-help-handler' for more
-information."
-  (set! *value-help-handlers* (delete! proc *value-help-handlers*)))
-
-(define (try-value-help value)
-  (or-map (lambda (proc) (proc value)) *value-help-handlers*))
-
-
 ;;; Documentation
 ;;;
 (define help
@@ -108,12 +85,10 @@
                 ((and (list? name)
                       (= (length name) 2)
                       (eq? (car name) 'unquote))
-                 (let ((value (local-eval (cadr name) env)))
-                   (cond ((try-value-help value)
-                          => noop)
-                         ((object-documentation value)
-                          => write-line)
-                         (else (not-found 'documentation (cadr name))))))
+                 (cond ((object-documentation
+                         (local-eval (cadr name) env))
+                        => write-line)
+                       (else (not-found 'documentation (cadr name)))))
 
                 ;; (quote SYMBOL)
                 ((and (list? name)
@@ -159,8 +134,7 @@
   (let ((entries (apropos-fold (lambda (module name object data)
 				 (cons (list module
 					     name
-					     (or (try-value-help object)
-                                                 (object-documentation object))
+					     (object-documentation object)
 					     (cond ((closure? object)
 						    "a procedure")
 						   ((procedure? object)
@@ -186,28 +160,22 @@
                                                #f "~S: ~S\n"
                                                (module-name (module entry))
                                                (name entry))))
-                           (cond
-                            ((eq? (doc entry) #t)
-                             ;; a value help handler has already handled
-                             ;; this entry -- don't do anything
-                             #t)
-                            ((doc entry)
-                             (set! documented-entries
-                                   (cons entry-summary documented-entries))
-                             ;; *fixme*: set up a handler in goops.scm
-                             ;; to use `describe'
-                             (set! documentations
-                                   (cons (simple-format
-                                          #f "`~S' is ~A in the ~S module.\n\n~A\n"
-                                          (name entry)
-                                          (type entry)
-                                          (module-name (module entry))
-                                          (doc entry))
-                                         documentations)))
-                            (else
-                             (set! undocumented-entries
-                                   (cons entry-summary
-                                         undocumented-entries))))))
+                           (if (doc entry)
+                               (begin
+                                 (set! documented-entries
+                                       (cons entry-summary documented-entries))
+                                 ;; *fixme*: Use `describe' when we have GOOPS?
+                                 (set! documentations
+                                       (cons (simple-format
+                                              #f "`~S' is ~A in the ~S module.\n\n~A\n"
+                                              (name entry)
+                                              (type entry)
+                                              (module-name (module entry))
+                                              (doc entry))
+                                             documentations)))
+                               (set! undocumented-entries
+                                     (cons entry-summary
+                                           undocumented-entries)))))
                        entries)
 
              (if (and (not (null? documented-entries))
@@ -528,5 +496,4 @@
 	 (string-append "Module " (symbol->string (module-name m))
 			" is now a " (if s "system" "user") " module."))))))
 
-;;; arch-tag: 5348c264-6261-4b1e-b29d-c19bb0fbc94e
 ;;; session.scm ends here

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Improving the help interface
  2004-05-07 15:11 Improving the help interface Andy Wingo
@ 2004-08-09 20:47 ` Marius Vollmer
  2004-08-09 20:47 ` Marius Vollmer
  1 sibling, 0 replies; 4+ messages in thread
From: Marius Vollmer @ 2004-08-09 20:47 UTC (permalink / raw)
  Cc: guile-devel

Andy Wingo <wingo@pobox.com> writes:

> I've been working a bit on the (help ...) interface. I'll explain why
> changes are needed, and what my proposed solution does.

Thanks, and sorry for the late answer.  (I have now organized my mail
better so that I can reply from wherever I am, that should help a
bit...)

> [0] Pretty nifty screenshot:
> http://ambient.2y.net/soundscrape/shots/17-dec-2003.png

Cool!

> The attached patch implements "value help handlers" (as opposed to the
> former "variable help handlers" or such). A value help handler is a proc
> that takes a value. If it returns #f, help keeps looking for
> documentation, perhaps falling back on its normal behavior. If it
> returns a string, that string is taken to be its help. If it returns #t,
> it means that the help has been handled in some other way (graphically,
> perhaps), and `help' has nothing else to do.

I think it is better to separate the action of retrieving the help
text for some feature (value, variable, etc), and the action of
displaying it.  Thus, a help-value-handler handler should not display
the help itself, it should just retrieve it.  Different ways of
displaying help can be implemented by different versions of 'help',
say.

> Value help handlers are added with `add-value-help-handler!', and
> removed in a similar way.

What about using Goops for this?  First, it would suffice to only talk
about 'the helpstring for a value': variables, procedures, macros etc
are all values.  Then there would be two levels of dispatching, I'd
say: first on the type of the value, and the default method for that
is to ask a list of 'help sources' with a second generic function.

Like this, maybe:

    (define-generic help-for-value)
    (define-generic help-from-source)

    (define help-sources ...)

    (define-method (help-for-value (val <gtk-object>))
      ...get it from the gtk docs, say...)

    (define-method (help-for-value val)
      (find-if help-from-source help-sources))

    (define-method (help-from-source (src <std-guile-doc-source>))
      ..use documentation-files ...)

> Thoughts? I'd like this in sometime soon. In the meantime I'm
> throwing it in my branch of guile-lib, with handlers for texinfo and
> stext in (text structured help).

As long as you can cleanly do this, I would prefer not to change the
guile help system in small ways.  I think we should first write a
comprehensive documentation for it "This is how the Guile Help System
Should Work" and then implement it insofar as it differs from what we
have now.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Improving the help interface
  2004-05-07 15:11 Improving the help interface Andy Wingo
  2004-08-09 20:47 ` Marius Vollmer
@ 2004-08-09 20:47 ` Marius Vollmer
  2004-08-15 11:41   ` Andy Wingo
  1 sibling, 1 reply; 4+ messages in thread
From: Marius Vollmer @ 2004-08-09 20:47 UTC (permalink / raw)
  Cc: guile-devel

Andy Wingo <wingo@pobox.com> writes:

> I've been working a bit on the (help ...) interface. I'll explain why
> changes are needed, and what my proposed solution does.

Thanks, and sorry for the late answer.  (I have now organized my mail
better so that I can reply from wherever I am, that should help a
bit...)

> [0] Pretty nifty screenshot:
> http://ambient.2y.net/soundscrape/shots/17-dec-2003.png

Cool!

> The attached patch implements "value help handlers" (as opposed to the
> former "variable help handlers" or such). A value help handler is a proc
> that takes a value. If it returns #f, help keeps looking for
> documentation, perhaps falling back on its normal behavior. If it
> returns a string, that string is taken to be its help. If it returns #t,
> it means that the help has been handled in some other way (graphically,
> perhaps), and `help' has nothing else to do.

I think it is better to separate the action of retrieving the help
text for some feature (value, variable, etc), and the action of
displaying it.  Thus, a help-value-handler handler should not display
the help itself, it should just retrieve it.  Different ways of
displaying help can be implemented by different versions of 'help',
say.

> Value help handlers are added with `add-value-help-handler!', and
> removed in a similar way.

What about using Goops for this?  First, it would suffice to only talk
about 'the helpstring for a value': variables, procedures, macros etc
are all values.  Then there would be two levels of dispatching, I'd
say: first on the type of the value, and the default method for that
is to ask a list of 'help sources' with a second generic function.

Like this, maybe:

    (define-generic help-for-value)
    (define-generic help-from-source)

    (define help-sources ...)

    (define-method (help-for-value (val <gtk-object>))
      ...get it from the gtk docs, say...)

    (define-method (help-for-value val)
      (find-if help-from-source help-sources))

    (define-method (help-from-source (src <std-guile-doc-source>))
      ..use documentation-files ...)

> Thoughts? I'd like this in sometime soon. In the meantime I'm
> throwing it in my branch of guile-lib, with handlers for texinfo and
> stext in (text structured help).

As long as you can cleanly do this, I would prefer not to change the
guile help system in small ways.  I think we should first write a
comprehensive documentation for it "This is how the Guile Help System
Should Work" and then implement it insofar as it differs from what we
have now.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Improving the help interface
  2004-08-09 20:47 ` Marius Vollmer
@ 2004-08-15 11:41   ` Andy Wingo
  0 siblings, 0 replies; 4+ messages in thread
From: Andy Wingo @ 2004-08-15 11:41 UTC (permalink / raw)


Hi Marius,

Glad to hear you have improved your email setup ;-)

On Mon, 09 Aug 2004, Marius Vollmer wrote:

> Andy Wingo <wingo@pobox.com> writes:
> 
> > The attached patch implements "value help handlers" (as opposed to the
> > former "variable help handlers" or such). A value help handler is a proc
> > that takes a value. If it returns #f, help keeps looking for
> > documentation, perhaps falling back on its normal behavior. If it
> > returns a string, that string is taken to be its help. If it returns #t,
> > it means that the help has been handled in some other way (graphically,
> > perhaps), and `help' has nothing else to do.
> 
> I think it is better to separate the action of retrieving the help
> text for some feature (value, variable, etc), and the action of
> displaying it.  Thus, a help-value-handler handler should not display
> the help itself, it should just retrieve it.  Different ways of
> displaying help can be implemented by different versions of 'help',
> say.

Hm. I agree, and also disagree ;) The only issue is the format for the
help. For some objects, help can be generated at runtime. It would be a
bit of a pain to render this semantic documentation to some kind of
serialization, e.g. as XML or texinfo, if it already exists in a native
scheme format, e.g SXML or stexinfo.

Having plain text as a bottleneck between retrieval and display would
not be helpful[0]. If we allow the help "text" to be of any value type
(as is the case now), this would not be a problem. As you mention, GOOPS
could assist with this.

[0] Ha! I'm punny.

> What about using Goops for this?  First, it would suffice to only talk
> about 'the helpstring for a value': variables, procedures, macros etc
> are all values.  Then there would be two levels of dispatching, I'd
> say: first on the type of the value, and the default method for that
> is to ask a list of 'help sources' with a second generic function.
> 
> Like this, maybe:
> 
>     (define-generic help-for-value)
>     (define-generic help-from-source)
> 
>     (define help-sources ...)
> 
>     (define-method (help-for-value (val <gtk-object>))
>       ...get it from the gtk docs, say...)
> 
>     (define-method (help-for-value val)
>       (find-if help-from-source help-sources))
> 
>     (define-method (help-from-source (src <std-guile-doc-source>))
>       ..use documentation-files ...)

Obviously this is a better solution ;) Would you mind autoloading GOOPS
when `help' is called?

[I've grown a bit wary of the object-orientation-everywhere tendency,
but this seems to be a valid application.]

> > Thoughts? I'd like this in sometime soon. In the meantime I'm
> > throwing it in my branch of guile-lib, with handlers for texinfo and
> > stext in (text structured help).
> 
> As long as you can cleanly do this, I would prefer not to change the
> guile help system in small ways.  I think we should first write a
> comprehensive documentation for it "This is how the Guile Help System
> Should Work" and then implement it insofar as it differs from what we
> have now.

Sounds good. I was being a bit more timid, but as maintainer you were
already thinking broadly. I'll see about writing something and send it
to the list.

Regards,
--
Andy Wingo <wingo@pobox.com>
http://ambient.2y.net/wingo/


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-08-15 11:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-07 15:11 Improving the help interface Andy Wingo
2004-08-09 20:47 ` Marius Vollmer
2004-08-09 20:47 ` Marius Vollmer
2004-08-15 11:41   ` Andy Wingo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).