This is a specialized version. Mostly doing the same things than the other "Align Block" addons. There are some special additions:
- Autoindent paragraphs with bullets or numbers
- Some special CleanUp and Format functions
The big advantages are, that this macro is well commented (in English ) and you can easily fix it to your needs .
The macro seems to work well. If you discover any critical error please let me know.
Have fun.
- ---- Align Block Special for Editor
- ---- - Align single line in Editor (if no selection available)
- ---- - Align selected lines in Editor
- ---- - Remembers Dialog-Settings only for current Far session
- ------------------------------------------------------------------------------
- -- Defaults/Variables for Dialog
- ------------------------------------------------------------------------------
- local F=far.Flags
- local MaxWidthDef=78
- local mBlockKey="CtrlB" -- Quick FormatBlock without Dialog
- local mBlockKeyDlg="CtrlShiftB" -- Quick FormatBlock with Dialog
- -- IDs taken from array "Items" below (helpful if you do some dialog changes and don't want to change complete macro-code)
- local DlgHeight=22 -- height of dialog
- local id_RightMargin, id_UseAutoIndent, id_IndentFirstLine, id_IndentLeft = 2,4,5,7
- local id_ReformatBlock, id_EmptyLineIsEndOfParagraph, id_CleanWordDividers, id_DeleteLinesAfterParagraph = 10,11,12,14
- local id_EmptyLineAfterParagraph, id_RemoveSpaces, id_RemoveSpacesNotOnStart, id_Punctuation=15,16,17,18
- local id_HelpText, id_OK=20,21
- local Items={
- --[[01]] {"DI_DOUBLEBOX",3, 1, 60, DlgHeight-2, 0,nil,nil,0,"Align Block Special",nil,nil},
- --[[02]] {"DI_FIXEDIT", 5, 2, 7, 0, 0, nil,'999',{DIF_MASKEDIT=1, DIF_SELECTONENTRY=1},MaxWidthDef,nil,nil}, -- id_RightMargin
- --[[03]] {"DI_TEXT", 9, 2, 0, 0, 0, nil,nil,0,"Right &margin",nil,nil},
- --[[04]] {"DI_CHECKBOX", 5, 3, 0, 0, 0, 0,0,0,"Disable &AutoIndent"}, -- id_UseAutoIndent
- --[[05]] {"DI_FIXEDIT", 9, 4, 11, 0, 0, nil,'999',{DIF_MASKEDIT=1, DIF_SELECTONENTRY=1},"2",nil,nil}, -- id_IndentFirstLine
- --[[06]] {"DI_TEXT", 13, 4, 0, 0, 0, nil,nil,0,"Indent &First line",nil,nil},
- --[[07]] {"DI_FIXEDIT", 9, 5, 11, 0, 0, nil,'999',{DIF_MASKEDIT=1, DIF_SELECTONENTRY=1},"4",nil,nil}, -- id_IndentLeft
- --[[08]] {"DI_TEXT", 13, 5, 0, 0, 0, nil,nil,0,"Indent &Left",nil,nil},
- --[[09]] {"DI_TEXT", 3, 6, 0, 0, 0, nil,nil,"DIF_SEPARATOR",nil,nil,nil},
- --[[10]] {"DI_CHECKBOX", 5, 7, 0, 0, 1, 0,0,0,"&Reformat block"}, -- id_ReformatBlock
- --[[11]] {"DI_CHECKBOX", 9, 8, 0, 0, 1, 0,0,0,"&Empty line is end of paragraph"}, -- id_EmptyLineIsEndOfParagraph
- --[[12]] {"DI_CHECKBOX", 9, 9, 0, 0, 1, 0,0,0,"&Treat '-' as WordDivider"}, -- id_CleanWordDividers
- --[[13]] {"DI_TEXT", 3, 10, 0, 0, 0, nil,nil,"DIF_SEPARATOR",nil,nil,nil},
- --[[14]] {"DI_CHECKBOX", 5, 11, 0, 0, 1, 0,0,0,"&Delete empty lines after paragraph"}, -- id_DeleteLinesAfterParagraph
- --[[15]] {"DI_CHECKBOX", 9, 12, 0, 0, 1, 0,0,0,"Empt&y line after paragraph"}, -- id_EmptyLineAfterParagraph
- --[[16]] {"DI_CHECKBOX", 5, 13, 0, 0, 1, 0,0,0,"Remove double &whitespaces"}, -- id_RemoveSpaces
- --[[17]] {"DI_CHECKBOX", 9, 14, 0, 0, 1, 0,0,0,"Ex&cept on line start"}, -- id_RemoveSpacesNotOnStart
- --[[18]] {"DI_CHECKBOX", 5, 15, 0, 0, 1, 0,0,0,"Clean up &punctuation marks"}, -- id_Punctuation
- --[[19]] {"DI_TEXT", 3, 16, 0, 0, 0, nil,nil,"DIF_SEPARATOR",nil,nil,nil},
- --[[20]] {"DI_TEXT", 5, 17, 58, 0, 0, nil,nil,{DIF_DISABLE=1},"",nil,nil}, -- id_HelpText
- --[[21]] {"DI_BUTTON", 0, 19, 0, 0, 0, nil,nil,{DIF_CENTERGROUP=1, DIF_DEFAULTBUTTON=1},"Ok",nil,nil}, -- id_OK
- --[[22]] {"DI_BUTTON", 0, 19, 0, 0, 0, nil,nil,{DIF_CENTERGROUP=1},"Cancel",nil,nil}
- }
- local ItemsHelp={
- --[[01]] "",
- --[[02]] "Right margin for Wordwrap",
- --[[03]] "",
- --[[04]] "AutoDetect paragraphs with bullets or numbers",
- --[[05]] "Indent for first line",
- --[[06]] "",
- --[[07]] "Indent for following lines",
- --[[08]] "",
- --[[09]] "",
- --[[10]] "Reformat selected lines to paragraph",
- --[[11]] "Start new paragraph after empty line",
- --[[12]] "Clean up word divider '-' between lines",
- --[[13]] "",
- --[[14]] "Delete empty lines after each paragraph",
- --[[15]] "Insert empty line after each paragraph",
- --[[16]] "Remove double spaces or tabs inside lines",
- --[[17]] "Do not remove them on the start of a line",
- --[[18]] "Reformat Spaces before/after '!?,.;:'",
- --[[19]] "",
- --[[20]] "",
- --[[21]] "Align the block now",
- --[[22]] "Cancel dialog",
- }
- ------------------------------------------------------------------------------
- ------------------------------------------------------------------------------
- ------------------------------------------------------------------------------
- function wrap(_str, _Width, _sIndent2, _sIndent1)
- -- * Word-wrap a string. Leaves strings longer than _Width as they are (from lua-users.org)
- -- * _str=string, _Width=MaxWidth, _sIndent2=Indent before lines (string), _sIndent1=Indent before 1. line (string)
- -- * returns string with Linebreaks ("\n")
- _sIndent1 = _sIndent1 or "" _sIndent2 = _sIndent2 or _sIndent1
- _Width = _Width or MaxWidthDef local here = 1-#_sIndent2
- return _sIndent2 .. _str:gsub("(%s+)()(%S+)()",
- function(sp, st, word, fi)
- if fi - here > _Width then
- here = st - #_sIndent1
- return "\n" .. _sIndent1 .. word
- end
- end)
- end
- ------------------------------------------------------------------------------
- ------------------------------------------------------------------------------
- ------------------------------------------------------------------------------
- local MyBlock_EachLine = function (_ShowDlg)
- -- Format Block: Current Line or selected Lines: Each single Line will be wordwrapped
- local s1
- local Sel=editor.GetSelection() local Inf=editor.GetInfo()
- local Beg = Sel and Sel.StartLine or Inf.CurLine
- local Endx = Sel and Sel.EndLine or Inf.CurLine
- ------------------------------------------------------------------------------
- if Editor.CurLine==Editor.Lines and Editor.GetStr(Editor.CurLine)=="" and Sel==nil then -- exit if end of file and ...
- exit()
- end
- ------------------------------------------------------------------------------
- -- Show Dialog (if more than 1 Line selected)
- ------------------------------------------------------------------------------
- -- if Beg~=Endx then
- if _ShowDlg then
- -----------------------------------
- local function DlgProc (hDlg,Msg,Param1,Param2)
- -----------------------------------
- if Msg == F.DN_BTNCLICK or Msg == F.DN_DRAWDLGITEM then -- Checkbox changed
- if Param1==id_ReformatBlock then
- local enable = far.SendDlgMessage(hDlg,"DM_GETCHECK",Param1)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+1,enable)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+2,enable)
- elseif Param1==id_DeleteLinesAfterParagraph then
- local enable = far.SendDlgMessage(hDlg,"DM_GETCHECK",Param1)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+1,enable)
- elseif Param1==id_RemoveSpaces then
- local enable = far.SendDlgMessage(hDlg,"DM_GETCHECK",Param1)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+1,enable)
- elseif Param1==id_UseAutoIndent then
- local enable = far.SendDlgMessage(hDlg,"DM_GETCHECK",Param1)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+1,enable)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+2,enable)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+3,enable)
- far.SendDlgMessage(hDlg,"DM_ENABLE",Param1+4,enable)
- end
- -----------------------------------
- elseif Msg == F.DN_GOTFOCUS then
- far.SendDlgMessage(hDlg,"DM_SETTEXT",id_HelpText,ItemsHelp[Param1])
- end
- end
- -----------------------------------
- local result=far.Dialog("",-1,-1,64,DlgHeight,nil,Items,nil,DlgProc)
- if result ~= id_OK then return end
- end
- if far.LIsAlphanum(Items[id_RightMargin][10]) then
- local maxwidth=1*Items[id_RightMargin][10] -- "1*" = change string to number
- else
- return -- Empty/Wrong Input in Field
- end
- ------------------------------------------------------------------------------
- -- Collect CurrentLine or SelectedLines in Array with Strings
- ------------------------------------------------------------------------------
- if (Inf.CurLine>=Beg and Inf.CurLine<=Endx) or (Sel and Sel.EndPos==-1 and Inf.CurLine==Sel.EndLine+1) then
- editor.UndoRedo(nil,0) -- disable/enable "UNDO"
- local TabSpace = string.rep (" ", Inf.TabSize) -- String with Spaces with length of TabSize
- local tab={} -- table for strings from editor which will be changed
- tab[1]="" -- define tab (not NIL)
- local j=1
- local Str, Eol
- -----------------------------------
- ---- Helper Func for id_RemoveSpaces
- -----------------------------------
- local function CleanDoubleSpaces (_s1)
- if _s1=="" then return "" end
- if Items[id_RemoveSpaces][6]==1 then
- if Items[id_RemoveSpacesNotOnStart][6]==1 then
- _s1=_s1:gsub("(%S)%s+", "%1 ")
- else
- _s1=_s1:gsub("%s+", " ")
- end
- end
- return _s1
- end
- ----------------------------------
- ---- START: Simple Align (do not Reformat Block)
- ----------------------------------
- if Items[id_ReformatBlock][6]==0 then -- Do: Simple Align (do not Reformat Block)
- ----------------------------------
- for i=Beg,Endx do
- Str,Eol=editor.GetString(nil,Beg,2) -- Modes 1 ("fast") and 2 ("fastest") have a side effect: the current line position in the Editor is set to StringNumber
- Str=CleanDoubleSpaces(Str) -- if Items[id_RemoveSpaces][6]==1 then ...
- ----------------------------------
- if Items[id_DeleteLinesAfterParagraph][6]==1 then -- Delete lines after paragraph
- if (Str:gsub("^%s*", "")~="") then -- LTrim (no empty string)
- tab[j]=Str -- put in table
- j = j+1
- end
- else
- tab[j]=Str -- put in table
- j = j+1
- end
- ----------------------------------
- editor.DeleteString() -- delete current string
- end
- ----------------------------------
- ---- START: Complex Align (Reformat Block)
- ----------------------------------
- else -- Do: Reformat Block
- local b, k=0,0
- -----------------------------------
- ---- Helper Func: add empty items to array
- -----------------------------------
- local function AddEmptyLines()
- local n=0
- if k>0 then -- Not DeleteLinesAfterParagraph
- for n=1,k do
- j=j+1
- tab[j]="" -- add empty line
- end
- k=0
- end
- end
- --------------------------------
- for i=Beg,Endx do
- Str,Eol=editor.GetString(nil,Beg,2) -- Modes 1 ("fast") and 2 ("fastest") have a side effect: the current line position in the Editor is set to StringNumber
- Str=Str:gsub("%s+$", "") -- RTrim each String (RTrim leaves Whitespaces before 1. string)
- ----------------------------------
- -- Line <> ""
- if Str~="" then
- Str=Str:gsub("^%s+", "") -- Now: LTrim
- Str=CleanDoubleSpaces(Str) -- if Items[id_RemoveSpaces][6]==1 then ...
- if b==1 then -- there are some linebreaks to handle...
- AddEmptyLines()
- j=j+1
- tab[j]=Str -- next one is for item
- b=0
- else -- there are no linebreaks to handle
- if tab[j]=="" then
- s1=""
- else
- s1=" "
- ----------------------------------
- ---- Clean WordDividers
- if Items[id_CleanWordDividers][6]==1 then
- if tab[j]:sub(-1)=="-" then
- if far.LIsAlphanum(tab[j]:sub(-2,-1)) and far.LIsAlphanum(Str:sub(1,1)) then
- tab[j]=tab[j]:sub(1,#tab[j]-1) -- delete "-"
- s1=""
- end
- end
- end
- end
- tab[j]=tab[j] .. s1 .. Str
- end
- ----------------------------------
- -- Line = ""
- else
- ----------------------------------
- if Items[id_EmptyLineIsEndOfParagraph][6]==1 then -- EmptyLineIsEndOfParagraph
- if Items[id_DeleteLinesAfterParagraph][6]~=1 then -- Not DeleteLinesAfterParagraph
- k=k+1
- end
- b=1
- end
- --------------------------------
- end
- --------------------------------
- -- Add rest of empty lines after finishing "FOR"-loop
- if Items[id_DeleteLinesAfterParagraph][6]~=1 then -- Not DeleteLinesAfterParagraph
- if b==1 then AddEmptyLines() end
- end
- --------------------------------
- editor.DeleteString() -- delete current string
- end
- end
- ----------------------------------
- editor.SetPosition(nil,Beg,0,1,-1,-1,-1) -- Goto Start of current Line
- ------------------------------------------------------------------------------
- -- Handle Indent
- ------------------------------------------------------------------------------
- local ind1, ind2
- for i=1,#tab do
- ----------------------------------
- -- AutoIndent on
- ----------------------------------
- if Items[id_UseAutoIndent][6]==0 then
- -- Searchmask for paragraphs with symbol: "- ", "1.1." etc.
- -- f1(.. f2[... [... f3(...
- -- f1 % * ? = + - : .0-9#^$'!,;_ = + - ) ] } .
- local nBeg, nEnd, f1, f2, f3 = tab[i]:find("^(%s*)([%%%*%?%=%+%-%:%.0-9#^$'!,;_]+[=%+%-%)%]%}%.]*)(%s+)")
- ----------------------------------
- if nBeg~=nil then -- Searchmask found
- f1 = f1:gsub("\t", TabSpace) -- replace tabs
- f3 = f3:gsub("\t", TabSpace) -- replace tabs
- ind1=string.rep (" ", #f1) .. f2 .. string.rep (" ", #f3) -- Indent for 1. line
- tab[i]=tab[i]:sub(#ind1+1) -- delete this Indent from string
- ind2=string.rep (" ", #ind1) -- Indent for lines after 1. line
- ----------------------------------
- else -- Searchmask not found
- local nBeg, nEnd, f1 = tab[i]:find("^(%s*)") -- Searchmask for paragraphs with leading whitespaces
- f1 = f1:gsub("\t", TabSpace) -- replace tabs
- ind1="" -- Indent for 1. line
- ind2=string.rep (" ", #f1) -- Indent for lines after 1. line
- end
- ----------------------------------
- -- AutoIndent off
- ----------------------------------
- else
- if far.LIsAlphanum(Items[id_IndentFirstLine][10]) then j=(1*Items[id_IndentFirstLine][10]) or 0 else j=0 end
- if j>0 then ind1=string.rep (" ", j) else ind1="" end -- Indent for 1. line
- tab[i]=tab[i]:gsub("^%s*", "") -- LTrim (spaces should be removed in first line)
- ----------------------------------
- if far.LIsAlphanum(Items[id_IndentLeft][10]) then j=(1*Items[id_IndentLeft][10]) or 0 else j=0 end
- if j>0 then ind2=string.rep (" ", j) else ind2="" end -- Indent for following lines
- end
- ----------------------------------
- -- ReFormat Punctuation
- if Items[id_Punctuation][6]==1 then tab[i]=tab[i]:gsub("(%s+)([%?%:%.!,;])(%s+)", "%2 ") end
- ----------------------------------
- -- Print Paragraphs
- local s2=wrap(tab[i], maxwidth, ind1, ind2) -- call word-wrap function
- print(s2 .. "\n") -- print in editor
- ----------------------------------
- -- Insert empty Line after Paragraph
- if Editor.CurLine>1 and Items[id_DeleteLinesAfterParagraph][6]==1 and Items[id_EmptyLineAfterParagraph][6]==1 then
- if Beg==Endx then -- If only 1 empty line then do not add line
- if Editor.GetStr(Editor.CurLine)~="" and Editor.GetStr(Editor.CurLine-1)~="" then
- print("\n")
- end
- else -- print in editor
- print("\n")
- end
- end
- ----------------------------------
- end
- ------------------------------------------------------------------------------
- editor.UndoRedo(nil,1) -- disable/enable "UNDO"
- end
- end
- ------------------------------------------------------------------------------
- ------------------------------------------------------------------------------
- ------------------------------------------------------------------------------
- Macro { description=":Format MyBlock: WordWrap EachLine";
- area="Editor"; key=mBlockKey; flags="NoSendKeysToPlugins";
- action = function() MyBlock_EachLine(false) end; }
- Macro { description=":Format MyBlock: WordWrap EachLine";
- area="Editor"; key=mBlockKeyDlg; flags="NoSendKeysToPlugins";
- action = function() MyBlock_EachLine(true) end; }
GeSHi © Codebox Plus Extension