// LINEFILT.VDM - Delete all lines in the current file that match or // don't match a search string. // It's like a search and deletion of unwanted lines. // // You can use pattern matching or regular expressions // in the search. // // Written by: Christian Ziemski // 27-Jan-2003. // Last change: 21-Apr-2003. // // Requires: VEDIT 6.10 or later. // // Usage: Select {MISC, More macros, LINEFILTER}. // //----------------------------------------------------------------------- // Used registers (they are saved and restored): // -------------------------------------------- // #86 position for the dialog // #87 temp. used // #88 saved value for BlockBegin // #89 saved value for Config_Value: highlight cursor line // #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 search string // $92 temp. string delimiter and then the correct delimited search string // $93 DI1() .b flag // $94 DI1() .b flag // //======================================================================== Num_Push(86,99) // save the used registers Reg_Push(89,94) // 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 #89=Config(D_H_CR_LINE) // save that config option Reg_Set(89, "Line-Filter - Delete matching / non-matching lines") // DI1() default title string Reg_Set(93, ".b") // set initial focus on [OK+STAY] button Reg_Empty(94) Reg_Set(90, @89) // set DI1() title string with default title Undo_Reset() // reset Undo // ======== main loop repeat(ALL) { Update #90=Dialog_Input_1(91,"`|@(90)`, `Delete all lines in the current file that match or don't match a search string. (Note: Since this function can delete many lines, use it with care!) `,`Delete all lines `, `.h()-with- or`, `.h()-without- the search string`, `.g[]From beginning of file (or block); else from cursor`, `[]Only within the highlighted block`, `[]Case sensitive`, `Search with`, `.h()pattern matching or`, `.h()regular expressions`, `??Search s&tring:`, ``, `\[Ok] deletes the lines and returns\n[Ok + Stay] deletes the lines and stays in this dialog\n[Search] only searches matching lines, does not delete anything`, `[&Ok]`, `|@(93)[O&k + Stay]`, `|@(94)[&Search]`, `[&Undo]`, `[&Done]`", @91,WORKAREA+#86,0,0) // === [Done] or if (#90 == 0 || #90 > 4) { Goto END } // === [Undo] as good as possible ... 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]: switch focus to it Reg_Empty(93) Reg_Set(94, ".b") } // clean error message Reg_Set(90, @89) // set DI1() title string with default title // Prepare the user's search string from $91 for later use in $92 if (Reg_Size(91) == 0) { // if no search string: return to dialog Reg_Set(90, "ERROR: no search string given!") Continue } else { // try to find a string delimiter not included in the user's search text #103=Buf_Num Buf_Switch(Buf_Free(EXTRA)) Reg_Ins(91, BEGIN) // the original search string Ins_Text(.`'´"%&*,:;/~^=.) // 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(92, Cur_Pos, CP+1) // get this possible delimiter Char(1) // advance past it Search(.|@(92)., 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(92) // and add the found delimiter at end too break // leave the loop } } Reg_Copy_Block(92, 0, File_Size) // copy the search string with correct delimiters to $92 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 } } // evaluate the begin and end of search area BoL // always complete lines #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 // now reduce the search area to the highlighted block, if set // To be exact: The here used search area contains all lines whose CR/LF or at least one // character are included in the highlighted block. if (#93) { // if [x]Block is checked if (BB == -1 && BE == -1) { // but if no blockmarker is set #93=0 // uncheck []Block Reg_Set(90, "Blockmode was activated but no marker set!") 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 } } Goto_Pos(BB) #98=Bol_Pos // always complete line #99=BE Goto_Pos(BE) // check the end of the highlighted block if (! At_BoL) { // if not at BoL #99=EoL_Pos // get complete last line } } #96=CASE*#94 + REGEXP*(#95==2) + NOERR // set the search options // === [Search] (once per line) if (#90 == 3) { Reg_Empty(93) Reg_Set(94, ".b") Reg_Set(101, 'Search_Block(') Reg_Set(101, @92, APPEND) Reg_Set(101, ', Max(#98,#97), #99, #96+BEGIN)', APPEND) Call(101) if (! EM) { #97=Cur_Pos + Chars_Matched // prepare next begin of [search] Config( D_H_CR_LINE, "Highlight cursor line", 1 ) } else { Reg_Set(90, "No search string found!") Goto_Pos(#99) // if not (more) found: goto end of search area Config( D_H_CR_LINE, "Highlight cursor line", 0 ) #97=0 } Continue } // === [OK] or [Ok + Stay] Reg_Set(93, ".b") Reg_Empty(94) BB(#98) BE(#99) Goto_Pos(BB) // goto begin of search area repeat(ALL) { Reg_Set(101, 'Search_Block(') Reg_Set(101, @92, APPEND) Reg_Set(101, ', ', APPEND) Reg_Set(101, 'BB, BE, #96)', APPEND) Call(101) if (#91 == 1) { // Delete lines with the search string within the search area if (Error_Match || (Cur_Pos >= BE)) { break } BoL Del_Line(1) } else { if (#91 == 2) { // Delete lines without the search string within the search area if (Error_Match) { Del_Block(BB, BE) break } else { BoL Del_Block(BB,Cur_Pos) Line(1, NOERR) BB(Cur_Pos) } 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: Config(D_H_CR_LINE, "Highlight cursor line (1=Full, 2=Partial)", #89 ) Update Reg_Pop(89,94) // restore the saved registers Num_Pop(86,99) Reg_Empty(101) // empty subroutine macro register Visual_Macro(NOMSG) return(0,DELETE) //=====================================================================