]> git.donarmstrong.com Git - lilypond.git/blobdiff - guile18/scripts/summarize-guile-TODO
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / scripts / summarize-guile-TODO
diff --git a/guile18/scripts/summarize-guile-TODO b/guile18/scripts/summarize-guile-TODO
new file mode 100755 (executable)
index 0000000..79543fe
--- /dev/null
@@ -0,0 +1,215 @@
+#!/bin/sh
+# aside from this initial boilerplate, this is actually -*- scheme -*- code
+main='(module-ref (resolve-module '\''(scripts summarize-guile-TODO)) '\'main')'
+exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
+!#
+;;; summarize-guile-TODO --- Display Guile TODO list in various ways
+
+;;     Copyright (C) 2002, 2006 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., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301 USA
+
+;;; Author: Thien-Thi Nguyen <ttn@gnu.org>
+
+;;; Commentary:
+
+;; Usage: summarize-guile-TODO TODOFILE
+;;
+;; The TODOFILE is typically Guile's (see workbook/tasks/README)
+;; presumed to serve as our signal to ourselves (lest we want real
+;; bosses hassling us) wrt to the overt message "items to do" as well as
+;; the messages that can be inferred from its structure.
+;;
+;; This program reads TODOFILE and displays interpretations on its
+;; structure, including registered markers and ownership, in various
+;; ways.
+;;
+;; A primary interest in any task is its parent task.  The output
+;; summarization by default lists every item and its parent chain.
+;; Top-level parents are not items.  You can use these command-line
+;; options to modify the selection and display (selection criteria
+;; are ANDed together):
+;;
+;; -i, --involved USER  -- select USER-involved items
+;; -p, --personal USER  -- select USER-responsible items
+;; -t, --todo           -- select unfinished items (status "-")
+;; -d, --done           -- select finished items (status "+")
+;; -r, --review         -- select review items (marker "R")
+;;
+;; -w, --who            -- also show who is associated w/ the item
+;; -n, --no-parent      -- do not show parent chain
+;;
+;;
+;; Usage from a Scheme program:
+;;   (summarize-guile-TODO . args)      ; uses first arg only
+;;
+;;
+;; Bugs: (1) Markers are scanned in sequence: D R X N%.  This means "XD"
+;;           and the like are completely dropped.  However, such strings
+;;           are unlikely to be used if the markers are chosen to be
+;;           somewhat exclusive, which is currently the case for D R X.
+;;           N% used w/ these needs to be something like: "D25%" (this
+;;           means discussion accounts for 1/4 of the task).
+;;
+;; TODO: Implement more various ways. (Patches welcome.)
+;;       Add support for ORing criteria.
+
+;;; Code:
+(debug-enable 'debug 'backtrace)
+
+(define-module (scripts summarize-guile-TODO)
+  :use-module (scripts read-text-outline)
+  :use-module (ice-9 getopt-long)
+  :autoload (srfi srfi-13) (string-tokenize) ; string library
+  :autoload (srfi srfi-14) (char-set) ; string library
+  :autoload (ice-9 common-list) (remove-if-not)
+  :export (summarize-guile-TODO))
+
+(define put set-object-property!)
+(define get object-property)
+
+(define (as-leaf x)
+  (cond ((get x 'who)
+         => (lambda (who)
+              (put x 'who
+                   (map string->symbol
+                        (string-tokenize who (char-set #\:)))))))
+  (cond ((get x 'pct-done)
+         => (lambda (pct-done)
+              (put x 'pct-done (string->number pct-done)))))
+  x)
+
+(define (hang-by-the-leaves trees)
+  (let ((leaves '()))
+    (letrec ((hang (lambda (tree parent)
+                     (if (list? tree)
+                         (begin
+                           (put (car tree) 'parent parent)
+                           (for-each (lambda (child)
+                                       (hang child (car tree)))
+                                     (cdr tree)))
+                         (begin
+                           (put tree 'parent parent)
+                           (set! leaves (cons (as-leaf tree) leaves)))))))
+      (for-each (lambda (tree)
+                  (hang tree #f))
+                trees))
+    leaves))
+
+(define (read-TODO file)
+  (hang-by-the-leaves
+   ((make-text-outline-reader
+     "(([ ][ ])*)([-+])(D*)(R*)(X*)(([0-9]+)%)* *([^[]*)(\\[(.*)\\])*"
+     '((level-substring-divisor . 2)
+       (body-submatch-number . 9)
+       (extra-fields . ((status . 3)
+                        (design? . 4)
+                        (review? . 5)
+                        (extblock? . 6)
+                        (pct-done . 8)
+                        (who . 11)))))
+    (open-file file "r"))))
+
+(define (select-items p items)
+  (let ((sub '()))
+    (cond ((option-ref p 'involved #f)
+           => (lambda (u)
+                (let ((u (string->symbol u)))
+                  (set! sub (cons
+                             (lambda (x)
+                               (and (get x 'who)
+                                    (memq u (get x 'who))))
+                             sub))))))
+    (cond ((option-ref p 'personal #f)
+           => (lambda (u)
+                (let ((u (string->symbol u)))
+                  (set! sub (cons
+                             (lambda (x)
+                               (cond ((get x 'who)
+                                      => (lambda (ls)
+                                           (eq? (car (reverse ls))
+                                                u)))
+                                     (else #f)))
+                             sub))))))
+    (for-each (lambda (pair)
+                (cond ((option-ref p (car pair) #f)
+                       (set! sub (cons (cdr pair) sub)))))
+              `((todo . ,(lambda (x) (string=? (get x 'status) "-")))
+                (done . ,(lambda (x) (string=? (get x 'status) "+")))
+                (review . ,(lambda (x) (get x 'review?)))))
+    (let loop ((sub (reverse sub)) (items items))
+      (if (null? sub)
+          (reverse items)
+          (loop (cdr sub) (remove-if-not (car sub) items))))))
+
+(define (make-display-item show-who? show-parent?)
+  (let ((show-who
+         (if show-who?
+             (lambda (item)
+               (cond ((get item 'who)
+                      => (lambda (who) (format #f " ~A" who)))
+                     (else "")))
+             (lambda (item) "")))
+        (show-parents
+         (if show-parent?
+             (lambda (item)
+               (let loop ((parent (get item 'parent)) (indent 2))
+                 (and parent
+                      (begin
+                        (format #t "under : ~A~A\n"
+                                (make-string indent #\space)
+                                parent)
+                        (loop (get parent 'parent) (+ 2 indent))))))
+             (lambda (item) #t))))
+    (lambda (item)
+      (format #t "status: ~A~A~A~A~A~A\nitem  : ~A\n"
+              (get item 'status)
+              (if (get item 'design?) "D" "")
+              (if (get item 'review?) "R" "")
+              (if (get item 'extblock?) "X" "")
+              (cond ((get item 'pct-done)
+                     => (lambda (pct-done)
+                          (format #f " ~A%" pct-done)))
+                    (else ""))
+              (show-who item)
+              item)
+      (show-parents item))))
+
+(define (display-items p items)
+  (let ((display-item (make-display-item (option-ref p 'who #f)
+                                         (not (option-ref p 'no-parent #f))
+                                         )))
+    (for-each display-item items)))
+
+(define (summarize-guile-TODO . args)
+  (let ((p (getopt-long (cons "summarize-guile-TODO" args)
+                        '((who (single-char #\w))
+                          (no-parent (single-char #\n))
+                          (involved (single-char #\i)
+                                    (value #t))
+                          (personal (single-char #\p)
+                                    (value #t))
+                          (todo (single-char #\t))
+                          (done (single-char #\d))
+                          (review (single-char #\r))
+                          ;; Add options here.
+                          ))))
+    (display-items p (select-items p (read-TODO (car (option-ref p '() #f))))))
+  #t)                                   ; exit val
+
+(define main summarize-guile-TODO)
+
+;;; summarize-guile-TODO ends here