-
Notifications
You must be signed in to change notification settings - Fork 168
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
Adapt gambdoc to use the new TSV index #698
base: master
Are you sure you want to change the base?
Conversation
cae6880
to
c0aafce
Compare
@feeley All of the above should be fixed now. Can you review? One nit is that |
It should be |
c0aafce
to
49d5397
Compare
OK, that works: > (help truncate/)
*** ERROR IN (stdin)@1.1 -- no help found for "truncate/" |
How do we change |
@feeley Please advise on |
{ | ||
entry="$GAMBDOC_ARG2_PARAM" | ||
index="$GAMBDOC_ARG3_PARAM" | ||
pattern="$(echo ";$index;$entry" | tr ';' '\t' | tr -d '\n')" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like that this depends on so many things... tr
, grep
, head
, cut
... It will be hard to port to another OS (e.g. Windows).
Here's a wild idea (which I think you've had previously)... how about doing that processing in Scheme using the Gambit interpreter, which we know is installed? The only part of the script that is difficult is launching the browser (because the Gambit runtime system may not have a working implementation of open-process
).
However there is (##os-shell-command cmd)
which uses the C system
function in the usual C-based runtime system. See lib/gambit/process/process.scm
for details. This can be relied on to work on all operating systems with a shell (even Gambit compiled to Python and JavaScript, but only on top of nodejs, have an implementation of ##os-shell-command
).
Come to think of it I may be overly paranoid because gambdoc.bat
is itself launched using open-process
.
And at that point maybe the whole logic should be encapsulated in a Scheme module. I'm not sure how the "find browser" part would be implemented (and portably). There's still an argument to be made to launch a subprocess so that it doesn't interfere with the running Scheme process too much. On the other hand I think it is more valuable to do everything "in process" to minimize external dependencies (in particular it would be easy to get working with the web REPL that runs in an environment where subprocesses are not available, but opening a new web page is easy).
Would you like to prototype this? Perhaps a Scheme module called _doc
or _help
that is builtin. The .tsv file could have been preprocessed to be an s-expression. It is best to read the file every time help
is called (i.e. not cache the database) so that the heap doesn't bloat permanently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like to prototype this?
Yes.
Perhaps a Scheme module called
_doc
or_help
that is builtin.
How about (gambit help)
?
The .tsv file could have been preprocessed to be an s-expression.
I chose the .tsv
format because it's standard (emitted by makeinfo
) while still being very simple. All you need to get the data as Scheme vectors is read-line
and then string-split
on tabs, 5-10 lines of code altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: string-split
is in SRFI 13 which we'll be implementing anyway, and read-line
is in R7RS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, string-split
is not actually in SRFI 13. It's in two of the newer string SRFIs. Might be good to add to (gambit string)
in any case.
Here's a complete parser:
(define (string-split string char)
(let loop ((a 0) (b 0) (fields '()))
(cond ((= b (string-length string))
(reverse (cons (substring string a b) fields)))
((char=? char (string-ref string b))
(loop (+ b 1) (+ b 1) (cons (substring string a b) fields)))
(else
(loop a (+ b 1) fields)))))
(define (parse-tsv)
(let loop ((entries '()))
(let ((line (read-line)))
(if (eof-object? line)
(reverse entries)
(let ((fields (string-split line #\tab)))
(loop (cons (list->vector fields) entries)))))))
(define (writeln x) (write x) (newline))
(for-each writeln (with-input-from-file "gambit.tsv" parse-tsv))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The standard way of doing this in Gambit is
(define (string-split str ch)
(call-with-input-string
str
(lambda (port)
(read-all port (lambda (port) (read-line port ch))))))
With SRFI 13 it is probably faster to do (untested code):
(define (string-split str ch)
(let loop ((i (string-length str)) (fields '()))
(let ((j (string-index-right str ch 0 i)))
(if j
(loop j (cons (substring str (+ j 1) i) fields))
(cons (substring str 0 i) fields)))))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can work on adding an implementation of string-split
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. The following each define string-split
, seemingly with mutually compatible signatures:
- SRFI 130: Cursor-based string library
- SRFI 140: Immutable Strings
- SRFI 152: String Library (reduced)
By the way, the Gambit web REPL uses this code to implement
So perhaps a "hook" is needed in the |
Good idea. |
The SRFI 152 |
I have experimented with 2 implementations of a lookup procedure to find a key in the gambit.tsv file. The first reads the whole .tsv file and splits each line around tabs. The second only reads as much lines as necessary and uses
|
What about |
The file |
There should probably be a |
|
A |
A parameter object lets the implementation provide a default list of browsers to try, which users can customize at runtime (either permanently or temporarily), and also lets libraries either force or prefer a specific browser. Seems like it would cover all use cases in a reasonably simple way. |
The problem with a parameter object is that it conflates two needs. The Scheme program may be executing code that installs a new binding for the list of browsers, because that is part of the logic of the program, and then it encounters an error so a REPL is started to debug that. But if at that REPL the programmer enters |
Note that there is already the parameter object |
49d5397
to
dda51ac
Compare
@feeley Here's a fledgling |
This patch is work-in-progress and is done on top of PR #697.
Adapts
gambdoc.unix.in
and the help procedures inlib/_repl.scm
to work with the TSV index.This doesn't properly handle the case where gambdoc is asked to look for remote documentation on gambitscheme.org; there's enough work as it is that I thought I'd ask for a review before doing that.