guile-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(scripts read-text-outline)


From: Thien-Thi Nguyen
Subject: (scripts read-text-outline)
Date: Tue, 02 Apr 2002 03:29:57 -0800

so nice to get away from funky meta issues and write a little tree
program for relaxation.  ahhh.  but wait, there's process application!
nooo!!  (this will be used to help publish file workbook/tasks/TODO in
the grand tradition of the early guile webpages, but hopefully w/ next
to zero hand-maintenance.)

i tried a tail-pointer style for building the tree -- feedback on this
approach welcome!

thi



_______________________________________________
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts read-text-outline)) '\'main')'
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
!#
;;; read-text-outline --- Read a text outline and display it as a sexp

;;      Copyright (C) 2002 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 the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this software; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA

;;; Author: Thien-Thi Nguyen <address@hidden>

;;; Commentary:

;; Usage: read-text-outline OUTLINE
;;
;; Scan OUTLINE file and display a list of trees, the structure of
;; each reflecting the "levels" in OUTLINE.  The recognized outline
;; format (used to indicate outline headings) is zero or more pairs of
;; leading spaces followed by "-" or "+".  Something like:
;;
;;    - a                  0
;;      - b                1
;;        - c              2
;;      - d                1
;;    - e                  0
;;      - f                1
;;        - g              2
;;      -h                 1
;;
;; In this example the levels are shown to the right.  The output for
;; such a file would be the single line:
;;
;;   (("a" ("b" "c") "d") ("e" ("f" "g") "h"))
;;
;;
;; Usage from a Scheme program: These three procs are exported:
;;
;;   (read-text-outline . args)           ; only first arg is used
;;   (read-text-outline-silently port)
;;   (display-outline-tree tree)
;;
;; Don't forget to iterate (say, `display-outline-tree') over the list of
;; trees that `read-text-outline-silently' returns.
;;
;;
;; Bugs and caveats:
;;
;; (1) Only the first file specified on the command line is scanned.
;; (2) TAB characters at the beginnings of lines are not recognized.
;; (3) Outlines that "skip" levels signal an error.  In other words,
;;     this will fail:
;;
;;            - a               0
;;              - b             1
;;                  - c         3       <-- skipped 2 -- error!
;;              - d             1
;;
;;
;; TODO: Determine what's the right thing to do for skips.
;;       Handle TABs.
;;       Handle follow-on lines.
;;       Make line/display format customizable via longopts.

;;; Code:

(define-module (scripts read-text-outline)
  :export (read-text-outline read-text-outline-silently display-outline-tree)
  :use-module (ice-9 regex)
  :use-module (ice-9 rdelim))

;; todo: make customizable
(define *depth-cue-rx* (make-regexp "(([ ][ ])*)[-+] *"))
(define *subm-number* 1)
(define *level-divisor* 2)

(define (>> level line)
  (format #t "\t~A\t~A- ~A\n" level (make-string level #\space) line))

(define (display-outline-tree level tree)
  (cond ((list? tree)
         (>> level (car tree))
         (for-each (lambda (kid)
                     (display-outline-tree (+ *level-divisor* level) kid))
                   (cdr tree)))
        (else (>> level tree))))

(define (read-text-outline-silently port)
  (let* ((all '(start))
         (pchain (list))                ; parents chain
         (tp all))                      ; tail pointer
    (let loop ((line (read-line port)) (prev-level -1))
      (or (eof-object? line)
          (cond ((regexp-exec *depth-cue-rx* line)
                 => (lambda (m)
                      (let* ((words (list (match:suffix m)))
                             (level (/ (string-length
                                        (or (match:substring m *subm-number*)
                                            ""))
                                       *level-divisor*))
                             (diff (- level prev-level))
                             (saved-tp tp))
                        (cond

                         ;; sibling
                         ((zero? diff)
                          (set-cdr! tp words)
                          (set! tp words))

                         ;; child
                         ((positive? diff)
                          (or (= 1 diff)
                              (error "unhandled diff not 1:" diff line))
                          (set-object-property! tp 'level prev-level)
                          (set! pchain (cons tp pchain))
                          (set-car! tp (cons (car tp) words))
                          (set! tp words))

                         ;; uncle
                         ((negative? diff)
                          (do ((p pchain (cdr p)))
                              ((= level (object-property (car p) 'level))
                               (set! pchain p)))
                          (set-cdr! (car pchain) words)
                          (set! pchain (cdr pchain))
                          (set! tp words)))

                        (loop (read-line port) level))))
                (else (loop (read-line port) prev-level)))))
    (set! all (car all))
    (if (eq? 'start all)
        '()
        (cdr all))))

(define (read-text-outline . args)
  (let ((trees (read-text-outline-silently (open-file (car args) "r"))))
    ;; try this
    ;; (for-each (lambda (tree)
    ;;             (display-outline-tree 0 tree))
    ;;           trees))
    (write trees)
    (newline))
  #t)                                   ; exit val

(define main read-text-outline)

;;; read-text-outline ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]