local SelectFound=true -- Select Found true=yes, false=no local Code=[[ local SearchTag=function(direction) local Data={ sSearchPat="<\\/?(?:\\w+?|xsl:\\w+?-?\\w+?)[ >]", sRegexLib="oniguruma", --"far" (default), "oniguruma", "pcre" or "pcre2" bRegExpr=true, bSearchBack=direction=="left" } local nFound=lfsearch.EditorAction("test:search",Data) return nFound end local CaptureTag=function() _G.LFST=nil local patt=regex.new("<\\/?(?:\\w+?|xsl:\\w+?-?\\w+?)[ >]|\\/>","ix") local s=editor.GetStringW() if not s then return end local EGI=editor.GetInfo() local pos,pEnd = EGI.CurPos,s.StringLength+1 _G.Y1 = EGI.CurLine if pos>=pEnd then return end local text,start = s.StringText.."\0",1 while true do local b,e = patt:findW(text,start) if b==nil or b>pos then break elseif e>=pos then --far.Message("b="..b.."\ne="..e) _G.LFST={} if e-b==1 then _G.LFST.Rev=true _G.LFST.Num=1 _G.LFST.Cnt=1 else _G.LFST.Txt=win.Utf16ToUtf8(win.subW(text,b,e-1)) _G.LFST.Rev=_G.LFST.Txt:sub(2,2)=='/' _G.LFST.Num=b==pos and not _G.LFST.Rev and 0 or 1 _G.LFST.Cnt=b==pos and 2 or 1 _G.LFST.Tag=_G.LFST.Rev and '<'.._G.LFST.Txt:sub(3,-1) or _G.LFST.Txt end _G.X1=_G.LFST.Rev and e or b break end start=e+1 end end local ProcessingTag=function() local Data={ sSearchPat="(<\\/?(?:\\w+?|xsl:\\w+?-?\\w+?))[ >]|(\\/>)", sReplacePat=[=[ if T[1] and T[1]==_G.LFST.Txt then _G.LFST.Num=_G.LFST.Num+1 elseif T[1] and (T[1]:sub(2,2)=='/' and '<'..T[1]:sub(3,-1) or T[1])==_G.LFST.Tag then _G.LFST.Num=LFST.Num-1 elseif _G.LFST.Rev and T[1] and T[1]:sub(2,2)~='/' and M==_G.LFST.Cnt and not _G.LFST.Tag then _G.LFST.Num=0 elseif not _G.LFST.Rev and T[2] and T[2]=='/>' and M==_G.LFST.Cnt and _G.LFST.Num==1 then _G.LFST.Num=0 end if _G.LFST.Num==0 then return true,true end ]=], sRegexLib="oniguruma", --"far" (default), "oniguruma", "pcre" or "pcre2" bRegExpr=true, bSearchBack=_G.LFST.Rev, bRepIsFunc=true, bConfirmReplace=true, fUserChoiceFunc=function() return "cancel" end } local nFound,nReps = lfsearch.EditorAction("test:replace",Data) return nFound,nReps end --- Algorithm --- CaptureTag() if not _G.LFST then res=far.Message("<= 1st =>\n=> 2nd <=","Seek priority","Left;Right") local nFound if res==1 then nFound=SearchTag("left") if nFound==0 then nFound=SearchTag("right") if nFound==1 then nFound=SearchTag("left") end end elseif res==2 then nFound=SearchTag("right") nFound=SearchTag("left") end if nFound==1 then CaptureTag() else return end end if _G.LFST then local nFound,nReps = ProcessingTag() if _G.LFST.Num>0 then nFound=SearchTag("left") if nFound==0 then nFound=SearchTag("right") if nFound==1 then nFound=SearchTag("left") end end if nFound==1 then CaptureTag() else return end if _G.LFST then nFound,nReps = ProcessingTag() end end --far.Message("Num="..tostring(_G.LFST.Num).."\nRev="..tostring(_G.LFST.Rev).."\nnFound="..tostring(nFound).."\nnReps="..tostring(nReps)) else return end if _G.LFST.Num==0 then return _G.LFST.Rev,_G.X1,_G.Y1 end ]] --<xsl:apply-templates select=""><div><div><div><font><p></p></font></div></div> --<xsl:when test=""><xsl:apply-templates select=""><xsl:sort select="" /><br />/> --</xsl:apply-templates></xsl:when></div></xsl:apply-templates></div><div>/> --<filetype mask="*." description="ctPgDn &x !.! - файл с именем в стиле 'Text UNIX' поместить в редактор Фара"> -- <command type="0" enabled="0" command="view:"!=\!+!""/> -- <command type="1" enabled="1" command="edit:"!=\!+!""/> -- <command type="2" enabled="0" command=""/> --</filetype> local LFS_Guid="8E11EA75-0303-4374-AC60-D1E38F865449" Macro { description="Goto Begin<=>End of Tags"; area="Editor"; key="AltM"; action=function() --local ttime=far.FarClock() local Rev,X1,Y1 = Plugin.SyncCall(LFS_Guid,"code",Code) --ttime = far.FarClock()-ttime if X1 and Y1 and not Rev then Keys("Left") end if SelectFound and X1 and Y1 then local EGI=editor.GetInfo() local X2,Y2 = EGI.CurPos,EGI.CurLine local F=far.Flags local SelectData={ BlockType=F.BTYPE_STREAM, BlockStartLine=math.min(Y2,Y1), BlockStartPos=Y1<Y2 and X1 or (Y1==Y2 and math.min(X1,X2) or X2) } if X1==X2 then SelectData.BlockStartPos=SelectData.BlockStartPos+(Y1<Y2 and 1 or -1) end SelectData.BlockHeight=math.max(Y1,Y2)-math.min(Y1,Y2)+1 if Y1<Y2 then SelectData.BlockWidth=X2-X1+1 elseif Y1==Y2 then SelectData.BlockWidth=math.abs(X2-X1)+1 else SelectData.BlockWidth=X1-X2+1 end if X1==X2 then if Y1<Y2 then SelectData.BlockStartPos=SelectData.BlockStartPos-1 else SelectData.BlockStartPos=SelectData.BlockStartPos+1 end end --far.Message("Y1="..SelectData.BlockStartLine.."\nX1="..SelectData.BlockStartPos.."\nW="..SelectData.BlockWidth.."\nH="..SelectData.BlockHeight) editor.Select(nil,SelectData) --local report="Time: "..ttime.." mcs" --far.Message(report,"Report",nil,"l") end end } |