Hi Felix,
I have refreshed my Scheme[1] and wrote some code (see attached
file).
Consider this as a first draft. Feel free to criticize my style but
don't be too harsh (this is the first Scheme code I have ever written!
;).
Some code could probably be optimized for speed. Right now, I'm just
looking for functionalities.
This Scheme code runs with guile but is currently independant of
TeXmacs (start it with "guile -s lp-code.scm").
David MENTRE <[EMAIL PROTECTED]> writes:
>> The way I see it right now the objectives are to create
>>
>> 1) overloaded load-save functions for source files with tm-comments
I haven't look at TeXmacs API yet.
Partially done for load/save functions. This code raises two points:
1. When reading from source, how we should distinguish between
commented TeXmacs lines and source comments? In attached code, I
consider commented TeXmacs lines all lines that start with a comment
on first character. For example:
;<TeXMacs|1.06> <--- TeXmacs line
; <--- code line
(define ....) <--- code line
Should we use a more specific delimiter, like ";tm"?
2. Right now, I represent parsed code as a list of pairs, the right
hand side being 'tm or 'code depending on line content. That should
be rewritten to work with TeXmacs data structure. E.g.:
(define test-scheme-blocks
'((tm . "<TeXmacs|1.0.6")
(tm . "<style|generic>")
(tm . "<\\body>")
(tm . "<tag|;>")
(code . "(define (hello-world) (display \"Hello world!\"))")
(code . "")
(tm . "</body>")
))
>> 2) an import function for plain source files (treating comments as
>> plain text) - 2) will share a lot of code with 1)
Not done yet.
>> 3) a database of commenting syntax (simply as a scheme file)
First attempt provided. We will need to refactor it, for example to
handle languages which have several kinds of comment.
>> 4) create style files that format verbatim blocks nicely (or do we
>> use the <code> tag as is in TeXmacs?)
We could start with the <code> tag.
>> 4) create convenience functions that split/join verbatim blocks
>> (how would you want the user interface for this one to be like?)
A right-click->"Split code line here" would be nice. I don't know if it
can be done easily however.
Best wishes,
d.
Footnotes:
[1] I read the R5RS report, found at:
http://schemers.org/Documents/Standards/R5RS/
--
pub 1024D/A3AD7A2A 2004-10-03 David MENTRE <[EMAIL PROTECTED]>
5996 CC46 4612 9CA4 3562 D7AC 6C67 9E96 A3AD 7A2A
; Scheme code for TeXmacs literate programming mode
; copyright 2006 David MENTRE
; code under GNU GPL
;; needed modules
(use-modules (ice-9 regex)) ; to have Guile's regexp procedures
(use-modules (ice-9 rdelim)) ; to have Guile's (read-line) & Co. procedures
;; database of comment styles
(define comment-db
'((c . #((".c" ".h") ; suffix-list
comment-pair ; comment-style
"/*" ; comment-start
"*/" ; comment-end
#\\)) ; escape-character
(scheme . #((".scm")
comment-until-eol
";"
""
#f)) ; no escape character
(c++ . #((".cpp" ".hpp")
comment-until-eol
"//"
""
#f))
))
;; accessors for this database
(define (comment-config language) (cdr (assoc language comment-db)))
(define (comment-suffixes comment-cfg) (vector-ref comment-cfg 0))
(define (comment-style comment-cfg) (vector-ref comment-cfg 1))
(define (comment-start comment-cfg) (vector-ref comment-cfg 2))
(define (comment-end comment-cfg) (vector-ref comment-cfg 3))
(define (escape-character comment-cfg) (vector-ref comment-cfg 4))
;; output procedures
(define (escape-comment-delimiter comment-cfg comment)
(define (add-escaped-char lst c)
(append lst (list (escape-character comment-cfg) c)))
(define (escape-chars res lst)
(if (null? lst)
res
(escape-chars (add-escaped-char res (car lst)) (cdr lst))))
(list->string (escape-chars '() (string->list comment))))
(define (substitute-in-string in-str matched-str by-str)
(let ((quoted-matched-str (regexp-quote matched-str)))
(regexp-substitute/global #f
quoted-matched-str
in-str
'pre
(lambda (x) by-str)
'post)))
(define (escape-comment-sequences comment-cfg str)
(if (eqv? (comment-style comment-cfg) 'comment-until-eol)
; no need to escape comment
; sequence for comment-until-eol
str
(let ((escaped-start
(escape-comment-delimiter comment-cfg
(comment-start comment-cfg)))
(escaped-end
(escape-comment-delimiter comment-cfg
(comment-end comment-cfg))))
(let ((str-sub-start
(substitute-in-string str ; escape start of comment delimiter
(comment-start comment-cfg)
escaped-start)))
(substitute-in-string str-sub-start ; escape end of comment delimiter
(comment-end comment-cfg)
escaped-end)))))
(define (output-blocks comment-cfg blocks)
(if (not (null? blocks))
(let* ((head (car blocks))
(type (car head))
(data (cdr head)))
(if (eqv? type 'code)
(begin (display data)
(display #\newline)
(output-blocks comment-cfg (cdr blocks)))
(begin (display (comment-start comment-cfg))
(display (escape-comment-sequences comment-cfg data))
(display (comment-end comment-cfg))
(display #\newline)
(output-blocks comment-cfg (cdr blocks)))))))
(define (output-to-file filename comment-cfg blocks)
(with-output-to-file filename
(lambda () (output-blocks comment-cfg blocks))))
;; input procedures
(define (unescape-comment-sequences comment-cfg str)
(if (eqv? (comment-style comment-cfg) 'comment-until-eol)
; no need to escape comment
; sequence for comment-until-eol
str
(let ((escaped-start
(escape-comment-delimiter comment-cfg
(comment-start comment-cfg)))
(escaped-end
(escape-comment-delimiter comment-cfg
(comment-end comment-cfg))))
(let ((str-sub-start
(substitute-in-string str ; escape start of comment delimiter
escaped-start
(comment-start comment-cfg))))
(substitute-in-string str-sub-start ; escape end of comment delimiter
escaped-end
(comment-end comment-cfg))))))
(define (remove-comment-until-eol comment-cfg str)
(let ((delim-len (string-length (comment-start comment-cfg))))
(substring str delim-len (string-length str))))
(define (remove-comment-pair comment-cfg str)
(let ((start-delim-len (string-length (comment-start comment-cfg)))
(end-delim-len (string-length (comment-end comment-cfg))))
(substring str start-delim-len (- (string-length str)
end-delim-len))))
(define (input-as-blocks comment-cfg)
(let ((remove-comment (if (eqv? (comment-style comment-cfg) 'comment-pair)
remove-comment-pair
remove-comment-until-eol))
(start-delim (comment-start comment-cfg))
(start-delim-len (string-length (comment-start comment-cfg))))
(define (read-new-line blocks)
(let ((line (read-line)))
(if (eof-object? line)
(reverse blocks)
(if (< (string-length line) start-delim-len)
; line too short for a comment
(read-new-line (cons (cons 'code line) blocks))
(if (string=? (substring line 0 start-delim-len)
start-delim)
; we have a comment
(let* ((bare-line (remove-comment comment-cfg line))
(unescaped (unescape-comment-sequences comment-cfg
bare-line)))
(read-new-line (cons (cons 'tm unescaped) blocks)))
; we have some code
(read-new-line (cons (cons 'code line) blocks)))))))
(read-new-line '())))
(define (input-from-file filename comment-cfg)
(with-input-from-file filename (lambda () (input-as-blocks comment-cfg))))
;; some tests for previous code
(define test-scheme-blocks
'((tm . "<TeXmacs|1.0.6")
(tm . "<style|generic>")
(tm . "<\\body>")
(tm . "<tag|;>")
(code . "(define (hello-world) (display \"Hello world!\"))")
(code . "")
(tm . "</body>")
))
(define test-c-blocks
'((tm . "<TeXmacs|1.0.6")
(tm . "<style|generic>")
(tm . "<\\body>")
(tm . "<tag|/* */>")
(code . " /* comment */")
(code . "int v;")
(code . "")
(tm . "</body>")
))
(display "\nScheme\n")
(output-blocks (comment-config 'scheme) test-scheme-blocks)
(display "\nC\n")
(output-blocks (comment-config 'c) test-c-blocks)
(output-to-file "/tmp/scheme" (comment-config 'scheme) test-scheme-blocks)
(display (equal? test-scheme-blocks
(input-from-file "/tmp/scheme" (comment-config 'scheme))))
(output-to-file "/tmp/c" (comment-config 'c) test-c-blocks)
(display (equal? test-c-blocks
(input-from-file "/tmp/c" (comment-config 'c))))
_______________________________________________
Texmacs-dev mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/texmacs-dev