add editor command to sort sel lines, close #78

This commit is contained in:
Basile Burg 2016-07-11 04:57:20 +02:00
parent 0d767dd129
commit 9aebae7f99
5 changed files with 188 additions and 11 deletions

BIN
icons/other/sort_az.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -13,7 +13,7 @@
<DpiAware Value="True"/> <DpiAware Value="True"/>
</XPManifest> </XPManifest>
<Icon Value="0"/> <Icon Value="0"/>
<Resources Count="86"> <Resources Count="87">
<Resource_0 FileName="../icons/window/layout_add.png" Type="RCDATA" ResourceName="LAYOUT_ADD"/> <Resource_0 FileName="../icons/window/layout_add.png" Type="RCDATA" ResourceName="LAYOUT_ADD"/>
<Resource_1 FileName="../icons/window/layout.png" Type="RCDATA" ResourceName="LAYOUT"/> <Resource_1 FileName="../icons/window/layout.png" Type="RCDATA" ResourceName="LAYOUT"/>
<Resource_2 FileName="../icons/window/application_go.png" Type="RCDATA" ResourceName="APPLICATION_GO"/> <Resource_2 FileName="../icons/window/application_go.png" Type="RCDATA" ResourceName="APPLICATION_GO"/>
@ -100,6 +100,7 @@
<Resource_83 FileName="../icons/other/case.png" Type="RCDATA" ResourceName="CASE"/> <Resource_83 FileName="../icons/other/case.png" Type="RCDATA" ResourceName="CASE"/>
<Resource_84 FileName="../icons/other/tag_purple.png" Type="RCDATA" ResourceName="TAG_PURPLE"/> <Resource_84 FileName="../icons/other/tag_purple.png" Type="RCDATA" ResourceName="TAG_PURPLE"/>
<Resource_85 FileName="../cesetup/version.txt" Type="RCDATA" ResourceName="VERSION"/> <Resource_85 FileName="../cesetup/version.txt" Type="RCDATA" ResourceName="VERSION"/>
<Resource_86 FileName="../icons/other/sort_az.png" Type="RCDATA" ResourceName="SORT_AZ"/>
</Resources> </Resources>
</General> </General>
<i18n> <i18n>

View File

@ -125,6 +125,13 @@ inherited CEEditorWidget: TCEEditorWidget
object MenuItem7: TMenuItem object MenuItem7: TMenuItem
Caption = '-' Caption = '-'
end end
object mnuedSortLines: TMenuItem
Caption = 'Sort lines'
OnClick = mnuedSortLinesClick
end
object MenuItem1: TMenuItem
Caption = '-'
end
object mnuedComm: TMenuItem object mnuedComm: TMenuItem
Caption = 'Comment selected lines' Caption = 'Comment selected lines'
OnClick = mnuedCommClick OnClick = mnuedCommClick

View File

@ -52,9 +52,11 @@ type
{ TCEEditorWidget } { TCEEditorWidget }
TCEEditorWidget = class(TCEWidget, ICEDocumentObserver, ICEMultiDocHandler, ICEProjectObserver) TCEEditorWidget = class(TCEWidget, ICEDocumentObserver, ICEMultiDocHandler, ICEProjectObserver)
MenuItem1: TMenuItem;
MenuItem10: TMenuItem; MenuItem10: TMenuItem;
MenuItem11: TMenuItem; MenuItem11: TMenuItem;
MenuItem12: TMenuItem; MenuItem12: TMenuItem;
mnuedSortLines: TMenuItem;
mnuedNextCarea: TMenuItem; mnuedNextCarea: TMenuItem;
mnuedPrevCarea: TMenuItem; mnuedPrevCarea: TMenuItem;
mnuedLowcase: TMenuItem; mnuedLowcase: TMenuItem;
@ -86,6 +88,7 @@ type
procedure mnuedNextCareaClick(Sender: TObject); procedure mnuedNextCareaClick(Sender: TObject);
procedure mnuedPrevCareaClick(Sender: TObject); procedure mnuedPrevCareaClick(Sender: TObject);
procedure mnuedLowcaseClick(Sender: TObject); procedure mnuedLowcaseClick(Sender: TObject);
procedure mnuedSortLinesClick(Sender: TObject);
procedure mnuedUpcaseClick(Sender: TObject); procedure mnuedUpcaseClick(Sender: TObject);
procedure MenuItem5Click(Sender: TObject); procedure MenuItem5Click(Sender: TObject);
procedure MenuItem6Click(Sender: TObject); procedure MenuItem6Click(Sender: TObject);
@ -314,6 +317,7 @@ begin
AssignPng(mnuedLowcase.Bitmap, 'CASE'); AssignPng(mnuedLowcase.Bitmap, 'CASE');
AssignPng(mnuedNextCarea.Bitmap, 'GO_NEXT'); AssignPng(mnuedNextCarea.Bitmap, 'GO_NEXT');
AssignPng(mnuedPrevCarea.Bitmap, 'GO_PREVIOUS'); AssignPng(mnuedPrevCarea.Bitmap, 'GO_PREVIOUS');
AssignPng(mnuedSortLines.Bitmap, 'SORT_AZ');
// //
EntitiesConnector.addObserver(self); EntitiesConnector.addObserver(self);
EntitiesConnector.addSingleService(self); EntitiesConnector.addSingleService(self);
@ -841,6 +845,12 @@ begin
fDoc.CommandProcessor(ecLowerCaseWordOrSel, #0, nil); fDoc.CommandProcessor(ecLowerCaseWordOrSel, #0, nil);
end; end;
procedure TCEEditorWidget.mnuedSortLinesClick(Sender: TObject);
begin
if fDoc.isNotNil then
fDoc.CommandProcessor(ecSortLines, #0, nil);
end;
procedure TCEEditorWidget.mnuedNextCareaClick(Sender: TObject); procedure TCEEditorWidget.mnuedNextCareaClick(Sender: TObject);
begin begin
if fDoc.isNotNil then if fDoc.isNotNil then

View File

@ -9,7 +9,7 @@ uses
SynEdit, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText, SynEdit, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText,
SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView, SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView,
SynEditMarks, SynEditTypes, SynHighlighterJScript, SynBeautifier, dialogs, SynEditMarks, SynEditTypes, SynHighlighterJScript, SynBeautifier, dialogs,
fpjson, jsonparser, LazUTF8, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs, ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs,
ce_sharedres, ce_dlang, ce_stringrange; ce_sharedres, ce_dlang, ce_stringrange;
@ -120,6 +120,8 @@ type
procedure next; procedure next;
end; end;
TSortDialog = class;
TCESynMemo = class(TSynEdit) TCESynMemo = class(TSynEdit)
private private
fFilename: string; fFilename: string;
@ -165,6 +167,7 @@ type
fAlwaysAdvancedFeatures: boolean; fAlwaysAdvancedFeatures: boolean;
fIsProjectDescription: boolean; fIsProjectDescription: boolean;
fAutoClosedPairs: TAutoClosePairs; fAutoClosedPairs: TAutoClosePairs;
fSortDialog: TSortDialog;
procedure decCallTipsLvl; procedure decCallTipsLvl;
procedure setMatchOpts(value: TIdentifierMatchOptions); procedure setMatchOpts(value: TIdentifierMatchOptions);
function getMouseBytePosition: Integer; function getMouseBytePosition: Integer;
@ -196,6 +199,7 @@ type
procedure gotoToChangedArea(next: boolean); procedure gotoToChangedArea(next: boolean);
procedure autoClosePair(value: TAutoClosedPair); procedure autoClosePair(value: TAutoClosedPair);
procedure setSelectionOrWordCase(upper: boolean); procedure setSelectionOrWordCase(upper: boolean);
procedure sortSelectedLines(descending, caseSensitive: boolean);
protected protected
procedure DoEnter; override; procedure DoEnter; override;
procedure DoExit; override; procedure DoExit; override;
@ -234,8 +238,8 @@ type
procedure ShowPhobosDoc; procedure ShowPhobosDoc;
procedure nextChangedArea; procedure nextChangedArea;
procedure previousChangedArea; procedure previousChangedArea;
procedure copy;
function implementMain: THasMain; function implementMain: THasMain;
procedure sortLines;
// //
function breakPointsCount: integer; function breakPointsCount: integer;
function breakPointLine(index: integer): integer; function breakPointLine(index: integer): integer;
@ -268,6 +272,20 @@ type
property autoClosedPairs: TAutoClosePairs read fAutoClosedPairs write fAutoClosedPairs; property autoClosedPairs: TAutoClosePairs read fAutoClosedPairs write fAutoClosedPairs;
end; end;
TSortDialog = class(TForm)
private
class var fDescending: boolean;
class var fCaseSensitive: boolean;
fEditor: TCESynMemo;
fCanUndo: boolean;
procedure btnApplyClick(sender: TObject);
procedure btnUndoClick(sender: TObject);
procedure chkCaseSensClick(sender: TObject);
procedure chkDescClick(sender: TObject);
public
constructor construct(editor: TCESynMemo);
end;
procedure SetDefaultCoeditKeystrokes(ed: TSynEdit); procedure SetDefaultCoeditKeystrokes(ed: TSynEdit);
function CustomStringToCommand(const Ident: string; var Int: Longint): Boolean; function CustomStringToCommand(const Ident: string; var Int: Longint): Boolean;
@ -292,6 +310,7 @@ const
ecNextChangedArea = ecUserFirst + 16; ecNextChangedArea = ecUserFirst + 16;
ecUpperCaseWordOrSel = ecUserFirst + 17; ecUpperCaseWordOrSel = ecUserFirst + 17;
ecLowerCaseWordOrSel = ecUserFirst + 18; ecLowerCaseWordOrSel = ecUserFirst + 18;
ecSortLines = ecUserFirst + 19;
var var
D2Syn: TSynD2Syn; // used as model to set the options when no editor exists. D2Syn: TSynD2Syn; // used as model to set the options when no editor exists.
@ -311,6 +330,95 @@ begin
result := inherited CalcHintRect(MaxWidth, AHint, AData); result := inherited CalcHintRect(MaxWidth, AHint, AData);
end; end;
{$REGION TSortDialog -----------------------------------------------------------}
constructor TSortDialog.construct(editor: TCESynMemo);
var
pnl: TPanel;
begin
inherited Create(nil);
fEditor := editor;
width := 150;
Height:= 95;
FormStyle:= fsStayOnTop;
BorderStyle:= bsToolWindow;
Position:= poScreenCenter;
ShowHint:=true;
with TCheckBox.Create(self) do
begin
parent := self;
BorderSpacing.Around:=2;
OnClick:=@chkCaseSensClick;
Caption:='case sensitive';
checked := fCaseSensitive;
align := alTop;
end;
with TCheckBox.Create(self) do
begin
parent := self;
BorderSpacing.Around:=2;
OnClick:=@chkDescClick;
Caption:='descending';
Checked:= fDescending;
align := alTop;
end;
pnl := TPanel.Create(self);
pnl.Parent := self;
pnl.Align:=alBottom;
pnl.Caption:='';
pnl.Height:= 32;
pnl.BevelOuter:=bvLowered;
with TSpeedButton.Create(self) do
begin
parent := pnl;
BorderSpacing.Around:=2;
OnClick:=@btnUndoClick;
align := alRight;
width := 28;
Hint := 'undo changes';
AssignPng(Glyph, 'ARROW_UNDO');
end;
with TSpeedButton.Create(self) do
begin
parent := pnl;
BorderSpacing.Around:=2;
OnClick:=@btnApplyClick;
align := alRight;
width := 28;
Hint := 'apply sorting';
AssignPng(Glyph, 'ACCEPT');
end;
end;
procedure TSortDialog.btnApplyClick(sender: TObject);
begin
fEditor.sortSelectedLines(fDescending, fCaseSensitive);
fCanUndo:= true;
end;
procedure TSortDialog.btnUndoClick(sender: TObject);
begin
if fCanUndo then
fEditor.undo;
fCanUndo:= false;
end;
procedure TSortDialog.chkCaseSensClick(sender: TObject);
begin
fCaseSensitive := TCheckBox(sender).checked;
end;
procedure TSortDialog.chkDescClick(sender: TObject);
begin
fDescending := TCheckBox(sender).checked;
end;
{$ENDREGION}
{$REGION TCESynMemoCache -------------------------------------------------------} {$REGION TCESynMemoCache -------------------------------------------------------}
constructor TCESynMemoCache.create(aComponent: TComponent); constructor TCESynMemoCache.create(aComponent: TComponent);
begin begin
@ -622,6 +730,7 @@ begin
fCallTipStrings.Free; fCallTipStrings.Free;
fLexToks.Clear; fLexToks.Clear;
fLexToks.Free; fLexToks.Free;
fSortDialog.Free;
// //
if fTempFileName.fileExists then if fTempFileName.fileExists then
sysutils.DeleteFile(fTempFileName); sysutils.DeleteFile(fTempFileName);
@ -792,6 +901,7 @@ begin
AddKey(ecNextChangedArea, VK_DOWN, [ssAlt], 0, []); AddKey(ecNextChangedArea, VK_DOWN, [ssAlt], 0, []);
addKey(ecLowerCaseWordOrSel, 0, [], 0, []); addKey(ecLowerCaseWordOrSel, 0, [], 0, []);
addKey(ecUpperCaseWordOrSel, 0, [], 0, []); addKey(ecUpperCaseWordOrSel, 0, [], 0, []);
addKey(ecSortLines, 0, [], 0, []);
end; end;
end; end;
@ -816,6 +926,7 @@ begin
'ecPreviousChangedArea':begin Int := ecPreviousChangedArea; exit(true); end; 'ecPreviousChangedArea':begin Int := ecPreviousChangedArea; exit(true); end;
'ecUpperCaseWordOrSel': begin Int := ecUpperCaseWordOrSel; exit(true); end; 'ecUpperCaseWordOrSel': begin Int := ecUpperCaseWordOrSel; exit(true); end;
'ecLowerCaseWordOrSel': begin Int := ecLowerCaseWordOrSel; exit(true); end; 'ecLowerCaseWordOrSel': begin Int := ecLowerCaseWordOrSel; exit(true); end;
'ecSortLines': begin Int := ecSortLines; exit(true); end;
else exit(false); else exit(false);
end; end;
end; end;
@ -841,6 +952,7 @@ begin
ecPreviousChangedArea:begin Ident := 'ecPreviousChangedArea'; exit(true); end; ecPreviousChangedArea:begin Ident := 'ecPreviousChangedArea'; exit(true); end;
ecUpperCaseWordOrSel: begin Ident := 'ecUpperCaseWordOrSel'; exit(true); end; ecUpperCaseWordOrSel: begin Ident := 'ecUpperCaseWordOrSel'; exit(true); end;
ecLowerCaseWordOrSel: begin Ident := 'ecLowerCaseWordOrSel'; exit(true); end; ecLowerCaseWordOrSel: begin Ident := 'ecLowerCaseWordOrSel'; exit(true); end;
ecSortLines: begin Ident := 'ecSortLines'; exit(true); end;
else exit(false); else exit(false);
end; end;
end; end;
@ -898,6 +1010,8 @@ begin
setSelectionOrWordCase(true); setSelectionOrWordCase(true);
ecLowerCaseWordOrSel: ecLowerCaseWordOrSel:
setSelectionOrWordCase(false); setSelectionOrWordCase(false);
ecSortLines:
sortLines;
end; end;
if fOverrideColMode and not SelAvail then if fOverrideColMode and not SelAvail then
begin begin
@ -1283,14 +1397,6 @@ begin
OpenURL(pth); OpenURL(pth);
end; end;
procedure TCESynMemo.copy;
begin
{$IFDEF WINDOWS}
{$ELSE}
// workaround https://github.com/BBasile/Coedit/issues/39
{$ENDIF}
end;
procedure TCESynMemo.nextChangedArea; procedure TCESynMemo.nextChangedArea;
begin begin
gotoToChangedArea(true); gotoToChangedArea(true);
@ -1453,6 +1559,59 @@ begin
EndUndoBlock; EndUndoBlock;
end; end;
end; end;
procedure TCESynMemo.sortSelectedLines(descending, caseSensitive: boolean);
var
i,j: integer;
lne: string;
lst: TStringListUTF8;
pt0: TPoint;
begin
if BlockEnd.Y - BlockBegin.Y < 1 then
exit;
lst := TStringListUTF8.Create;
try
BeginUndoBlock;
for i:= BlockBegin.Y-1 to BlockEnd.Y-1 do
lst.Add(lines[i]);
pt0 := BlockBegin;
pt0.X:=1;
ExecuteCommand(ecGotoXY, #0, @pt0);
lst.CaseSensitive:=caseSensitive;
if not caseSensitive then
lst.Sorted:=true;
case descending of
false: for i:= 0 to lst.Count-1 do
begin
ExecuteCommand(ecDeleteLine, #0, nil);
ExecuteCommand(ecInsertLine, #0, nil);
lne := lst[i];
for j := 1 to lne.length do
ExecuteCommand(ecChar, lne[j], nil);
ExecuteCommand(ecDown, #0, nil);
end;
true: for i:= lst.Count-1 downto 0 do
begin
ExecuteCommand(ecDeleteLine, #0, nil);
ExecuteCommand(ecInsertLine, #0, nil);
lne := lst[i];
for j := 1 to lne.length do
ExecuteCommand(ecChar, lne[j], nil);
ExecuteCommand(ecDown, #0, nil);
end;
end;
EndUndoBlock;
finally
lst.Free;
end;
end;
procedure TCESynMemo.sortLines;
begin
if not assigned(fSortDialog) then
fSortDialog := TSortDialog.construct(self);
fSortDialog.Show;
end;
{$ENDREGION} {$ENDREGION}
{$REGION DDoc & CallTip --------------------------------------------------------} {$REGION DDoc & CallTip --------------------------------------------------------}