// STRNFILT.VDM - Delete all strings (perhaps multi line) in the current // file that match or don't match a search string. // It's like a search and deletion of unwanted strings. // // You can use pattern matching or regular expressions // in the search. // // Written by: Christian Ziemski (based on my own LINEFILT.VDM) // Last change: 21-Apr-2004 (still beta) // // Requires: VEDIT 6.10 or later. // // Usage: ... // //----------------------------------------------------------------------- // Used registers (they are saved and restored): // -------------------------------------------- // #85 flag for first run // #86 position for the dialog // #87 temp. used // #88 saved value for BlockBegin // #89 - // #90 DI1() return value // #91 DI1() () with or without searchstring // #92 DI1() [] start at begin of block/file // #93 DI1() [] block // #94 DI1() [] case sensitivity // #95 DI1() () pattern or regexp search // #96 options for Search() // #97 variable begin of search area // #98 begin of search area // #99 end of search area // // $89 DI1() default title string // $90 DI1() current title string (e.g.) error message // $91 user's frame string (begin) // $92 user's search string // $93 user's frame string (end) // $94 temp. string delimiter and then the correct delimited frame string (begin) // $95 temp. string delimiter and then the correct delimited search string // $96 temp. string delimiter and then the correct delimited frame string (end) // $97 DI1() .b flag // $98 DI1() .b flag // // Used Markers: 8,9 (not restored) // //------------------------------------------------------------------------ // To do: // more testing, esp. with marked block // restore used markers // //======================================================================== Num_Push(85,99) // save the used registers Reg_Push(89,99) // set some defaults for the Dialog box #86=CENTER // center the dialog in the workarea // #86=RIGHT+BOTTOM // or put it to bottom-right? #91=1 // delete lines -with- search string #92=0 // start at cursor #93=0 // no block if (BB != -1 || BE != -1) { // if at least one blockmarker is set #92=1 // preset "start at begin of block/file" #93=1 // preset "Block" } #94=0 // no case sensitivity #95=1 // use pattern matching #97=0 // used for search function #85=1 // first run flag Reg_Set(89, "String-Filter - Delete matching / non-matching strings") // DI1() default title string Reg_Set(97, ".b") // set initial focus on [OK+STAY] button Reg_Empty(98) Reg_Set(90, @89) // set DI1() title string with default title Undo_Reset() // ======== main loop repeat(ALL) { Update Reg_Set(104, @91) // for checking of modification below Reg_Set(105, @92) Reg_Set(106, @93) #103=#94 #104=#95 //? M("1") .#92 #93 #90=Dialog_Input_1(91,^`|@(90)`, `Delete all (even multi-line) "frame" strings in the current file that contain or don't contain a search string. (Note: Since this function can delete much text, use it with care!) `,`Delete all strings `, `.h()-with- or`, `.h()-without- the search string`, `.g[]From beginning of file (or block); else from cursor`, `[]Only within the (initially) highlighted block`, `[]Case sensitive`, `Search with`, `.h()pattern matching or`, `.h()regular expressions`, `??Begin of frame string `, `??Search s&tring `, `??End of frame string `, ``, `\[Ok] deletes the strings and returns\n[Ok + Stay] deletes the strings and stays in this dialog\n[Search] only searches matching strings, does not delete anything`, `[&Ok]`, `|@(97)[O&k + Stay]`, `|@(98)[&Search]`, `[&Undo]`, `[&Done]`^, SET+WORKAREA+#86,0,0) //? M("2") .#92 #93 // === [Done] or if (#90 == 0 || #90 > 4) { Goto END } if (#85) { // if first run // evaluate/fix the begin and end of search area #98=Cur_Pos // Default: begin search at current cursor position if (#92) { // if [x]Begin at block/file is checked #98=0 // search from BoF on } #99=File_Size // to EoF if (#93) { // if [x]Block is checked if (BB == -1 && BE == -1) { // but if no blockmarker is set Reg_Set(90, "Blockmode was activated but no marker set!") #93=0 // uncheck []Block Continue // and do nothing more } if (BB == -1) { BB(Cur_Pos) } // if no BB: set it to current cursor position if (BE == -1) { BE(File_Size) } // if no BE: set it to end-of-file if (BB > BE) { // if reverse marked block: #103=BB // switch the markers BB(BE) BE(#103) } #98=BB // let the search begin at BB per default if (#92 == 0) { // if []Begin at block/file is not checked if (Cur_Pos >= BB && Cur_Pos <= BE) { // if cursor within the block #98=Cur_Pos // let the search begin at cursor position } } #99=BE #92=#92|0x80 // grey out [] From beginning of file (or block) #93=#93|0x80 // grey out [] block Set_Marker(8, BB) // save initial BB and BE Set_Marker(9, BE) } } else { // not first run if ((Reg_Compare(104, @91) != 0) || (Reg_Compare(105, @92) != 0) || (Reg_Compare(106, @93) != 0)) { // if a string changed #97 = Cur_Pos // only set variable begin with cursor position } if ((#103 != #94) || (#104 != #95)) { // if search options changed #97 = Cur_Pos // only set variable begin with cursor position } // Fix for DI_1() bug: the high bits are reset!?!?!?? if (#93) { #92=#92|0x80 // grey out [] From beginning of file (or block) #93=#93|0x80 // grey out [] block } } #85=0 // reset first run flag #96=CASE*#94 + REGEXP*(#95==2) + NOERR // set the search options //? M("3") .#92 #93 // === [Undo] if (#90 == 4) { Undo_Edit(1) // Undo changes as good as possible if (#93) { // if in block mode: BB(#98) // set BB to begin of search area again } #97=0 // reset variable search begin Continue } if (#90 == 3) { // if [Search]: set focus on this button Reg_Empty(97) Reg_Set(98, ".b") } // clean error message Reg_Set(90, @89) // set DI1() title string with default title // Prepare the user's frame string (begin) from $91 for later use in $94 if (Reg_Size(91) == 0) { // if missing begin-string return to dialog Reg_Set(90, "ERROR: missing begin of frame string!") Continue } else { // try to find a string delimiter not included in the user's input #103=Buf_Num Buf_Switch(Buf_Free(EXTRA)) Reg_Ins(91) // the original search string - begin BoF Ins_Text(.`'´"%&*,:;/~^=., BEGIN) // and all possible delimiters (without the dot ".", which is used here internally) for (#87=0; #87<14 ; #87++) { // loop through all the possible delimiters Goto_Pos(#87) Reg_Copy_Block(94, Cur_Pos, CP+1) // get this possible delimiter Char(1) // advance past it Search(.|@(94)., NOERR) // search for it in the rest of the string if (EM) { // if not found: good Goto_Pos(#87+1) // delete the rest of the possible ones Del_Char(14-#87-1) Del_Block(0, #87) EoF Reg_Ins(94) // and add the found delimiter at end too break // leave the loop } } Reg_Copy_Block(94, 0, File_Size) // copy the search string with correct delimiters to $94 Buf_Quit(OK) Buf_Switch(#103) if (#87 == 14) { // if no delimiter found Dialog_Input_1(1,"`Error`, `There are no more string delimiters possible for internal use.\nAll of them are used in your string.`, `Please change your frame string (begin) a bit!`", WORKAREA+CENTER,0,0) Continue } } // Prepare the user's frame string (end) from $93 for later use in $96 if (Reg_Size(93)== 0) { // if missing search string begin/end return to dialog Reg_Set(90, "ERROR: missing end of frame string!") Continue } else { // try to find a string delimiter not included in the user's input #103=Buf_Num Buf_Switch(Buf_Free(EXTRA)) Reg_Ins(93) // the original search string - end BoF Ins_Text(.`'´"%&*,:;/~^=., BEGIN) // and all possible delimiters (without the dot ".", which is used here internally) for (#87=0; #87<14 ; #87++) { // loop through all the possible delimiters Goto_Pos(#87) Reg_Copy_Block(96, Cur_Pos, CP+1) // get this possible delimiter Char(1) // advance past it Search(.|@(96)., NOERR) // search for it in the rest of the string if (EM) { // if not found: good Goto_Pos(#87+1) // delete the rest of the possible ones Del_Char(14-#87-1) Del_Block(0, #87) EoF Reg_Ins(96) // and add the found delimiter at end too break // leave the loop } } Reg_Copy_Block(96, 0, File_Size) // copy the search string with correct delimiters to $95 Buf_Quit(OK) Buf_Switch(#103) if (#87 == 14) { // if no delimiter found Dialog_Input_1(1,"`Error`, `There are no more string delimiters possible for internal use.\nAll of them are used in your string.`, `Please change your frame string (end) a bit!`", WORKAREA+CENTER,0,0) Continue } } // Prepare the user's search string from $92 for later use in $95 // try to find a string delimiter not included in the user's input #103=Buf_Num Buf_Switch(Buf_Free(EXTRA)) Reg_Ins(92, BEGIN) // the original search string Ins_Text(.`'´"%&*,:;/~^=., BEGIN) // and all possible delimiters (without the dot ".", which is used here internally) for (#87=0; #87<14 ; #87++) { // loop through all the possible delimiters Goto_Pos(#87) Reg_Copy_Block(95, Cur_Pos, CP+1) // get this possible delimiter Char(1) // advance past it Search(.|@(95)., NOERR) // search for it in the rest of the string if (EM) { // if not found: good Goto_Pos(#87+1) // delete the rest of the possible ones Del_Char(14-#87-1) Del_Block(0, #87) EoF Reg_Ins(95) // and add the found delimiter at end too break // leave the loop } } Reg_Copy_Block(95, 0, File_Size) // copy the search string with correct delimiters to $94 Buf_Quit(OK) Buf_Switch(#103) if (#87 == 14) { // if no delimiter found Dialog_Input_1(1,"`Error`, `There are no more string delimiters possible for internal use.\nAll of them are used in your string.`, `Please change your search string a bit!`", WORKAREA+CENTER,0,0) Continue } // === [Search] if (#90 == 3) { Reg_Empty(97) // switch focus to [Search] button Reg_Set(98, ".b") BB(CLEAR) // search begin of frame string Reg_Set(101, 'Search_Block(') Reg_Set(101, @94, APPEND) Reg_Set(101, ', Max(#98,#97), #99, #96+BEGIN)', APPEND) Call(101) if (EM) { // if begin of frame string not found: goto end of search area Reg_Set(90, "No frame string found!") Goto_Pos(#99) #97=0 Continue } #103=CP // remember position of begin of frame string #104=CP+Chars_Matched // remember position after begin of frame string BB(CLEAR) // search end of frame string Reg_Set(101, 'Search_Block(') Reg_Set(101, @96, APPEND) Reg_Set(101, ', #104, #99, #96+BEGIN)', APPEND) Call(101) #105=CP // remember pos of begin of end frame string #106=CP+Chars_Matched // remember pos after frame string if (! EM) { // if frame found: search string within frame if (Reg_Size(95) > 2) { // if a search string given Reg_Set(101, 'Search_Block(') // search for it within frame string Reg_Set(101, @95, APPEND) Reg_Set(101, ', ', APPEND) Reg_Set(101, '#104, #105, #96+BEGIN)', APPEND) Call(101) if (! EM) { // if found too: mark complete frame string visually BB(#103) BE(#106) } else { Goto_Pos(#103) // else simply position cursor at begin of frame string } } else { // if search string empty: whole frame string is target BB(#103) BE(#106) } Update #97=#106 // set begin of possible next search after end of frame string } else { Reg_Set(90, "No frame string found!") Goto_Pos(#99) // if not (more) found: goto end of search area #97=0 } Continue } // === [OK] or [Ok + Stay] Reg_Set(97, ".b") Reg_Empty(98) BB(#98) BE(#99) Goto_Pos(BB) // goto begin of search area repeat(ALL) { Reg_Set(101, 'Search_Block(') // search for begin of frame string Reg_Set(101, @94, APPEND) Reg_Set(101, ', ', APPEND) Reg_Set(101, 'BB, BE, #96)', APPEND) Call(101) if (Error_Match || (Cur_Pos >= BE)) { break } #103=CP // remember position of begin of frame string #104=CP+Chars_Matched // remember position after begin of frame string BB(CLEAR) // search end of frame string Reg_Set(101, 'Search_Block(') Reg_Set(101, @96, APPEND) Reg_Set(101, ', #104, #99, #96+BEGIN)', APPEND) Call(101) #105=CP // remember pos of begin of end frame string #106=CP+Chars_Matched // remember pos after frame string if (#91 == 1) { // Delete strings with the search string within the search area Reg_Set(101, 'Search_Block(') Reg_Set(101, @95, APPEND) Reg_Set(101, ', ', APPEND) Reg_Set(101, '#104, #105, #96+BEGIN)', APPEND) Call(101) // search within that string for the search string if (! EM) { // if found: delete the block Del_Block(#103, #106) } else { // else: set cursor past block Goto_Pos(#106) } } else { if (#91 == 2) { // Delete strings without the search string within the search area Reg_Set(101, 'Search_Block(') Reg_Set(101, @95, APPEND) Reg_Set(101, ', ', APPEND) Reg_Set(101, '#104, #105, #96+BEGIN)', APPEND) Call(101) // search within that string for the search string if (! EM) { // if found: Goto_Pos(#106) } else { // else: delete the block Del_Block(#103, #106) } if (Cur_Pos >= BE) { break } } else { break // just to be sure ... } } } if (#93) { // if in block mode: BB(#98) // set BB to begin of search area again } else { BB(CLEAR) } if (#90 != 2) { // if not in "stay" mode break // leave the loop } Goto_Pos(BB) } :END: if (#93) { BB(Marker(8)) BE(Marker(9)) } Update Reg_Pop(89,99) // restore the saved registers Num_Pop(85,99) Reg_Empty(101) // empty subroutine macro register Visual_Macro(NOMSG) return(0,DELETE) //=====================================================================