Spaces:
Sleeping
Sleeping
#!/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 <[email protected]> | |
;;; 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 | |