Bladeren bron

ADD: Multi-rename - only replace the first occurrence of the search string

Alexander Koblov 3 jaren geleden
bovenliggende
commit
1d7e6737fe
3 gewijzigde bestanden met toevoegingen van 108 en 56 verwijderingen
  1. 65 43
      src/fmultirename.lfm
  2. 3 1
      src/fmultirename.lrj
  3. 40 12
      src/fmultirename.pas

+ 65 - 43
src/fmultirename.lfm

@@ -358,36 +358,6 @@ object frmMultiRename: TfrmMultiRename
           ParentColor = False
           ParentFont = False
         end
-        object cbRegExp: TCheckBox
-          AnchorSideLeft.Control = gbFindReplace
-          AnchorSideTop.Control = edReplace
-          AnchorSideTop.Side = asrBottom
-          Left = 4
-          Height = 23
-          Top = 116
-          Width = 149
-          BorderSpacing.Top = 4
-          Caption = 'Regular e&xpressions'
-          OnChange = cbRegExpChange
-          ParentFont = False
-          TabOrder = 2
-        end
-        object cbUseSubs: TCheckBox
-          AnchorSideLeft.Control = gbFindReplace
-          AnchorSideTop.Control = cbRegExp
-          AnchorSideTop.Side = asrBottom
-          AnchorSideBottom.Side = asrBottom
-          Left = 4
-          Height = 23
-          Top = 141
-          Width = 126
-          BorderSpacing.Top = 2
-          Caption = '&Use substitution'
-          Enabled = False
-          OnChange = cbNameStyleChange
-          ParentFont = False
-          TabOrder = 3
-        end
         object edFind: TEdit
           AnchorSideLeft.Control = gbFindReplace
           AnchorSideTop.Control = lbFind
@@ -420,19 +390,71 @@ object frmMultiRename: TfrmMultiRename
           ParentFont = False
           TabOrder = 1
         end
-        object cbCaseSens: TCheckBox
-          AnchorSideLeft.Control = cbRegExp
-          AnchorSideLeft.Side = asrBottom
-          AnchorSideTop.Control = cbRegExp
-          Left = 140
-          Height = 19
-          Hint = 'Case sensitive'
-          Top = 88
-          Width = 42
-          BorderSpacing.Left = 12
-          Caption = 'A≠a'
-          OnChange = cbNameStyleChange
-          TabOrder = 4
+        object pnlFindReplace: TPanel
+          AnchorSideLeft.Control = edReplace
+          AnchorSideTop.Control = edReplace
+          AnchorSideTop.Side = asrBottom
+          AnchorSideRight.Control = edReplace
+          AnchorSideRight.Side = asrBottom
+          Left = 4
+          Height = 46
+          Top = 86
+          Width = 318
+          Anchors = [akTop, akLeft, akRight]
+          AutoSize = True
+          BevelOuter = bvNone
+          ChildSizing.TopBottomSpacing = 2
+          ChildSizing.HorizontalSpacing = 12
+          ChildSizing.VerticalSpacing = 2
+          ChildSizing.Layout = cclLeftToRightThenTopToBottom
+          ChildSizing.ControlsPerLine = 2
+          ClientHeight = 46
+          ClientWidth = 318
+          TabOrder = 2
+          object cbRegExp: TCheckBox
+            Left = 0
+            Height = 19
+            Top = 4
+            Width = 124
+            BorderSpacing.Top = 4
+            Caption = 'Regular e&xpressions'
+            OnChange = cbRegExpChange
+            ParentFont = False
+            TabOrder = 0
+          end
+          object cbCaseSens: TCheckBox
+            Left = 136
+            Height = 19
+            Hint = 'Case sensitive'
+            Top = 4
+            Width = 42
+            Caption = 'A≠a'
+            OnChange = cbNameStyleChange
+            TabOrder = 2
+          end
+          object cbUseSubs: TCheckBox
+            AnchorSideBottom.Side = asrBottom
+            Left = 0
+            Height = 19
+            Top = 25
+            Width = 124
+            BorderSpacing.Top = 2
+            Caption = '&Use substitution'
+            Enabled = False
+            OnChange = cbNameStyleChange
+            ParentFont = False
+            TabOrder = 1
+          end
+          object cbOnlyFirst: TCheckBox
+            Left = 136
+            Height = 19
+            Hint = 'Replace only once per file'
+            Top = 25
+            Width = 42
+            Caption = '1x'
+            OnChange = cbNameStyleChange
+            TabOrder = 3
+          end
         end
       end
       object btnEditor: TBitBtn

+ 3 - 1
src/fmultirename.lrj

@@ -11,9 +11,11 @@
 {"hash":218395566,"name":"tfrmmultirename.lbfind.caption","sourcebytes":[38,70,105,110,100,46,46,46],"value":"&Find..."},
 {"hash":35724926,"name":"tfrmmultirename.lbreplace.caption","sourcebytes":[82,101,38,112,108,97,99,101,46,46,46],"value":"Re&place..."},
 {"hash":20463635,"name":"tfrmmultirename.cbregexp.caption","sourcebytes":[82,101,103,117,108,97,114,32,101,38,120,112,114,101,115,115,105,111,110,115],"value":"Regular e&xpressions"},
-{"hash":121437630,"name":"tfrmmultirename.cbusesubs.caption","sourcebytes":[38,85,115,101,32,115,117,98,115,116,105,116,117,116,105,111,110],"value":"&Use substitution"},
 {"hash":219672053,"name":"tfrmmultirename.cbcasesens.hint","sourcebytes":[67,97,115,101,32,115,101,110,115,105,116,105,118,101],"value":"Case sensitive"},
 {"hash":5223265,"name":"tfrmmultirename.cbcasesens.caption","sourcebytes":[65,226,137,160,97],"value":"A\u2260a"},
+{"hash":121437630,"name":"tfrmmultirename.cbusesubs.caption","sourcebytes":[38,85,115,101,32,115,117,98,115,116,105,116,117,116,105,111,110],"value":"&Use substitution"},
+{"hash":54067429,"name":"tfrmmultirename.cbonlyfirst.hint","sourcebytes":[82,101,112,108,97,99,101,32,111,110,108,121,32,111,110,99,101,32,112,101,114,32,102,105,108,101],"value":"Replace only once per file"},
+{"hash":904,"name":"tfrmmultirename.cbonlyfirst.caption","sourcebytes":[49,120],"value":"1x"},
 {"hash":174873218,"name":"tfrmmultirename.gbcounter.caption","sourcebytes":[67,111,117,110,116,101,114],"value":"Counter"},
 {"hash":42119666,"name":"tfrmmultirename.lbstnb.caption","sourcebytes":[83,38,116,97,114,116,32,78,117,109,98,101,114],"value":"S&tart Number"},
 {"hash":49,"name":"tfrmmultirename.edpoc.text","sourcebytes":[49],"value":"1"},

+ 40 - 12
src/fmultirename.pas

@@ -67,6 +67,7 @@ type
     FRegExp: boolean;
     FUseSubs: boolean;
     FCaseSens: Boolean;
+    FOnlyFirst: Boolean;
     FCounter: string;
     FInterval: string;
     FWidth: integer;
@@ -84,6 +85,7 @@ type
     property RegExp: boolean read FRegExp write FRegExp;
     property UseSubs: boolean read FUseSubs write FUseSubs;
     property CaseSens: Boolean read FCaseSens write FCaseSens;
+    property OnlyFirst: Boolean read FOnlyFirst write FOnlyFirst;
     property Counter: string read FCounter write FCounter;
     property Interval: string read FInterval write FInterval;
     property Width: integer read FWidth write FWidth;
@@ -123,6 +125,10 @@ type
   { TfrmMultiRename }
   TfrmMultiRename = class(TAloneForm, IFormCommands)
     cbCaseSens: TCheckBox;
+    cbRegExp: TCheckBox;
+    cbUseSubs: TCheckBox;
+    cbOnlyFirst: TCheckBox;
+    pnlFindReplace: TPanel;
     pnlButtons: TPanel;
     StringGrid: TStringGrid;
     pnlOptions: TPanel;
@@ -146,8 +152,6 @@ type
     edFind: TEdit;
     lbReplace: TLabel;
     edReplace: TEdit;
-    cbRegExp: TCheckBox;
-    cbUseSubs: TCheckBox;
     gbCounter: TGroupBox;
     lbStNb: TLabel;
     edPoc: TEdit;
@@ -465,6 +469,7 @@ begin
   FRegExp := False;
   FUseSubs := False;
   FCaseSens := False;
+  FOnlyFirst := False;
   FCounter := '1';
   FInterval := '1';
   FWidth := 0;
@@ -978,6 +983,7 @@ begin
             AMultiRenamePreset.RegExp := AConfig.GetValue(ANode, 'RegExp', False);
             AMultiRenamePreset.UseSubs := AConfig.GetValue(ANode, 'UseSubs', False);
             AMultiRenamePreset.CaseSens := AConfig.GetValue(ANode, 'CaseSensitive', False);
+            AMultiRenamePreset.OnlyFirst := AConfig.GetValue(ANode, 'OnlyFirst', False);
             AMultiRenamePreset.Counter := AConfig.GetValue(ANode, 'Counter', '1');
             AMultiRenamePreset.Interval := AConfig.GetValue(ANode, 'Interval', '1');
             AMultiRenamePreset.Width := AConfig.GetValue(ANode, 'Width', 0);
@@ -1077,6 +1083,7 @@ begin
     FMultiRenamePresetList.MultiRenamePreset[PresetIndex].RegExp := cbRegExp.Checked;
     FMultiRenamePresetList.MultiRenamePreset[PresetIndex].UseSubs := cbUseSubs.Checked;
     FMultiRenamePresetList.MultiRenamePreset[PresetIndex].CaseSens := cbCaseSens.Checked;
+    FMultiRenamePresetList.MultiRenamePreset[PresetIndex].OnlyFirst := cbOnlyFirst.Checked;
     FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Counter := edPoc.Text;
     FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Interval := edInterval.Text;
     FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Width := cmbxWidth.ItemIndex;
@@ -1130,6 +1137,7 @@ begin
     AConfig.AddValue(SubNode, 'RegExp', FMultiRenamePresetList.MultiRenamePreset[i].RegExp);
     AConfig.AddValue(SubNode, 'UseSubs', FMultiRenamePresetList.MultiRenamePreset[i].UseSubs);
     AConfig.AddValue(SubNode, 'CaseSensitive', FMultiRenamePresetList.MultiRenamePreset[i].CaseSens);
+    AConfig.AddValue(SubNode, 'OnlyFirst', FMultiRenamePresetList.MultiRenamePreset[i].OnlyFirst);
     AConfig.AddValue(SubNode, 'Counter', FMultiRenamePresetList.MultiRenamePreset[i].Counter);
     AConfig.AddValue(SubNode, 'Interval', FMultiRenamePresetList.MultiRenamePreset[i].Interval);
     AConfig.AddValue(SubNode, 'Width', FMultiRenamePresetList.MultiRenamePreset[i].Width);
@@ -2035,7 +2043,9 @@ function TfrmMultiRename.FreshText(ItemIndex: integer): string;
 var
   I: integer;
   bError: boolean;
-  Flags: TReplaceFlags;
+  wsText: UnicodeString;
+  wsReplace: UnicodeString;
+  Flags: TReplaceFlags = [];
   sTmpName, sTmpExt: string;
 begin
   bError := False;
@@ -2058,16 +2068,32 @@ begin
   if (edFind.Text <> '') then
   begin
     if cbRegExp.Checked then
-      try
-        FRegExp.ModifierI := not cbCaseSens.Checked;
-        Result := UTF16ToUTF8(FRegExp.Replace(CeUtf8ToUtf16(Result), CeUtf8ToUtf16(edReplace.Text), cbUseSubs.Checked));
-      except
-        Result := rsMsgErrRegExpSyntax;
-        bError := True;
+    try
+      wsText:= CeUtf8ToUtf16(Result);
+      wsReplace:= CeUtf8ToUtf16(edReplace.Text);
+      FRegExp.ModifierI := not cbCaseSens.Checked;
+
+      if not cbOnlyFirst.Checked then
+      begin
+        Result := CeUtf16ToUtf8(FRegExp.Replace(wsText, wsReplace, cbUseSubs.Checked));
       end
-    else
-    begin
-      Flags:= [rfReplaceAll];
+      else if FRegExp.Exec(wsText) then
+      begin
+        Delete(wsText, FRegExp.MatchPos[0], FRegExp.MatchLen[0]);
+        if cbUseSubs.Checked then
+          Insert(FRegExp.Substitute(wsReplace), wsText, FRegExp.MatchPos[0])
+        else begin
+          Insert(wsReplace, wsText, FRegExp.MatchPos[0]);
+        end;
+        Result:= CeUtf16ToUtf8(wsText);
+      end;
+    except
+      Result := rsMsgErrRegExpSyntax;
+      bError := True;
+    end
+    else begin
+      if not cbOnlyFirst.Checked then
+        Flags:= [rfReplaceAll];
       if not cbCaseSens.Checked then
         Flags+= [rfIgnoreCase];
       // Many at once, split find and replace by |
@@ -2246,6 +2272,7 @@ begin
   cbRegExp.Checked := False;
   cbUseSubs.Checked := False;
   cbCaseSens.Checked := False;
+  cbOnlyFirst.Checked := False;
   cbNameMaskStyle.ItemIndex := 0;
   cmbExtensionStyle.ItemIndex := 0;
   edPoc.Text := '1';
@@ -2581,6 +2608,7 @@ begin
         cbRegExp.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].RegExp;
         cbUseSubs.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].UseSubs;
         cbCaseSens.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].CaseSens;
+        cbOnlyFirst.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].OnlyFirst;
         edPoc.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Counter;
         edInterval.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Interval;
         cmbxWidth.ItemIndex := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Width;