;; This file is part of Idest ;; Copyright (C) 2011 Sergey Poznyakoff ;; ;; Idest 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 3, or (at your option) ;; any later version. ;; ;; Idest 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 Idest. If not, see . (define-module (idest list-modules)) (use-modules (ice-9 getopt-long) (srfi srfi-1)) (define (strip-suffix name) (call-with-current-continuation (lambda (return) (for-each (lambda (suf) (if (and (not (string-null? suf)) (string-suffix? suf name)) (return (substring name 0 (- (string-length name) (string-length suf)))))) %load-extensions) (return #f)))) (define-public (idest-list-modules type) (let ((progname (car (command-line))) (grammar `((which (single-char #\w)))) (print-dir #f)) (catch 'misc-error (lambda () (for-each (lambda (x) (case (car x) ((which) (set! print-dir #t)) (else (set-program-arguments (cons progname (cdr x)))))) (getopt-long (command-line) grammar))) (lambda (key . args) (with-output-to-port (current-error-port) (lambda () (format #t "~A: " progname) (apply format #t (list-ref args 1) (list-ref args 2)) (newline) (exit 1))))) (let ((saved-load-hook %load-hook) ;; Collect a list of possible modules. List elements are conses: ;; (basename . dir) ;; where basename is the module name and dir is the directory where ;; it is found. Make sure only one entry for each basename exists. ;; Sort the list alphabetically on basename. (candidates (sort (fold (lambda (elt prev) (catch 'misc-error (lambda () (let ((dir (string-append elt "/idest/" (symbol->string type)))) (if (and dir (file-exists? dir) (eq? (stat:type (stat dir)) 'directory)) (let ((d (opendir dir))) (let loop ((file (readdir d))) (cond ((not (eof-object? file)) (if (eq? (stat:type (stat (string-append dir "/" file))) 'regular) (let ((base (strip-suffix file))) (if (and base (not (assoc-ref prev base))) (set! prev (cons (cons base dir) prev))))) (loop (readdir d))))))))) (lambda (key . args) #f)) prev) '() %load-path) (lambda (a b) (stringsymbol (car candidate)))))) ; Check if it defines idest-main (module-ref mod 'idest-main) ; Print module name (display (car candidate)) ; Its directory, if required (if print-dir (format #t " (~A)" (cdr candidate))) ; A colon, and description (if any (format #t ": ~A~%" (catch #t (lambda () (module-ref mod 'description)) (lambda (key . args) "no description"))))) (lambda (key . args) #f))) candidates) (newline) (set! %load-hook saved-load-hook))))