mirror of https://gitlab.com/basile.b/dexed.git
fix #280 - auto detection of indent mode + add convert dialog
This commit is contained in:
parent
1b8a879291
commit
5936b5d760
|
@ -26,7 +26,7 @@ const
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
TIndentationMode = (imSpaces, imTabs);
|
TIndentationMode = (imNone, imSpaces, imTabs, imMixed);
|
||||||
|
|
||||||
THasMain = (mainNo, mainYes, mainDefaultBehavior);
|
THasMain = (mainNo, mainYes, mainDefaultBehavior);
|
||||||
|
|
||||||
|
@ -299,16 +299,6 @@ type
|
||||||
*)
|
*)
|
||||||
function globToReg(const glob: string ): string;
|
function globToReg(const glob: string ): string;
|
||||||
|
|
||||||
(**
|
|
||||||
* Detects the main indentation mode used in a file
|
|
||||||
*)
|
|
||||||
function indentationMode(strings: TStrings): TIndentationMode;
|
|
||||||
|
|
||||||
(**
|
|
||||||
* Detects the main indentation mode used in a file
|
|
||||||
*)
|
|
||||||
function indentationMode(const fname: string): TIndentationMode;
|
|
||||||
|
|
||||||
(**
|
(**
|
||||||
* Removes duplicate items in strings
|
* Removes duplicate items in strings
|
||||||
*)
|
*)
|
||||||
|
@ -1323,41 +1313,6 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function indentationMode(strings: TStrings): TIndentationMode;
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
s: string;
|
|
||||||
tabs: integer = 0;
|
|
||||||
spcs: integer = 0;
|
|
||||||
begin
|
|
||||||
for s in strings do
|
|
||||||
for i := 1 to s.length do
|
|
||||||
begin
|
|
||||||
case s[i] of
|
|
||||||
#9: tabs += 1;
|
|
||||||
' ': spcs += 1;
|
|
||||||
else break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
if spcs >= tabs then
|
|
||||||
result := imSpaces
|
|
||||||
else
|
|
||||||
result := imTabs;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function indentationMode(const fname: string): TIndentationMode;
|
|
||||||
var
|
|
||||||
str: TStringList;
|
|
||||||
begin
|
|
||||||
str := TStringList.Create;
|
|
||||||
try
|
|
||||||
str.LoadFromFile(fname);
|
|
||||||
result := indentationMode(str);
|
|
||||||
finally
|
|
||||||
str.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function openUrl(const value: string): boolean;
|
function openUrl(const value: string): boolean;
|
||||||
{$IFDEF WINDOWS}
|
{$IFDEF WINDOWS}
|
||||||
function GetDefaultBrowserForCurrentUser: String;
|
function GetDefaultBrowserForCurrentUser: String;
|
||||||
|
|
|
@ -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,
|
||||||
md5,
|
md5, Spin,
|
||||||
//SynEditMarkupFoldColoring,
|
//SynEditMarkupFoldColoring,
|
||||||
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
|
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
|
||||||
ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs, ce_dastworx,
|
ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs, ce_dastworx,
|
||||||
|
@ -316,6 +316,8 @@ type
|
||||||
procedure save;
|
procedure save;
|
||||||
procedure saveTempFile;
|
procedure saveTempFile;
|
||||||
//
|
//
|
||||||
|
function indentationMode: TIndentationMode;
|
||||||
|
procedure forceIndentation(m: TIndentationMode; w: integer);
|
||||||
procedure addBreakPoint(line: integer);
|
procedure addBreakPoint(line: integer);
|
||||||
procedure removeBreakPoint(line: integer);
|
procedure removeBreakPoint(line: integer);
|
||||||
procedure curlyBraceCloseAndIndent;
|
procedure curlyBraceCloseAndIndent;
|
||||||
|
@ -396,6 +398,14 @@ type
|
||||||
constructor construct(editor: TCESynMemo);
|
constructor construct(editor: TCESynMemo);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TMixedIndetationDialog = class(TForm)
|
||||||
|
private
|
||||||
|
class var fSpacesPerTab: integer;
|
||||||
|
procedure spinSpacesPerTabChange(sender: TObject);
|
||||||
|
public
|
||||||
|
constructor construct();
|
||||||
|
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;
|
||||||
|
@ -470,13 +480,13 @@ begin
|
||||||
Font.Size:= FontSize;
|
Font.Size:= FontSize;
|
||||||
result := inherited CalcHintRect(MaxWidth, AHint, AData);
|
result := inherited CalcHintRect(MaxWidth, AHint, AData);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$REGION TSortDialog -----------------------------------------------------------}
|
{$REGION TSortDialog -----------------------------------------------------------}
|
||||||
constructor TSortDialog.construct(editor: TCESynMemo);
|
constructor TSortDialog.construct(editor: TCESynMemo);
|
||||||
var
|
var
|
||||||
pnl: TPanel;
|
pnl: TPanel;
|
||||||
begin
|
begin
|
||||||
inherited Create(nil);
|
inherited Create(nil);
|
||||||
|
BorderStyle:= bsToolWindow;
|
||||||
fEditor := editor;
|
fEditor := editor;
|
||||||
|
|
||||||
width := 150;
|
width := 150;
|
||||||
|
@ -560,6 +570,64 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
|
{$REGION TMixedIndetationDialog}
|
||||||
|
constructor TMixedIndetationDialog.construct();
|
||||||
|
begin
|
||||||
|
inherited create(nil);
|
||||||
|
BorderStyle:= bsToolWindow;
|
||||||
|
caption := 'Indentation converter';
|
||||||
|
Position:= TPosition.poMainFormCenter;
|
||||||
|
fSpacesPerTab := 4;
|
||||||
|
with TButton.Create(self) do
|
||||||
|
begin
|
||||||
|
Align:= alBottom;
|
||||||
|
parent := self;
|
||||||
|
caption := 'Do nothing';
|
||||||
|
AutoSize:= true;
|
||||||
|
ModalResult:= 1;
|
||||||
|
BorderSpacing.Around:=4;
|
||||||
|
end;
|
||||||
|
with TSpinEdit.Create(self) do
|
||||||
|
begin
|
||||||
|
value := fSpacesPerTab;
|
||||||
|
Align:= alTop;
|
||||||
|
parent := self;
|
||||||
|
Caption := 'Spaces per TAB';
|
||||||
|
MinValue:= 1;
|
||||||
|
MaxValue:= 8;
|
||||||
|
BorderSpacing.Around:=4;
|
||||||
|
OnChange:= @spinSpacesPerTabChange;
|
||||||
|
hint := 'defines how many spaces per TAB will be used';
|
||||||
|
ShowHint:=true;
|
||||||
|
end;
|
||||||
|
with TButton.Create(self) do
|
||||||
|
begin
|
||||||
|
Align:= alTop;
|
||||||
|
parent := self;
|
||||||
|
caption := 'Always use tabs';
|
||||||
|
AutoSize:= true;
|
||||||
|
ModalResult:= 10;
|
||||||
|
BorderSpacing.Around:=4;
|
||||||
|
end;
|
||||||
|
with TButton.Create(self) do
|
||||||
|
begin
|
||||||
|
Align:= alTop;
|
||||||
|
parent := self;
|
||||||
|
caption := 'Always use spaces';
|
||||||
|
AutoSize:= true;
|
||||||
|
ModalResult:= 11;
|
||||||
|
BorderSpacing.Around:=4;
|
||||||
|
end;
|
||||||
|
width := ScaleX(280, 96);
|
||||||
|
height := ScaleY(150, 96);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMixedIndetationDialog.spinSpacesPerTabChange(sender: TObject);
|
||||||
|
begin
|
||||||
|
self.fSpacesPerTab:= TSpinEdit(sender).Value;
|
||||||
|
end;
|
||||||
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGION TCESynMemoCache -------------------------------------------------------}
|
{$REGION TCESynMemoCache -------------------------------------------------------}
|
||||||
constructor TCESynMemoCache.create(aComponent: TComponent);
|
constructor TCESynMemoCache.create(aComponent: TComponent);
|
||||||
begin
|
begin
|
||||||
|
@ -1374,6 +1442,93 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCESynMemo.indentationMode: TIndentationMode;
|
||||||
|
function checkLine(index: integer): TIndentationMode;
|
||||||
|
var
|
||||||
|
u: string;
|
||||||
|
begin
|
||||||
|
result := imNone;
|
||||||
|
u := Lines[index];
|
||||||
|
if (u.length > 0) and (u[1] = #9) then
|
||||||
|
result := imTabs
|
||||||
|
else if (u.length > 1) and (u[1..2] = ' ') then
|
||||||
|
result := imSpaces;
|
||||||
|
end;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
t: integer = 0;
|
||||||
|
s: integer = 0;
|
||||||
|
begin
|
||||||
|
for i:= 0 to lines.count-1 do
|
||||||
|
begin
|
||||||
|
result := checkLine(i);
|
||||||
|
t += byte(result = imTabs);
|
||||||
|
s += byte(result = imSpaces);
|
||||||
|
end;
|
||||||
|
if (t <> 0) and (s <> 0) then
|
||||||
|
result := imMixed
|
||||||
|
else if t = 0 then
|
||||||
|
result := imSpaces
|
||||||
|
else if s = 0 then
|
||||||
|
result := imTabs
|
||||||
|
else
|
||||||
|
result := imNone;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCESynMemo.forceIndentation(m: TIndentationMode; w: integer);
|
||||||
|
var
|
||||||
|
s: string;
|
||||||
|
i: integer;
|
||||||
|
p: integer;
|
||||||
|
c: integer;
|
||||||
|
b: string;
|
||||||
|
begin
|
||||||
|
for i:= 0 to lines.Count-1 do
|
||||||
|
begin
|
||||||
|
c := 0;
|
||||||
|
p := 1;
|
||||||
|
s := lines.Strings[i];
|
||||||
|
case m of
|
||||||
|
imTabs:
|
||||||
|
begin
|
||||||
|
while p <= s.length do
|
||||||
|
begin
|
||||||
|
if s[p] = ' ' then
|
||||||
|
c+=1
|
||||||
|
else break;
|
||||||
|
p += 1;
|
||||||
|
end;
|
||||||
|
if c >= w then
|
||||||
|
begin
|
||||||
|
setLength(b, c div w);
|
||||||
|
FillChar(b[1], b.length, #9);
|
||||||
|
s := b + s[c+1 .. s.length];
|
||||||
|
lines[i] := s;
|
||||||
|
fModified:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
imSpaces:
|
||||||
|
begin
|
||||||
|
while p <= s.length do
|
||||||
|
begin
|
||||||
|
if s[p] = #9 then
|
||||||
|
c+=1
|
||||||
|
else break;
|
||||||
|
p += 1;
|
||||||
|
end;
|
||||||
|
if c > 0 then
|
||||||
|
begin
|
||||||
|
setLength(b, c * w);
|
||||||
|
FillChar(b[1], b.length, ' ');
|
||||||
|
s := b + s[c+1 .. s.length];
|
||||||
|
lines[i] := s;
|
||||||
|
fModified:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCESynMemo.insertLeadingDDocSymbol(c: char);
|
procedure TCESynMemo.insertLeadingDDocSymbol(c: char);
|
||||||
begin
|
begin
|
||||||
BeginUndoBlock;
|
BeginUndoBlock;
|
||||||
|
@ -2853,12 +3008,34 @@ begin
|
||||||
loadCache;
|
loadCache;
|
||||||
fCacheLoaded := true;
|
fCacheLoaded := true;
|
||||||
end;
|
end;
|
||||||
if detectIndentMode then
|
case indentationMode() of
|
||||||
begin
|
imTabs:
|
||||||
case indentationMode(lines) of
|
if detectIndentMode then
|
||||||
imTabs: Options:= Options - [eoTabsToSpaces];
|
Options:= Options - [eoTabsToSpaces];
|
||||||
imSpaces: Options:= Options + [eoTabsToSpaces];
|
imSpaces:
|
||||||
end;
|
if detectIndentMode then
|
||||||
|
Options:= Options + [eoTabsToSpaces];
|
||||||
|
imMixed:
|
||||||
|
if (isDSource or alwaysAdvancedFeatures) and
|
||||||
|
(dlgYesNo('Mixed indentation style detected, ' +
|
||||||
|
'do you wish to convert to a single mode ?') = mrYes) then
|
||||||
|
with TMixedIndetationDialog.construct() do
|
||||||
|
try
|
||||||
|
case ShowModal of
|
||||||
|
10:
|
||||||
|
begin
|
||||||
|
forceIndentation(imTabs, TMixedIndetationDialog.fSpacesPerTab);
|
||||||
|
Options:= Options - [eoTabsToSpaces];
|
||||||
|
end;
|
||||||
|
11:
|
||||||
|
begin
|
||||||
|
forceIndentation(imSpaces, TMixedIndetationDialog.fSpacesPerTab);
|
||||||
|
Options:= Options + [eoTabsToSpaces];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
free;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
|
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
|
||||||
fCanDscan := true;
|
fCanDscan := true;
|
||||||
|
|
Loading…
Reference in New Issue