Main Page       Index


su.lsp


 su.lsp
 Version 1.00
 Date 31 October 2004
 Authors:
 Steven Jones

 Contact jones57@swbell.net include the word "nyquist" in subject line

 The contents of this file are released under the terms of the GNU General
 Public License. See the file LICENSE.txt
>
 Implements a subset of the Python string module in XLISP.  Most of the
 standard python string functions are implemented with near identical
 behavior. The match between the python standard is not 100%. Besides the
 obvious difference between LISP and Python any other differences are noted
 in the embedded documentation.  A few additional functions have also been
 defined.
 
 Python string functions which have not been implemented.
 index
 rindex
 maketrans
 swapcase
 translate
 replace


function

->string

 (->string n)
 Convert object to string

 n      - any
 return - string


function

su:expandtabs

 (su:expandtabs |tabsize|)
 Replace tab characters in string with spaces.

 str     - string. The string to be expanded
 tabsize - integer. Size of tab, default: 8
 return  - string.


function

su:reverse

 (su:reverse  str)
 Reverse characters of string

 str    - string. The string to be reversed
 return - string.


function

su:find

 (su:find  str sub [:start s][:end e])
 Locate index of substring within string.

 str    - string. The string to be searched.
 sub    - string. The sub-string to search for.
 :start - integer. The starting index of the search. default: 0
 :end   - integer. The ending search index. default: Length of str.
 return - integer. The index of the first occurrence of sub in str which is
          greater than start and less than end. If there is no such match 
          return NIL.

 NOTE:  Differences between this function and the python
 equivalent:
 1) The python version accepts negative indexing for start and stop.
 2) The python version returns -1 for a non-match.


function

su:find-any

 (su:find-any  str  sublst [:start s][:end e])
 Find occurrence of any string in sublst in string.
 This is similar to find but accepts a list of target strings instead of a
 single sub-string. If any string in the target list is located its
 position is returned.

 str    - string. The string to search.
 sublst - list of strings.   A list of sub-strings to search in str.
 :start - integer. Starting index of search.
 :end   - integer. Ending index of search.
 return - integer.  The index of the first element in sublst which is located
          in str. The result is greater than start and less than end. 
          If no match is found the result is NIL.


function

su:rfind

 (su:rfind  str sub [:start s][:end e])
 Search for substring starting from right side of string.
 su:rfind has the same argument set as find and the same python/lisp difference
 apply.  See su:find.


function

su:count

 (su:count  str sub [:start s][:end e])
 Return number of non-overlapping copies of substring in string.
 str    - string. The string to be searched.
 sub    - string. The search string to be counted.
 :start - integer. The starting index of search.
 :end   - integer. The ending index of the search.
 return - integer  .
 NOTE: Python version accepts negative indexes.


function

su:lower

 (su:lower str)
 Convert string to lower case. Exactly equivalent to string-downcase.

 str    - string.
 return - string. 


function

su:left-trim-all

 (su:left-trim-all  str [chrs])
 Remove all left most characters of string which are also characters in chrs
 str    - string. The string to be trimmed.
 chrs   - string. Characters to be removed. default: su:*whitespace*
 return - string. 


function

su:find-first-non-matching-char

 (su:find-first-non-matching-char  str  [chrs])
 Locate index of the left-most character of str which is not also
 a character of chrs. Hows that for clarity?
 
 str    - string. The string to be searched.
 chrs   - string. The characters search for.
 return - integer. The index of the first character in str which is not also
          a character in chrs. If all characters of str are also characters 
          of chrs return NIL.


function

su:string-to-char-list

 (su:string-to-char-list  str)
 Convert string to list of single character strings.

 str    - string. The string to be converted.
 return - list. 


function

su:split-first

 (su:split-first  str  [chars])
 Split string at first "word"
 A word is defined as any continuous sequence of characters which are not in
 the string chars. The default is to delineate words by whitespace.

 str    - string. The string to be split.

 chars  - string. Characters to be used as deliminators.
          default su:*whitespace*

 return - list. The result is a list, the car which is the first word
          (trimmed of leading and trailing deliminators) in str.  If 
          there are more than on word in the original string the cdr 
          of the result is a string containing the original text without 
          the first word.


function

su:split

 (su:split  str [chars])
 Convert string into list of words. A word is any continuous sequence of
 characters not containing a deliminator. By default words are separated by
 any white character.

 str    - string. The string to be split.

 chars  - string. The delineation characters.

 return - list
 
 NOTE: There are several difference between the XLISP and Python version of
 split:
 1) In XLISP version the deliminators are only 1 character. The Python
 version allows for arbitrary string 
 2) The XLISP version allows for multiple deliminators.
 3) The python version takes an optional maxsplit argument.


function

su:join

 (su:join lst [sep])
 Concatenate list elements to string.

 lst    - list. 
 sep    - string. The string to be inserted between adjacent elements of lst
 return - string 


function

su:lstrip

 (su:lstrip  str [chars])
 Remove all left most characters of string which are also characters in
 chars

 str    - string. The string to be stripped.
 chars  - string. List of characters to strip, default su:*whitespace*
 return - string. 


function

su:rstrip

 (su:rstrip str [chars])
 Right hand version of su:lstrip.


function

su:strip

 (su:strip str [chars])
 Bilateral version of su:lstrip.


function

su:upper

 (su:upper str)
 Convert string to upper case.


function

su:ljust

 (su:ljust str width [pad])
 Left justify string.

 str    - string. The text to be justified.

 width  - integer. The minimum length of the result.

 pad    - string. Character(s) to be inserted to fill out result to required
          length. default: space
 
 return - string. The result is always at least width characters and source
          string is never truncated.

 NOTE: The XLISP version allows pad character to be set as an option, the
 python version does not.


function

su:rjust

 (su:rjust  str  width [pad])
 The right hand version of su:ljust.


function

su:center

 (su:center  str width [rpad [lpad]])
 Center text in field of width characters.

 str    - string. The string to be centered.

 width  - integer. The minimum length of result.

 rpad   - string. The right hand pad character. default space

 lpad   - string. The left hand pad character. default space

 return - string. The result is always at least width characters. 
          The source string is never truncated.

 NOTE: XLISP version allows the pad characters to be something other than a
 space. Further the left and right pad characters may be set separately.


function

su:zfill

 (su:zfill str width)
 Pad string with zeros on left to at least width characters.
 Strings with leading sign characters are handled properly.

 str    - string. The string to be padded.
 width  - integer. The minimum number of characters.
 return - string.


function

su:capitalize

 (su:capitalize  str)
 Capitalize first character in string.


function

su:capwords

 (su:capwords str)
 Capitalize each word in str

 str    - string. The string to be capitalized.
 return - string .

 NOTE Embedded white space which spans more than one character is replaced
 by a single space.


function

su:starts-with

 (su:starts-with   str pat [nocase])
 Test if string starts with pattern.
 
 str    - string. The string to be tested.
 pat    - string. The pattern 
 nocase - bool. If true the test is case insensitive. Default: NIL
 return - bool. True iff str starts with pat.


function

su:ends-with

 (su:ends-with str pat [nocase])
 Test if string ends with pattern

 str    - string. The string to be tested

 pat    - string. The pattern

 nocase - bool. If true the test is case insensitive: Default: NIL

 return - bool. True iff str ends with pat.


function

su:but-first

 (su:but-first  (str [n]))
 Return all but first character of string.

 str    - string. The string to be processed

 n      - integer. The number of characters to be skipped. Default: 1

 return - string. All but the first n characters of str.
          If str is NIL or "" return and empty string.
          If n > length of str, return ""


function

su:but-last

 (su:but-last  str [n])
 Return all but last n characters of string.

 str    - string. The string to be processed.

 n      - integer. The number of characters to strip from end. Default: 1

 return - string   All but the last n characters of str.
          If str is NIL or "" return ""
          If n > length of str return ""


function

su:-but-last

 (su:-but-last  str pat [nocase])
 Conditional version of su:but-last

 str    - string. The string to be processed.

 pat    - string. The pattern.

 nocase - bool. If true the test is case insensitive.

 return - string. If string str ends with the sub-string pat, strip pat 
          from the end of str and return. 
          If string str does not end with pat, return str.


function

su:strcat

 (su:strcat [a1 [a2 [a3 ... [an]]]])
 The su version of strcat. 
 The standard strcat function may only take string arguments. su:strcat may
 take any object as an argument. Non-string arguments are converted to their
 string representation and then concatenated to the result. NIL arguments
 are converted to an empty string "".

 a1 a2 a3 ...-  any.  Arbitrary number of arguments to be converted
                 to string and concatenated.

 return - string.


function

su:quote

 (su:quote  str  [q])
 Add quotation characters around string.

 str    - string.  The string to be quoted.

 q      -  char.  The quote character. Default #\"

 return - string


macro

su:cat

 (su:cat str frmt [args ...])
 Destructive string concatenation with format.
 su:cat is an alias for 
 (setq str (strcat str (format nil frmt args....)))
 
 str    - Symbol. A variable containing a string. The value of str is 
          changed as a side effect

 frmt   - String. The string formating template. See standard XLISP format 
          statement.

 return - String. The new value of str.


View the Sourcecode :



;; su.lsp
;; Version 1.00
;; Date 31 October 2004
;; Authors:
;; Steven Jones
;;
;; Contact jones57@swbell.net include the word "nyquist" in subject line
;;
;; The contents of this file are released under the terms of the GNU General
;; Public License. See the file LICENSE.txt
;;
;; Implements a subset of the Python string module in XLISP.  Most of the
;; standard python string functions are implemented with near identical
;; behavior. The match between the python standard is not 100%. Besides the
;; obvious difference between LISP and Python any other differences are noted
;; in the embedded documentation.  A few additional functions have also been
;; defined.
;; 
;; Python string functions which have not been implemented.
;; index
;; rindex
;; maketrans
;; swapcase
;; translate
;; replace
;; 

(current-file "su")
(provide 'su)

(setf su:*ascii-lowercase*   "abcdefghijklmnopqrstuvwxyz")
(setf su:*ascii-uppercase*   "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(setf su:*digits*            "0123456789")
(setf su:*hexdigits*         "0123456789abcdefABCDEF")
(setf su:*octdigits*         "01234567")
(setf su:*punctuation*       "~!@#$%^&*()_+`-={}|\\:;'\"<>?,./")
(setf su:*whitespace*        "\t\n ")
(setf su:*null*              "")


;; @doc function ->string
;; (->string n)
;; Convert object to string
;;
;; n      - any
;; return - string
;;

(defun ->string (n)
  (if (stringp n) n
    (format nil "~a" n)))


;; @doc function  su:expandtabs
;; (su:expandtabs |tabsize|)
;; Replace tab characters in string with spaces.
;;
;; str     - string. The string to be expanded
;; tabsize - integer. Size of tab, default: 8
;; return  - string.
;;

(defun su:expandtabs (str &optional (tabsize 8))
  (let ((sp (do ((index 0 (+ 1 index))(rs su:*null*)) ;tab replacement string
		((>= index tabsize) rs)
	      (setf rs (strcat rs " "))))
	(acc su:*null*))			       ;Result 
    (do ((index 0 (+ index 1)))
	((>= index (length str)))
      (let ((test (subseq str index (+ index 1))))
	(if (string= test "\t")
	    (setf acc (strcat acc sp))
	  (setf acc (strcat acc test)))))
    acc))


;; @doc function  su:reverse
;; (su:reverse  str)
;; Reverse characters of string
;;
;; str    - string. The string to be reversed
;; return - string.
;;

(defun su:reverse (str)
  (let ((rs su:*null*))
    (dotimes (i (length str))
      (let ((j (- (length str) 1 i)))
	(setf rs (strcat rs (subseq str j (+ j 1))))))
    rs))


;; @doc function  su:find
;; (su:find  str sub [:start s][:end e])
;; Locate index of substring within string.
;;
;; str    - string. The string to be searched.
;; sub    - string. The sub-string to search for.
;; :start - integer. The starting index of the search. default: 0
;; :end   - integer. The ending search index. default: Length of str.
;; return - integer. The index of the first occurrence of sub in str which is
;;          greater than start and less than end. If there is no such match 
;;          return NIL.
;;
;; NOTE:  Differences between this function and the python
;; equivalent:
;; 1) The python version accepts negative indexing for start and stop.
;; 2) The python version returns -1 for a non-match.
;;

(defun su:find (str sub &key start end)
  (if (null sub)
      nil
    (let ((start (or start 0))
	  (end (or end (length str))))
      (string-search sub str :start start :end end))))


;; @doc function su:find-any
;; (su:find-any  str  sublst [:start s][:end e])
;; Find occurrence of any string in sublst in string.
;; This is similar to find but accepts a list of target strings instead of a
;; single sub-string. If any string in the target list is located its
;; position is returned.
;;
;; str    - string. The string to search.
;; sublst - list of strings.   A list of sub-strings to search in str.
;; :start - integer. Starting index of search.
;; :end   - integer. Ending index of search.
;; return - integer.  The index of the first element in sublst which is located
;;          in str. The result is greater than start and less than end. 
;;          If no match is found the result is NIL.
;;

(defun su:find-any (str sublst &key start end)
  (let ((index (su:find str (car sublst) :start start :end end)))
    (or index (if sublst
		  (su:find-any str (cdr sublst) :start start :end end)
		nil))))


;; @doc function  su:rfind
;; (su:rfind  str sub [:start s][:end e])
;; Search for substring starting from right side of string.
;; su:rfind has the same argument set as find and the same python/lisp difference
;; apply.  See su:find.
;;

(defun su:rfind (str sub &key start end)
  (let ((index (su:find (su:reverse str) (su:reverse sub) :start start :end end)))
    (if index
	(- (length str) index 1)
      NIL)))


;; @doc function  su:count
;; (su:count  str sub [:start s][:end e])
;; Return number of non-overlapping copies of substring in string.
;; str    - string. The string to be searched.
;; sub    - string. The search string to be counted.
;; :start - integer. The starting index of search.
;; :end   - integer. The ending index of the search.
;; return - integer  .
;; NOTE: Python version accepts negative indexes.
;;

(defun su:count (str sub &key start end)
  (let* ((rs 0)
	 (start (or start 0))
	 (end (or end (length str)))
	 (index (su:find str sub :start start :end end)))
    (if index
	(+ 1 (su:count str sub :start (+ index (length sub)) :end))
      0)))


;; @doc function  su:lower
;; (su:lower str)
;; Convert string to lower case. Exactly equivalent to string-downcase.
;;
;; str    - string.
;; return - string. 
;;

(setfn su:lower string-downcase)


;; @doc function   su:left-trim-all
;; (su:left-trim-all  str [chrs])
;; Remove all left most characters of string which are also characters in chrs
;; str    - string. The string to be trimmed.
;; chrs   - string. Characters to be removed. default: su:*whitespace*
;; return - string. 
;;

(defun su:left-trim-all (str &optional (chrs su:*whitespace*))
  (if (not (zerop (length str)))
      (let ((first (subseq str 0 1)))
	  ;(format t "STR=~a \t FIRST=~a  CHRS=~a~%"  str first chrs)
	(if (string-search first chrs)
	    (su:left-trim-all (subseq str 1) chrs )
	  str))))


;; @doc function  su:find-first-non-matching-char
;; (su:find-first-non-matching-char  str  [chrs])
;; Locate index of the left-most character of str which is not also
;; a character of chrs. Hows that for clarity?
;; 
;; str    - string. The string to be searched.
;; chrs   - string. The characters search for.
;; return - integer. The index of the first character in str which is not also
;;          a character in chrs. If all characters of str are also characters 
;;          of chrs return NIL.
;;

(defun su:find-first-non-matching-char (str &optional (chrs su:*whitespace*))
  (do ((index 0 (+ index 1))(stop nil))
      ((or (>= index (length str)) stop)(if stop (- index 1) nil))
    (let ((test (subseq str index (+ index 1))))
      (if (not (string-search test chrs))
	  (setf  stop t)))))


;; @doc function   su:string-to-char-list
;; (su:string-to-char-list  str)
;; Convert string to list of single character strings.
;;
;; str    - string. The string to be converted.
;; return - list. 
;;

(defun su:string-to-char-list (str)
  (if (not (zerop (length str)))
      (cons (subseq str 0 1)(su:string-to-char-list (subseq str 1)))
    nil))


;; @doc function  su:split-first
;; (su:split-first  str  [chars])
;; Split string at first "word"
;; A word is defined as any continuous sequence of characters which are not in
;; the string chars. The default is to delineate words by whitespace.
;;
;; str    - string. The string to be split.
;;
;; chars  - string. Characters to be used as deliminators.
;;          default su:*whitespace*
;;
;; return - list. The result is a list, the car which is the first word
;;          (trimmed of leading and trailing deliminators) in str.  If 
;;          there are more than on word in the original string the cdr 
;;          of the result is a string containing the original text without 
;;          the first word.
;;

(defun su:split-first (str &optional (chars su:*whitespace*))
  (let ((str (su:left-trim-all str chars)))
    (let ((index (su:find-any str (su:string-to-char-list chars))))
      (if index
	  (list (subseq str 0 index)(subseq str index))
	(cons str nil)))))


;; @doc function   su:split
;; (su:split  str [chars])
;; Convert string into list of words. A word is any continuous sequence of
;; characters not containing a deliminator. By default words are separated by
;; any white character.
;;
;; str    - string. The string to be split.
;;
;; chars  - string. The delineation characters.
;;
;; return - list
;; 
;; NOTE: There are several difference between the XLISP and Python version of
;; split:
;; 1) In XLISP version the deliminators are only 1 character. The Python
;; version allows for arbitrary string 
;; 2) The XLISP version allows for multiple deliminators.
;; 3) The python version takes an optional maxsplit argument.
;;

(defun su:split (str &optional (chars su:*whitespace*))
  (if (not (su:find-first-non-matching-char str chars))
      nil
    (let ((lst (su:split-first str chars)))
      (if (cdr lst)
	  (cons (car lst)(su:split (car (cdr lst)) chars))
	lst))))


;; Used as part of su:join
;;

(defun su:__join (lst &optional (sep " "))
  (if lst
      (strcat (format nil (strcat "~a" sep)(car lst))(su:__join (cdr lst) sep))
    su:*null*))


;; @doc function  su:join
;; (su:join lst [sep])
;; Concatenate list elements to string.
;;
;; lst    - list. 
;; sep    - string. The string to be inserted between adjacent elements of lst
;; return - string 
;;

(defun su:join (lst &optional (sep " "))
  (let ((rs (su:__join lst sep)))
    (subseq rs 0 (- (length rs)(length sep)))))


;; @doc function  su:lstrip
;; (su:lstrip  str [chars])
;; Remove all left most characters of string which are also characters in
;; chars
;;
;; str    - string. The string to be stripped.
;; chars  - string. List of characters to strip, default su:*whitespace*
;; return - string. 
;;

(defun su:lstrip (str &optional (chars su:*whitespace*))
  (string-left-trim chars str))


;; @doc function  su:rstrip
;; (su:rstrip str [chars])
;; Right hand version of su:lstrip.
;;

(defun su:rstrip (str &optional (chars su:*whitespace*))
  (string-right-trim chars str))


;; @doc function  su:strip
;; (su:strip str [chars])
;; Bilateral version of su:lstrip.
;;

(defun su:strip (str &optional (chars su:*whitespace*))
  (su:lstrip (su:rstrip str chars) chars))


;; @doc function  su:upper
;; (su:upper str)
;; Convert string to upper case.
;;

(setfn su:upper string-upcase)


;; @doc function  su:ljust
;; (su:ljust str width [pad])
;; Left justify string.
;;
;; str    - string. The text to be justified.
;;
;; width  - integer. The minimum length of the result.
;;
;; pad    - string. Character(s) to be inserted to fill out result to required
;;          length. default: space
;; 
;; return - string. The result is always at least width characters and source
;;          string is never truncated.
;;
;; NOTE: The XLISP version allows pad character to be set as an option, the
;; python version does not.
;;

(defun su:ljust (str width &optional (pad " "))
  (if (< (length str) width)
      (su:ljust (strcat str pad) width pad)
    str))


;; @doc function  su:rjust
;; (su:rjust  str  width [pad])
;; The right hand version of su:ljust.
;;

(defun su:rjust (str width &optional (pad " "))
  (if (< (length str) width)
      (su:rjust (strcat pad str) width pad)
    str))


;; @doc function   su:center
;; (su:center  str width [rpad [lpad]])
;; Center text in field of width characters.
;;
;; str    - string. The string to be centered.
;;
;; width  - integer. The minimum length of result.
;;
;; rpad   - string. The right hand pad character. default space
;;
;; lpad   - string. The left hand pad character. default space
;;
;; return - string. The result is always at least width characters. 
;;          The source string is never truncated.
;;
;; NOTE: XLISP version allows the pad characters to be something other than a
;; space. Further the left and right pad characters may be set separately.
;;

(defun su:center (str width &optional (rpad " ")(lpad " "))
  (if (< (length str) width)
      (su:center (strcat rpad str lpad) width rpad lpad)
    str))


;; @doc function  su:zfill
;; (su:zfill str width)
;; Pad string with zeros on left to at least width characters.
;; Strings with leading sign characters are handled properly.
;;
;; str    - string. The string to be padded.
;; width  - integer. The minimum number of characters.
;; return - string.
;;

(defun su:zfill (str width)
  (if (numberp str)
      (setf str (string-trim " " (->string str))))
  (let ((sign (if (not (zerop (length str)))
		  (subseq str 0 1)
		su:*null*)))
    (if (or (string= sign "+")(string= sign "-"))
	(let ()
	  (setf str (su:rjust (subseq str 1)(- width 1) "0"))
	  (strcat sign str))
      (su:rjust str width "0"))))


;; @doc function  su:capitalize 
;; (su:capitalize  str)
;; Capitalize first character in string.
;;

(defun su:capitalize (str)
  (if (not (zerop (length str)))
      (strcat (su:upper (subseq str 0 1))(subseq str 1))
    str))


;; Used as part of su:capwords definition.
;;

(defun su:__capwords (lst)
  (if lst
      (cons (su:capitalize (format nil "~a" (car lst)))(su:__capwords (cdr lst)))
    nil))


;; @doc function  su:capwords
;; (su:capwords str)
;; Capitalize each word in str
;;
;; str    - string. The string to be capitalized.
;; return - string .
;;
;; NOTE Embedded white space which spans more than one character is replaced
;; by a single space.
;;

(defun su:capwords (str)
  (if (zerop (length str))
      str
    (let ((lst (su:__capwords (su:split str))))
      (su:join lst))))


;; function  su:list->string  DEPRECIATED
;; (su:list->string   lst [spacer])
;; Exactly equivalent to list->string defined in utilities.lsp
;;
;;(defun su:list->string (lst &optional (spacer " "))
;;  (if lst
;;      (strcat (car (format nil "~a~a" (car lst) spacer)
;;		   (su:list->string (cdr lst) spacer)))
;;    ""))


;; @doc function  su:starts-with
;; (su:starts-with   str pat [nocase])
;; Test if string starts with pattern.
;; 
;; str    - string. The string to be tested.
;; pat    - string. The pattern 
;; nocase - bool. If true the test is case insensitive. Default: NIL
;; return - bool. True iff str starts with pat.
;;

(defun su:starts-with  (str pat &optional (nocase nil))
  (let (tstr tpat index)
    (if nocase
	(setf tstr (su:lower str)
	      tpat (su:lower pat))
      (setf tstr str
	    tpat pat))
    (setf index (string-search tpat tstr))
    (and (numberp index) (zerop index))))


;; @doc function  su:ends-with 
;; (su:ends-with str pat [nocase])
;; Test if string ends with pattern
;;
;; str    - string. The string to be tested
;;
;; pat    - string. The pattern
;;
;; nocase - bool. If true the test is case insensitive: Default: NIL
;;
;; return - bool. True iff str ends with pat.
;;

(defun su:ends-with   (str pat &optional (nocase nil))
    (su:starts-with (su:reverse str) (su:reverse pat) nocase))


;; @doc function su:but-first
;; (su:but-first  (str [n]))
;; Return all but first character of string.
;;
;; str    - string. The string to be processed
;;
;; n      - integer. The number of characters to be skipped. Default: 1
;;
;; return - string. All but the first n characters of str.
;;          If str is NIL or "" return and empty string.
;;          If n > length of str, return ""
;;

(defun su:but-first (str &optional (n 1))
  (cond ((null str) su:*null*)
	((string= str su:*null*) su:*null*)
	((> n (length str)) su:*null*)
	(t (subseq str n))))


;; @doc function  su:but-last 
;; (su:but-last  str [n])
;; Return all but last n characters of string.
;;
;; str    - string. The string to be processed.
;;
;; n      - integer. The number of characters to strip from end. Default: 1
;;
;; return - string   All but the last n characters of str.
;;          If str is NIL or "" return ""
;;          If n > length of str return ""
;;

(defun su:but-last (str &optional (n 1))
  (cond ((null str) su:*null*)
	((string= str su:*null*) su:*null*)
	((> n (length str)) su:*null*)
	(t (subseq str 0 (- (length str) n)))))


;; @doc function  su:-but-last
;; (su:-but-last  str pat [nocase])
;; Conditional version of su:but-last
;;
;; str    - string. The string to be processed.
;;
;; pat    - string. The pattern.
;;
;; nocase - bool. If true the test is case insensitive.
;;
;; return - string. If string str ends with the sub-string pat, strip pat 
;;          from the end of str and return. 
;;          If string str does not end with pat, return str.
;; 

(defun su:-but-last (str pat &optional (nocase NIL))
    (if (su:ends-with str pat nocase)
	(su:but-last str (length pat))
      str))


;; @doc function   su:strcat 
;; (su:strcat [a1 [a2 [a3 ... [an]]]])
;; The su version of strcat. 
;; The standard strcat function may only take string arguments. su:strcat may
;; take any object as an argument. Non-string arguments are converted to their
;; string representation and then concatenated to the result. NIL arguments
;; are converted to an empty string "".
;;
;; a1 a2 a3 ...-  any.  Arbitrary number of arguments to be converted
;;                 to string and concatenated.
;;
;; return - string.
;;

(defun su:strcat  (&rest args)
  (do ((index 0 (+ index 1))(acc su:*null*))
      ((> index (- (length args) 1)) acc)
    (let ((tok (nth index args)))
      (setf tok (if (null tok) su:*null* (format nil "~a" tok)))
      (setf acc (strcat acc tok)))))


;; @doc function   su:quote
;; (su:quote  str  [q])
;; Add quotation characters around string.
;;
;; str    - string.  The string to be quoted.
;;
;; q      -  char.  The quote character. Default #\"
;;
;; return - string
;;

(defun su:quote (str &optional (q #\"))
  (let ((qchr (string-trim " " (->string q))))
    (strcat qchr str qchr)))


;; @doc macro su:cat
;; (su:cat str frmt [args ...])
;; Destructive string concatenation with format.
;; su:cat is an alias for 
;; (setq str (strcat str (format nil frmt args....)))
;; 
;; str    - Symbol. A variable containing a string. The value of str is 
;;          changed as a side effect
;;
;; frmt   - String. The string formating template. See standard XLISP format 
;;          statement.
;;
;; return - String. The new value of str.
;;

(defmacro su:cat (str frmt &rest args)
  `(setq ,str (strcat ,str (format nil ,frmt ,@args))))


Main Page       Index