(Fix bug at ;;and CurrentCharacter is a TextDelimiter,) |
(Clarify some variables) |
||
Line 35: | Line 35: | ||
;;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 |
CHARACTERCOUNTER |
||
(1- FIRSTCHARACTERINDEX) |
(1- FIRSTCHARACTERINDEX) |
Revision as of 14:02, 12 August 2008
;;;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. ;;; ] ;;; ) ;| Edit the source code for this function at
http://autocad.wikia.com/wiki/Strtolst
|; ;;;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 an empty string matches the FieldSeparatorWC, ((WCMATCH "" 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) )