scsh-users
[Top] [All Lists]

suggested features

To: scsh@martigny.ai.mit.edu
Subject: suggested features
From: brent@jade.ssd.csd.harris.com (Brent Benson)
Date: Fri, 2 Dec 94 08:24:53 -0500
Reply-to: Brent.Benson@mail.csd.harris.com
Here are some suggestions (and sample implementations) of some
features that I missed when re-writing a bunch of /bin/sh and perl
scripts in scsh.  Feel free to use the code if you wish.

* argc

I found that I used (length command-line-arguments) at least once in
most of my scripts.  It would be useful to have a function that
corresponded to `arg' and `argv' that is used for finding the number
of arguments to a script.

      (argc [command-line]) => integer

    When no arguments are supplied, `argc' returns the number of
    command line arguments or (length command-line-arguments).  When
    a list of arguments is provided, it returns the length of that
    list.

A magic variable `argument-count' could be provided instead.

* split

There should be a set of functions for splitting strings into a list
of strings.  I propose:

      (split string) => list of strings

    Splits a string into a list of whitespace delimited string fields.

      (split-fields character string) => list of strings

    Splits a string into a list of strings based on a delimiter character.

      (regexp-split regexp string) => list of strings

    Splits a string into a list of strings based on a delmiting regexp.

* file->list et al

I found myself doing things like (port->string-list (open-input-file "foo")) 
an awful lot.  It would be nice to have

      (file->string filename)
      (file->sexp-list filename)
      (file->string-list filename)
      (file->list reader filename)

---sample implementations---

; With no arguments, return the number of command line arguments.
; If passed an argument list, return the length of the list.
;
(define (argc . maybe-list)
  (let ((command-line #f))
    (cond
     ((null? maybe-list) 
      (set! command-line command-line-arguments))
     ((null? (cdr maybe-list)) 
      (set! command-line (car maybe-list)))
     (else (error "bad argument to ARGC")))
    (if (not (list? command-line))
        (error "bad command line to ARGC"))
    (length command-line)))

; Split a string into a list of strings by stripping whitespace
; from the beginning and end of the original string, pulling
; out whitespace delimited fields.
;
(define (split string)
  (let ((len (string-length string)))

    (define (skip index)
      (cond
       ((= index len) '())
       ((char-whitespace? (string-ref string index))
        (skip (+ index 1)))
       (else (collect index index))))

    (define (collect start end)
      (cond
       ((= end len) 
        (list (substring string start end)))
       ((char-whitespace? (string-ref string end))
        (cons (substring string start end)
              (skip (+ end 1))))
       (else (collect start (+ end 1)))))

    (skip 0)))

; Split a string into a list of strings based on
; a single delimiter character.  Multiple occurences of
; the delimiter character are significant.
;
(define (split-fields delimiter string)
  (let ((len (string-length string)))

    (define (collect start end)
      (cond
       ((= end len)
        (list (substring string start end)))
       ((char=? (string-ref string end) delimiter)
        (cons (substring string start end)
              (collect (+ end 1) (+ end 1))))
       (else (collect start (+ end 1)))))
    
    (collect 0 0)))

; Split a string into a list of strings based on a delimiting
; regular expression.
;
(define (regexp-split regexp string)
  (let ((regexp (if (regexp? regexp) regexp (make-regexp regexp)))
        (len (string-length string)))
    (let loop ((i 0))
      (if (= i len)
          '()
          (let ((match (regexp-exec regexp string i)))
            (if match
                (cons (substring string i (match:start match))
                      (loop (match:end match)))
                (list (substring string i len))))))))
                
; These routines correspond to port->list, file->string,
; file->sexp-list, and file->string-list, but obviate the
; need for opening the file. 
;
(define (file->list reader filename)
  (call-with-input-file filename
    (lambda (port) (port->list reader port))))

(define (file->string filename)
  (call-with-input-file filename
    (lambda (port) (port->string port))))

(define (file->sexp-list filename)
  (file->list read filename))

(define (file->string-list filename)
  (file->list read-line filename))

<Prev in Thread] Current Thread [Next in Thread>