Jump to content

Find and replace LISP (Regexp) - How to add leading or trailing whitespace to replace?


3dwannab

Recommended Posts

Hi all,

 

I've written a regexp replace lisp that will replace TEXT, MTEXT and MLEADERS.

 

I want to be able to supply a leading and/or trailing whitespace in the command line but I can't seem to find how allow a space in the replace.

 


;; --------------------=={ RegExp_Find_Replace }==------------------------
;; -----------------------------------------------------------------------

;; AUTHOR & ADDITIONAL CODE
;; Author:          by 3dwannab, Copyright © 2018
;; Based of code by fixo  http://www.cadtutor.net/forum/showthread.php?54347-parse-the-string&p=370918&viewfull=1#post370918
;; LM:ssget fn        LeeMac Help pages. www.lee-mac.com.
;;              Thank you Lee. You're an inspiration for what you do.

;; ABOUT / NOTES
;; - Regular expression find and replace routine for TEXT, MTEXT AND MULTILEADER/s.

;; FUNCTION SYNTAX
;; Short-cut        RFR
;; Long-cut         RegExp_Find_Replace

;; VERSION          DATE      INFO
;; Version 1.0      2018.08.19    Unreleased
;; Version 1.1      2024.01.24    Added TEXT and MTEXT with the original MLEADERs'

;; TO DO LIST
;; - OPTION:              All drawing, current space or selection
;; - OPTION:              Add attributes also
;; - QUESTION ON FORUM:   How to add a whitespace in the replace. e.g. 'new word '

;; -----------------------------------------------------------------------
;; ----------------=={ RegExp_Find_Replace START }==----------------------

(defun c:--LDRegExp_Find_Replace (/) (LOAD "3dwannab_RegExp_Find_&_Replace") (c:RegExp_Find_Replace))

(defun c:RFR () (c:RegExp_Find_Replace))

(defun c:RegExp_Find_Replace (/ assocNo elist ent_new i regex regexp_newstr regexp_oldstr result ss1 typ) 

  (defun *error* (errmsg) 
    (and acDoc (vla-EndUndoMark acDoc))
    (and errmsg 
         (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*"))
         (princ (strcat "\n<< Error: " errmsg " >>\n"))
    )
    (setvar 'cmdecho var_cmdecho)
    (setvar 'osmode var_osmode)
    (setvar 'snapmode var_snapmode)
    (setvar 'cursortype var_cursortype)
  )

  (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc))

  (setq var_cmdecho (getvar "cmdecho"))
  (setq var_osmode (getvar "osmode"))
  (setq var_snapmode (getvar "snapmode"))
  (setq var_cursortype (getvar "cursortype"))
  (setvar 'cmdecho 0)
  (setvar 'osmode 0)
  (setvar 'snapmode 0) ;; Grid snap: 0 = OFF, 1 = 0N
  (setvar 'cursortype 1)

  (setq regex (vlax-create-object "Vbscript.RegExp"))
  (vlax-put-property regex "IgnoreCase" 1)
  (vlax-put-property regex "Global" 1)

  ; (SS_Invisible_Cursor)
  (setq regexp_oldstr (getstring T "\n\t\tRegExp Find : "))
  (setq regexp_newstr (getstring T "\n\t\tRegExp Replace   { . = whitespace } : "))

  (if (= regexp_newstr ".") 
    (setq regexp_newstr " ")
  )

  (setvar 'cursortype var_cursortype)
  ; (SS_Invisible_Cursor)

  (if (setq ss1 (LM:ssget "\n\t\tSelect your MULTILEADER/s :\n" (list "_:L" (append '((0 . "MULTILEADER,*TEXT")))))) 

    (progn 
      (repeat (setq i (sslength ss1)) 
        (setq i (1- i))
        (vlax-put-property 
          regex
          "Pattern"
          regexp_oldstr
        )


        ; Set the assoc no. based on entity type
        (setq typ (cdr (assoc 0 (entget (ssname ss1 i)))))
        (cond 
          ((or (= typ "MTEXT") (= typ "TEXT"))
           (setq assocNo 1)
          )
          ((= typ "MLEADER")
           (setq assocNo 340)
          )
        )

        (setq result (vlax-invoke-method 
                       regex
                       "Replace"
                       (cdr (assoc assocNo (entget (ssname ss1 i))))
                       (strcat regexp_newstr)
                     )
        )
        (setq ent_new (cdr (assoc -1 (entget (ssname ss1 i)))))
        (setq elist (entget (ssname ss1 i)))
        (entmod (subst (cons assocNo result) (assoc assocNo elist) elist))
        (entupd ent_new)
      )
    )
  )
  (vlax-release-object regex)
  (*error* nil)
  (princ)
) ;; end RegExp_Find_Replace

  ;; -----------------------------------------------------------------------
  ;; ----------------------=={ Functions START }==--------------------------
(vl-load-com)

  ;; ssget  -  Lee Mac
  ;; A wrapper for the ssget function to permit the use of a custom selection prompt
  ;;
  ;; Arguments:
  ;; msg    - selection prompt
  ;; params - list of ssget arguments
(defun LM:ssget (msg params / sel) 
  (princ msg)
  (setvar 'nomutt 1)
  (setq sel (vl-catch-all-apply 'ssget params))
  (setvar 'nomutt 0)
  (if (not (vl-catch-all-error-p sel)) sel)
)

  ;;----------------------------------------------------------------------;;
  ;; Set cursor invisible
(defun SS_Invisible_Cursor () 

  (setq tm (getvar "tilemode"))
  (setq pref (vla-get-display 
               (vla-get-Preferences 
                 (vlax-get-acad-object)
               )
             )
  )
  (if (zerop tm) 
    (setq cur (vla-get-graphicswinlayoutbackgrndcolor pref))
    (setq cur (vla-get-graphicswinmodelbackgrndcolor pref))
  )

  (vla-put-layoutcrosshaircolor 
    pref
    cur
  )

  (vla-put-modelcrosshaircolor 
    pref
    cur
  )

  (vlax-release-object pref)

  (princ)
)
(princ)

  ;; -----------------------------------------------------------------------
  ;; ---------------------=={ Functions END }==-- --------------------------
(princ "\n: ------------------------------\n\"RegExp_Find_Replace.lsp\" loaded | Version 1.1 by 3dwannab. Type \"RegExp_Find_Replace\" OR \"RFR\" to run.\n: ------------------------------\n")
(princ)

  ;; -----------------------------------------------------------------------
  ;; -----------------=={ RegExp_Find_Replace END }==-----------------------
  ;; EOL

 

Link to comment
Share on other sites

what do you mean by white space?

 

--Edit

If white space is a string variable maybe?

(setq regexp_newstr (getstring T (strcat "\n\t\tRegExp Replace { " whitespace " } : ")))

 

Edited by mhupp
Link to comment
Share on other sites

Thanks @mhupp but I want to be able to find 'xxx' and replace with '     xxxxxx    '.

 

Notice the leading and trailing whitespace characters. They get truncated with my original code when the replacement gets made.

Link to comment
Share on other sites

I might write the function in the following way - by obtaining the text content from the DXF data, non-ASCII characters are retained, but the new content is easier populated using ActiveX:

(defun c:rxfind ( / *error* ent fnd idx new rep rgx sel str )

    (defun *error* ( msg )
        (if (and (= 'vla-object (type rgx)) (not (vlax-object-released-p rgx)))
            (vlax-release-object rgx)
        )
        (if (and msg (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*")))
            (princ (strcat "\nError: " msg))
        )
        (princ)
    )
    
    (cond
        (   (= "" (setq fnd (getstring t "\nSpecify RegEx find pattern <exit>: "))))
        (   (not
                (setq rep (getstring t "\nSpecify RegEx replace pattern <blank>: ")
                      sel (LM:ssget "\nSelect text, mtext or multileaders: " '("_:L" ((0 . "TEXT,MTEXT,MULTILEADER"))))
                )
            )
            (princ "\n*Cancel*")
        )
        (   (or (not (setq rgx (vl-catch-all-apply 'vlax-create-object '("vbscript.regexp"))))
                (vl-catch-all-error-p rgx)
            )
            (princ "\nUnable to interface with Regular Expressions object.")
        )
        (   t
            (vlax-put-property rgx 'pattern fnd)
            (vlax-put-property rgx 'global     actrue)
            (vlax-put-property rgx 'multiline  actrue)
            (vlax-put-property rgx 'ignorecase actrue) ;; Change this to suit

            (repeat (setq idx (sslength sel))
                (setq idx (1- idx)
                      ent (ssname sel idx)
                )
                (if (and (setq str (LM:gettextstring ent))
                         (setq new (vlax-invoke rgx 'replace str rep))
                         (/= str new)
                    )
                    (vla-put-textstring (vlax-ename->vla-object ent) new)
                )
            )
        )
    )
    (*error* nil)
    (princ)
)


;; ssget  -  Lee Mac
;; A wrapper for the ssget function to permit the use of a custom selection prompt
;; msg - [str] selection prompt
;; arg - [lst] list of ssget arguments

(defun LM:ssget ( msg arg / sel )
    (princ msg)
    (setvar 'nomutt 1)
    (setq sel (vl-catch-all-apply 'ssget arg))
    (setvar 'nomutt 0)
    (if (not (vl-catch-all-error-p sel)) sel)
)

;; Get Textstring  -  Lee Mac
;; Returns the text content of Text, MText, Multileaders, Dimensions & Attributes

(defun LM:gettextstring ( ent / enx itm str typ )
    (setq enx (reverse (entget ent))
          typ (cdr (assoc 0 enx))
    )
    (cond
        (   (wcmatch typ "TEXT,*DIMENSION")
            (cdr (assoc 1 enx))
        )
        (   (and (= "MULTILEADER" typ)
                 (= acmtextcontent (cdr (assoc 172 enx)))
            )
            (cdr (assoc 304 (reverse enx)))
        )
        (   (wcmatch typ "ATTRIB,MTEXT")
            (setq str (cdr (assoc 1 enx)))
            (while (setq itm (assoc 3 enx))
                (setq str (strcat (cdr itm) str)
                      enx (cdr (member itm enx))
                )
            )
            str
        )
    )
)

(vl-load-com)
(princ)

 

I'm unsure why you were using "." for whitespace - you can simply enter a space at the getstring prompt.

  • Like 1
Link to comment
Share on other sites

I was using the . as it wouldn't replace with a single space, or at least I couldn't get it to work.

 

Thanks for that Lee. I see that you have attributes in the LM:gettextstring function.

 

Is it difficult to find and replace attributes also?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...