Author Topic: [Solved] Text translator  (Read 6380 times)

0 Members and 1 Guest are viewing this topic.

zibidi

  • Guest
Re: [Bug] Text translator
« Reply #15 on: July 18, 2007, 06:12:53 PM »
I am getting close to the correct code.

I have a few questions:

1) How do I break a while loop?

2) how can I easily prevent the user from inputing nothing when prompted for the new text to translate to? I tried (initget 1) but it didn't work.

3) I ma having troubles writing to the lookup file from autocad. I don't understand if it always prepends a newline character when writing to the end of the lookup file. Sometimes it does sometimes it doesn't.

4) I also think I have a problem when the text has parenthesis. If a text on drawing has a parenthesis and autocad needs to create a new entry in the lookup file, then it crashes. The text on the drawing gets updated, when when it writes to the file it crashes.

EDIT: I was right concerning the parenthesis, autocad cannot write a line to a file if it has a parenthesis, but it can ready from it. How to overcome that? Do I need to escape the parenthesis character?

EDIT2: actually no. I don't understand what's happening. I have removed the parenthesis, and it still crashes even on simple text with no parenthesis. It looks like if the script chrashes once, it's doomed, womething wrong must be written to the lookup file, and the file gets corrupted.

Here is the latest code:
Code: [Select]
(defun C:PT (/ )

;newlines are marked as \P in autocad text.

(setq path2file (findfile "ProTranslator.dat")) ;path to the data file

(setq listOfText (ssget "_X" '((0 . "*TEXT")))) ;fetch all the text entities on the drawing

;(alert (itoa (sslength listofText)))
;To display a number in alert box, you have to first make it into a string.

(setq pointer 0);that's the pointer inside the listOfText. Lists begin with an index of 0

(repeat (setq n (sslength listOfText))
;count how many text entities have been found, and loop n times
;because of the way we move in our list, we need to redefine n each time we loop

(setq fileData (open path2file "r")) ;open the data file and assign it to fileData

(setq textEntity (entget (ssname listOfText pointer)))
;retrieve the text entity so that we can modify its text attribute using entmod

(setq textEntityContent (cdr (assoc 1 textEntity)));select the text content from the
;text entity
;strcase converts the string into HIGHCAPS so we will be able to still match capitalization
;typos.

(setq matchFound "false") ;this variable is used to detect text entities that have no
;entry in the lookup file and that need one.

(while (setq oneLine (read-line fileData)) ;we loop through each line of the file

;that small block of code is dirty, but it is to overcome a bug when autocad writes
;a new line in the lookup file. There is a problem when it creates a new line
(if (= oneLine "")
(setq oneLine (read-line fileData))
);

(setq listed (read (strcat "(" oneLine ")")));here is a nice trick. Each line in the
;lookup file has the data written between double quotes. We want to turn a line into
;a list of two members with the first member being the textToLookFor and the second
;member being the newText that will update theTextToLookFor.

(setq textToLookFor (car listed))
(setq newText (nth 1 listed));nth 1 is the equivalent of cadr.

(if (= textToLookFor textEntityContent);look for a string match
(progn ;always use a progn after an if. ALWAYS!!!
(entmod (subst (cons 1 newText) (assoc 1 textEntity) textEntity))
;update the text content with the usual entmod+subst combo
;Note that here (cons 1 newText) is mandatory, as '(1 . newText) doesn't work.
(setq matchFound "true")
);end of progn
);end of the if that looks for a string match

;The following if block, is used when the script is launched for more than once
;it looks for a match in the translated text, otherwise it would try to translate
;text that has already been translated.
(if (= textEntityContent newText)
(progn
(setq matchFound "true")
);end of progn
);end of the if that looks for a string match



);end of the while loop that goes through each line of the file

(close fileData); close the file after reaching the end otherwise the next while
;will not loop through the file again
;The file must be closed and reopened as append for adding data. Opening the file
;in first place as append doesn't allow to read lines from it.

(if (= matchFound "false")
(progn ;progn is used to evalutate more than one expression with an if block
(princ (strcat "\nThe text: " textEntityContent))
(princ (strcat "\nhas no entry in the lookup file!"))

(setq textToAppend (getstring T "\nEnter the new text to replace with: "))
;prompt user for the name of the text that will act as a replacement.

(entmod (subst (cons 1 textToAppend) (assoc 1 textEntity) textEntity));Replace text

(setq addLine (strcat "\n"" textEntityContent "\" " "\"" textToAppend "\""))
;we need to create the new that will be appended to the lookup file

(setq fileData (open path2file "a"))
(write-line addLine fileData) ;append the new line to the end of fileData
(close fileData)

);end of progn
);end of the if when matchFound is "false"

(setq pointer (1+ pointer));increment the pointer
); end of the repeat loop

(princ "\nProTranslator has finished.")
(princ)
) ;end of defun



EDIT3:
Once again complete nonsense, I haven't touched my code and it refuses to work on a file on which it used to work. I don't know what's happening, it seems that the lookup file gets messed up.


EDIT4; it's getting ridiculous!!!

I have commented tout the portion of code that writes to the file, and replaced it with an alert box. Guess what! The text gets updated, autocad prompts me for a new entry, does all the text, and never shows the alert box although it should appear!!!  :ugly:  :pissed:  :realmad:
« Last Edit: July 18, 2007, 07:13:10 PM by zibidi »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: [Bug] Text translator
« Reply #16 on: July 18, 2007, 07:17:36 PM »
How is the text in you look up file done?  You may want to separate them with a character that you will most likely never use.  This will help you so you can easily list the items.

We will take this step by step.  The first step is getting the information from your look up file in to Acad in a usable fashion.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

zibidi

  • Guest
Re: [Bug] Text translator
« Reply #17 on: July 19, 2007, 05:58:57 AM »
Here is how the lookup file is layed out:
Quote
"vis" "screw"
"plaque" "plate"
I use double quotes to separate each member on a line.

We could use the pipe character (i.e: "|" ) to separate each element. Or if autolisp supports regular expressions, I could use something like ">>>" the heredoc style  :-)

T.Willey

  • Needs a day job
  • Posts: 5251
Re: [Bug] Text translator
« Reply #18 on: July 19, 2007, 10:56:08 AM »
Here is how the lookup file is layed out:
Quote
"vis" "screw"
"plaque" "plate"
I use double quotes to separate each member on a line.

We could use the pipe character (i.e: "|" ) to separate each element. Or if autolisp supports regular expressions, I could use something like ">>>" the heredoc style  :-)
I would use either or.  Then it would be easier to make an associated list (like the dxf code list) so we can find the old text easier, and the next text will be right there when we do.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

daron

  • Guest
Re: [Bug] Text translator
« Reply #19 on: July 19, 2007, 12:24:37 PM »
>>1) How do I break a while loop?

The best way that I know is to make sure that your test condition is transmutable and can have an escape clause, i.e.
Code: [Select]
(setq input t)
(while input
(test some code here)
(here...)
(if {test complete}
(setq input nil)
)
)

zibidi

  • Guest
Re: [Bug] Text translator
« Reply #20 on: July 19, 2007, 01:26:34 PM »
Thanks daron. I thought there was a "break" command to break any loop in which you are...


Anyway, my code is now functional, I had to modify the way data was written to the file. Instead of using the write-line function which sometimes adds a new line before writing and sometimes doesn't (I didn't understand how it worked), I used a print+prin1 combo.

Code: [Select]
(defun C:PT (/ )

;newlines are marked as \P in autocad text.

(setq path2file (findfile "ProTranslator.dat")) ;path to the data file

(setq listOfText (ssget "_X" '((0 . "*TEXT")))) ;fetch all the text entities on the drawing

;(alert (itoa (sslength listofText)))
;To display a number in alert box, you have to first make it into a string.

(setq pointer 0);that's the pointer inside the listOfText. Lists begin with an index of 0

(repeat (setq n (sslength listOfText))
;count how many text entities have been found, and loop n times
;because of the way we move in our list, we need to redefine n each time we loop

(setq fileData (open path2file "r")) ;open the data file and assign it to fileData

(setq textEntity (entget (ssname listOfText pointer)))
;retrieve the text entity so that we can modify its text attribute using entmod

(setq textEntityContent (cdr (assoc 1 textEntity)));select the text content from the
;text entity
;strcase converts the string into HIGHCAPS so we will be able to still match capitalization
;typos.

(setq matchFound "false") ;this variable is used to detect text entities that have no
;entry in the lookup file and that need one.

(while (setq oneLine (read-line fileData)) ;we loop through each line of the file

(setq listed (read (strcat "(" oneLine ")")));here is a nice trick. Each line in the
;lookup file has the data written between double quotes. We want to turn a line into
;a list of two members with the first member being the textToLookFor and the second
;member being the newText that will update theTextToLookFor.

(setq textToLookFor (car listed))
(setq newText (nth 1 listed));nth 1 is the equivalent of cadr.

(if (= textToLookFor textEntityContent);look for a string match
(progn ;always use a progn after an if. ALWAYS!!!
(entmod (subst (cons 1 newText) (assoc 1 textEntity) textEntity))
;update the text content with the usual entmod+subst combo
;Note that here (cons 1 newText) is mandatory, as '(1 . newText) doesn't work.
(setq matchFound "true")
);end of progn
);end of the if that looks for a string match

;The following if block, is used when the script is launched more than once.
;It looks for a match in the translated text, otherwise it would try to translate
;text that has already been translated.
(if (= textEntityContent newText)
(progn
(setq matchFound "true")
);end of progn
);end of the if that looks for a string match



);end of the while loop that goes through each line of the file

(close fileData); close the file after reaching the end otherwise the next while
;will not loop through the file again
;The file must be closed and reopened as append for adding data. Opening the file
;in first place as append doesn't allow to read lines from it.

(if (= matchFound "false")
(progn ;progn is used to evalutate more than one expression with an if block
(princ (strcat "\nThe text: " textEntityContent))
(princ "\nhas no entry in the lookup file!")
(princ "\n------------------------------------------------------")
(princ "\nTo add a new line type \\\P in your text")

(setq textToAppend (getstring T "\nEnter the new text to replace with: "))
;prompt user for the name of the text that will act as a replacement.

(entmod (subst (cons 1 textToAppend) (assoc 1 textEntity) textEntity));Replace text

(setq fileData (open path2file "a"));open file for append. You cannot open it
;for append in the first instance, because you couldn't read from it.

(print textEntityContent fileData); prints data in double quotes and preceded
;by a newline
(prin1 textToAppend fileData);prints data in double quotes on the same line as
;the previous expression

;(setq lineToAppend (strcat "\n"" textEntityContent "\" " "\"" textToAppend "\""))
;we need to create the new that will be appended to the lookup file
;(write-line addLine fileData) ;append the new line to the end of fileData
;the write-line method made me run in troubles, there was a problem with newlines
;being added or not, so use the print+prin1 combo instead

(close fileData)

);end of progn
);end of the if when matchFound is "false"

(setq pointer (1+ pointer));increment the pointer
); end of the repeat loop

(princ "\nProTranslator has finished.")
(princ)
) ;end of defun
The first time the script is launched, you must have at least one line of data in the lookup file.

Now if someone wants to add the ability to update text that is in a dimension, a block or an annotation, he is more than welcomed to participate  :-)

By the way, the approach I have taken might be annoying, because the program will prompt for any new piece of text that isn't in the lookup file. So if there is text that doesn't need to be translated you have to retype it at the prompt. I don't know if it is a good idea, only time will tell.

Maybe I should add the ability to type a new entry in the lookup file, and then propose to launch the translator without prompting. I'll see.

EDIT: I should first propose if the new text needs to be put in the lookup file, and if Yes, then type the text to save.



EDIT: that's getting crazy!!!! The code broke again! I just relaunched the script in a drawing on which it just worked, and it crashed. I only modified a line in the lookup file because it had detected an empty text and I thought it didn't accept it.  :realmad: :pissed:

EDIT: false error. I tried to break a loop like daron said, and that's what was crashing, I must have mistyped something.
« Last Edit: July 19, 2007, 01:44:18 PM by zibidi »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: [Solved] Text translator
« Reply #21 on: July 19, 2007, 01:42:11 PM »
You may want to make your variables local.  Sometimes that causes problems.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

zibidi

  • Guest
Re: [Solved] Text translator
« Reply #22 on: July 19, 2007, 01:45:26 PM »
What are local variables in autolisp by the way?

On the previous page, I made a variable as local and that created a problem, so that's why I was staying away from them.

i think for now, I will stop fiddling with the code and use it as it is now. As time passes if I need to make adjustments, I will, but for now I should first play a bit with it and see how it performs.


EDIT: does autolisp has some support of regular expressions? I searched in the forum but it doesn't seem to. I once heard that express tools can add this ability, is it true?
« Last Edit: July 19, 2007, 01:48:55 PM by zibidi »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: [Solved] Text translator
« Reply #23 on: July 19, 2007, 01:57:38 PM »
To make a variable local, instead of
Code: [Select]
(defun c:Example ()

(setq test "Test string.")
(prompt test)
(princ)
)
do this
Code: [Select]
(defun c:Examplev02 (/ test2)

(setq test2 "Test string v02.")
(prompt test2)
(princ)
)

If you load these two samples, and run them both they will print to the command line the string that is assigned to the variable test.  But after running the first one, type '!test' to the command line (no quotes) and see what is returned.  Then run the second one, and type '!test2' after.  Notice the difference.

Concerning regular expressions, I have no idea, as I have never used them.  You might be able to, but I have never tried.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.