AutoCAD
No edit summary
(Added examples for CSV and white space delimited parsing)
 
(12 intermediate revisions by 2 users not shown)
Line 4: Line 4:
 
;;;Usage: (wiki-strtolst
 
;;;Usage: (wiki-strtolst
 
;;; [InputString containing fields]
 
;;; [InputString containing fields]
;;; [FieldSeparatorWC field delimiter wildcard string]
+
;;; [FieldSeparatorWC field delimiter wildcard string
  +
;;; Use "`," for comma and " ,\t" for white space
;;; [TextDelimiter text delimiter character.
 
;;; Use "`," for comma and " ,\t,\n" for white space]
+
;;; ]
 
;;; [TextDelimiter text delimiter character.]
 
;;; [EmptyFieldsDoCount flag.
 
;;; [EmptyFieldsDoCount flag.
 
;;; If nil, consecutive field delimiters are ignored.
 
;;; If nil, consecutive field delimiters are ignored.
Line 12: Line 13:
 
;;; ]
 
;;; ]
 
;;; )
 
;;; )
  +
;;; Examples:
  +
;;; CSV (wiki-strtolst string "`," "\"" T)
  +
;;; Word delimited (wiki-strtolst string " ,\t,\n" "" nil)
  +
;;; Revision history
  +
;;; 2009-01-17 TGH Replaced test for empty fieldseparatorwc with a simple '= function
 
;|
 
;|
Edit the source code for this function at </pre>
+
Edit the source code for this function at </pre>
[[strtolst (AutoLISP function)]]
+
[[strtolst (AutoLISP function)|http://autocad.wikia.com/wiki/Strtolst_(AutoLISP_function)]]
 
<pre>
 
<pre>
 
|;
 
|;
Line 23: Line 29:
 
;;;And I am trying a new commenting style.
 
;;;And I am trying a new commenting style.
 
;;;Tests
 
;;;Tests
;;;(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n----\n" x)) (wiki-strtolst "1 John,\"2 2\"\" pipe,\nheated\",3 the end,,,,," "," "\"" nil))))
+
;;;(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n----\n" x)) (wiki-strtolst "1 John,\"2 2\"\" pipe,\nheated\",3 the end,,,,," "`," "\"" nil))))
;;;(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n----\n" x)) (wiki-strtolst "1 John,\"2 2\"\" pipe,\nheated\",3 the end,,,,," "," "\"" T))))
+
;;;(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n----\n" x)) (wiki-strtolst "1 John,\"2 2\"\" pipe,\nheated\",3 the end,,,,," "`," "\"" T))))
 
(DEFUN
 
(DEFUN
 
WIKI-STRTOLST (INPUTSTRING FIELDSEPARATORWC TEXTDELIMITER
 
WIKI-STRTOLST (INPUTSTRING FIELDSEPARATORWC TEXTDELIMITER
 
EMPTYFIELDSDOCOUNT / CHARACTERCOUNTER CONVERSIONISDONE
 
EMPTYFIELDSDOCOUNT / CHARACTERCOUNTER CONVERSIONISDONE
CURRENTCHARACTER CURRENTFIELD CURRENTFIELDISDONE FIRSTCHARACTERINDEX
+
CURRENTCHARACTER CURRENTFIELD CURRENTFIELDISDONE
PREVIOUSCHARACTER RETURNLIST TEXTMODEISON
+
FIRSTCHARACTERINDEX PREVIOUSCHARACTER RETURNLIST
  +
TEXTMODEISON
 
)
 
)
 
;;Initialize the variables for clarity's sake
 
;;Initialize the variables for clarity's sake
 
(SETQ
 
(SETQ
  +
;;For the AutoLISP (substr string index length) function, the first character index is 1
 
FIRSTCHARACTERINDEX 1
 
FIRSTCHARACTERINDEX 1
  +
;;We start the character counter one before the beginning
CHARACTERCOUNTER (1- FIRSTCHARACTERINDEX)
 
  +
CHARACTERCOUNTER
 
(1- FIRSTCHARACTERINDEX)
 
PREVIOUSCHARACTER ""
 
PREVIOUSCHARACTER ""
 
CURRENTCHARACTER ""
 
CURRENTCHARACTER ""
Line 45: Line 55:
 
;;Make sure that the FieldSeparatorWC is not empty.
 
;;Make sure that the FieldSeparatorWC is not empty.
 
(COND
 
(COND
;;If an empty string matches the FieldSeparatorWC,
+
;;If the FieldSeparatorWC is an empty string,
((WCMATCH "" FIELDSEPARATORWC)
+
((= FIELDSEPARATORWC "")
 
;;Then
 
;;Then
 
;;1. Give an alert about the problem.
 
;;1. Give an alert about the problem.
Line 79: Line 89:
 
;;Decide what to do with CurrentCharacter.
 
;;Decide what to do with CurrentCharacter.
 
(COND
 
(COND
  +
;;If
;;If CurrentCharacter is a TextDelimiter, then
 
  +
((AND
((= CURRENTCHARACTER TEXTDELIMITER)
 
  +
;;there is a TextDelimiter,
  +
(/= TEXTDELIMITER "")
 
;;and CurrentCharacter is a TextDelimiter,
 
(= CURRENTCHARACTER TEXTDELIMITER)
  +
)
  +
;;then
 
;;1. Toggle the TextModeIsOn flag
 
;;1. Toggle the TextModeIsOn flag
 
(IF (NOT TEXTMODEISON)
 
(IF (NOT TEXTMODEISON)
Line 131: Line 147:
 
(NOT (WCMATCH PREVIOUSCHARACTER FIELDSEPARATORWC))
 
(NOT (WCMATCH PREVIOUSCHARACTER FIELDSEPARATORWC))
 
;;the ReturnList is still nil due to only empty non-counting fields in string,
 
;;the ReturnList is still nil due to only empty non-counting fields in string,
;;(This check is a bug fix added 2008-02-18 TGH)
+
;;(Added 2008-02-18 TGH. Bug fix.)
 
(= RETURNLIST NIL)
 
(= RETURNLIST NIL)
 
)
 
)
Line 161: Line 177:
 
;;Reverse the backwards return list and we are done.
 
;;Reverse the backwards return list and we are done.
 
(REVERSE RETURNLIST)
 
(REVERSE RETURNLIST)
 
)</pre>
)
 
;|«Visual LISP© Format Options»
 
(72 2 40 2 nil "end of " 60 2 2 2 1 nil nil nil T)
 
;*** DO NOT add text below the comment! ***|;
 
</pre>
 
 
{{AutoLISPfooter}}
 
{{AutoLISPfooter}}
 
<noinclude>[[Category:AutoLISP function]]</noinclude>
 
<noinclude>[[Category:AutoLISP function]]</noinclude>

Latest revision as of 22:42, 1 February 2009

;;;WIKI-STRTOLST
;;;Parses a string into a list of fields.
;;;Usage: (wiki-strtolst
;;;         [InputString containing fields]
;;;         [FieldSeparatorWC field delimiter wildcard string
;;;          Use "`," for comma and " ,\t" for white space
;;;         ]
;;;         [TextDelimiter text delimiter character.]
;;;         [EmptyFieldsDoCount flag.
;;;           If nil, consecutive field delimiters are ignored.
;;;           Nil is good for word (white space) delimited strings.
;;;         ]
;;;       )
;;; Examples:
;;; CSV            (wiki-strtolst string "`," "\"" T)
;;; Word delimited (wiki-strtolst string " ,\t,\n" "" nil)
;;; Revision history
;;; 2009-01-17 TGH     Replaced test for empty fieldseparatorwc with a simple '= function
;|
   Edit the source code for this function at 
  http://autocad.wikia.com/wiki/Strtolst_(AutoLISP_function)
|;
;;;Avoid cleverness.
;;;Human readability trumps elegance and economy and cleverness here.
;;;This should be readable to a programmer familiar with any language.
;;;In this function, I'm trying to honor readability in a new (2008) way.
;;;And I am trying a new commenting style.
;;;Tests
;;;(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n----\n" x)) (wiki-strtolst "1 John,\"2 2\"\" pipe,\nheated\",3 the end,,,,," "`," "\"" nil))))
;;;(alert (apply 'strcat (mapcar '(lambda (x) (strcat "\n----\n" x)) (wiki-strtolst "1 John,\"2 2\"\" pipe,\nheated\",3 the end,,,,," "`," "\"" T))))
(DEFUN
   WIKI-STRTOLST (INPUTSTRING FIELDSEPARATORWC TEXTDELIMITER
                  EMPTYFIELDSDOCOUNT / CHARACTERCOUNTER CONVERSIONISDONE
                  CURRENTCHARACTER CURRENTFIELD CURRENTFIELDISDONE
                  FIRSTCHARACTERINDEX PREVIOUSCHARACTER RETURNLIST
                  TEXTMODEISON
                 )
  ;;Initialize the variables for clarity's sake
  (SETQ
    ;;For the AutoLISP (substr string index length) function, the first character index is 1
    FIRSTCHARACTERINDEX 1
    ;;We start the character counter one before the beginning
    CHARACTERCOUNTER
     (1- FIRSTCHARACTERINDEX)
    PREVIOUSCHARACTER ""
    CURRENTCHARACTER ""
    CURRENTFIELD ""
    CURRENTFIELDISDONE NIL
    TEXTMODEISON NIL
    CONVERSIONISDONE NIL
    RETURNLIST NIL
  )
  ;;Make sure that the FieldSeparatorWC is not empty.
  (COND
    ;;If the FieldSeparatorWC is an empty string,
    ((= FIELDSEPARATORWC "")
     ;;Then
     ;;1. Give an alert about the problem.
     (ALERT
       ;;Include princ to allow user to see and copy error
       ;;after dismissing alert box.
       (PRINC
         (STRCAT
           "\n\""
           FIELDSEPARATORWC
           "\" is not a valid field delimiter."
         )
       )
     )
     ;;2. Exit with error.
     (EXIT)
    )
  )
  ;;Start the main character-by-character InputString examination loop.
  (WHILE (NOT CONVERSIONISDONE)
    (SETQ
      ;;Save CurrentCharacter as PreviousCharacter.
      PREVIOUSCHARACTER
       CURRENTCHARACTER
      ;;CharacterCounter is initialized above to start 1 before first character.  Increment it.
      CHARACTERCOUNTER
       (1+ CHARACTERCOUNTER)
      ;;Get new CurrentCharacter from InputString.
      CURRENTCHARACTER
       (SUBSTR INPUTSTRING CHARACTERCOUNTER 1)
    )
    ;;Decide what to do with CurrentCharacter.
    (COND
      ;;If
      ((AND
         ;;there is a TextDelimiter,
         (/= TEXTDELIMITER "")
         ;;and CurrentCharacter is a TextDelimiter,
         (= CURRENTCHARACTER TEXTDELIMITER)
       )
       ;;then
       ;;1.  Toggle the TextModeIsOn flag
       (IF (NOT TEXTMODEISON)
         (SETQ TEXTMODEISON T)
         (SETQ TEXTMODEISON NIL)
       )
       ;;2.  If this is the second consecutive TextDelimiter character, then
       (IF (= PREVIOUSCHARACTER TEXTDELIMITER)
         ;;Output it to CurrentField.
         (SETQ CURRENTFIELD (STRCAT CURRENTFIELD CURRENTCHARACTER))
       )
      )
      ;;Else if CurrentCharacter is a FieldDelimiter wildcard match,
      ((WCMATCH CURRENTCHARACTER FIELDSEPARATORWC)
       ;;Then
       (COND
         ;;If TextModeIsOn = True, then 
         ((= TEXTMODEISON T)
          ;;Output CurrentCharacter to CurrentField.
          (SETQ CURRENTFIELD (STRCAT CURRENTFIELD CURRENTCHARACTER))
         )
         ;;Else if
         ((OR ;;EmptyFieldsDoCount, or
              (= EMPTYFIELDSDOCOUNT T)
              ;;the CurrentField isn't empty,
              (/= "" CURRENTFIELD)
          )
          ;;Then
          ;;Set the CurrentFieldIsDone flag to true.
          (SETQ CURRENTFIELDISDONE T)
         )
         (T
          ;;Else do nothing
          ;;Do not flag the CurrentFieldDone,
          ;;nor output the CurrentCharacter.
          NIL
         )
       )
      )
      ;;Else if CurrentCharacter is empty,
      ((= CURRENTCHARACTER "")
       ;;Then
       ;;We are at the end of the string.
       ;;1.  Flag ConversionIsDone.
       (SETQ CONVERSIONISDONE T)
       ;;2.  If
       (IF (OR ;;EmptyFieldsDoCount, or
               EMPTYFIELDSDOCOUNT
               ;;the PreviousCharacter wasn't a FieldSeparatorWC, or
               (NOT (WCMATCH PREVIOUSCHARACTER FIELDSEPARATORWC))
               ;;the ReturnList is still nil due to only empty non-counting fields in string,
               ;;(Added 2008-02-18 TGH. Bug fix.)
               (= RETURNLIST NIL)
           )
         ;;Then flag the CurrentFieldIsDone to wrap up the last field.
         (SETQ CURRENTFIELDISDONE T)
       )
      )
      ;;Else (CurrentCharacter is something else),
      (T
       ;;Output CurrentCharacter to CurrentField.
       (SETQ CURRENTFIELD (STRCAT CURRENTFIELD CURRENTCHARACTER))
      )
    )
    ;;If CurrentFieldIsDone,
    (IF CURRENTFIELDISDONE
      ;;Then
      ;;Output it to the front of ReturnList.
      (SETQ
        RETURNLIST
         (CONS CURRENTFIELD RETURNLIST)
        ;;Start a new CurrentField.
        CURRENTFIELD
         ""
        CURRENTFIELDISDONE NIL
      )
    )
    ;;End the main character-by-character InputString examination loop.
  )
  ;;Reverse the backwards return list and we are done.
  (REVERSE RETURNLIST)
)