Quellcode durchsuchen

Splitting 500 lines long TCustomScpExplorerForm::CustomCommand method

Source commit: dd42f1a4f677d25a70308458611857312b92d959
Martin Prikryl vor 8 Jahren
Ursprung
Commit
6f7192c391
2 geänderte Dateien mit 391 neuen und 351 gelöschten Zeilen
  1. 379 351
      source/forms/CustomScpExplorer.cpp
  2. 12 0
      source/forms/CustomScpExplorer.h

+ 379 - 351
source/forms/CustomScpExplorer.cpp

@@ -1656,451 +1656,479 @@ int __fastcall TCustomScpExplorerForm::CustomCommandState(
   return Result;
 }
 //---------------------------------------------------------------------------
-void __fastcall TCustomScpExplorerForm::CustomCommand(TStrings * FileList,
-  const TCustomCommandType & ACommand, TStrings * ALocalFileList)
+void __fastcall TCustomScpExplorerForm::RemoteCustomCommand(
+  TStrings * FileList, const TCustomCommandType & ACommand,
+  const TCustomCommandData & Data, const UnicodeString & CommandCommand)
 {
+  if (EnsureCommandSessionFallback(fcShellAnyCommand))
+  {
+    TRemoteCustomCommand RemoteCustomCommand(Data, Terminal->CurrentDirectory);
+    TWinInteractiveCustomCommand InteractiveCustomCommand(
+      &RemoteCustomCommand, ACommand.Name, ACommand.HomePage);
 
-  TCustomCommandData Data(Terminal);
-  UnicodeString Site = Terminal->SessionData->SessionKey;
-  UnicodeString HelpKeyword = ACommand.HomePage;
+    UnicodeString Command = InteractiveCustomCommand.Complete(CommandCommand, false);
 
-  std::unique_ptr<TStrings> CustomCommandOptions(CloneStrings(WinConfiguration->CustomCommandOptions));
-  if (ACommand.AnyOptionWithFlag(TCustomCommandType::ofRun))
-  {
-    std::unique_ptr<TCustomCommand> CustomCommandForOptions;
-    if (FLAGCLEAR(ACommand.Params, ccLocal))
-    {
-      CustomCommandForOptions.reset(new TRemoteCustomCommand(Data, Terminal->CurrentDirectory));
-    }
-    else
-    {
-      CustomCommandForOptions.reset(new TLocalCustomCommand(Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory()));
-    }
+    Configuration->Usage->Inc(L"RemoteCustomCommandRuns2");
 
-    if (!DoCustomCommandOptionsDialog(
-           &ACommand, CustomCommandOptions.get(), TCustomCommandType::ofRun, CustomCommandForOptions.get(), Site))
+    bool Capture =
+      FLAGSET(ACommand.Params, ccShowResults) ||
+      FLAGSET(ACommand.Params, ccCopyResults) ||
+      FLAGSET(ACommand.Params, ccShowResultsInMsgBox);
+    TCaptureOutputEvent OutputEvent = NULL;
+
+    DebugAssert(FCapturedLog == NULL);
+    if (Capture)
     {
-      Abort();
+      FCapturedLog = new TStringList();
+      OutputEvent = TerminalCaptureLog;
     }
-  }
 
-  UnicodeString CommandCommand = ACommand.GetCommandWithExpandedOptions(CustomCommandOptions.get(), Site);
-
-  if (FLAGCLEAR(ACommand.Params, ccLocal))
-  {
-    if (EnsureCommandSessionFallback(fcShellAnyCommand))
+    try
     {
-      TRemoteCustomCommand RemoteCustomCommand(Data, Terminal->CurrentDirectory);
-      TWinInteractiveCustomCommand InteractiveCustomCommand(
-        &RemoteCustomCommand, ACommand.Name, ACommand.HomePage);
-
-      UnicodeString Command = InteractiveCustomCommand.Complete(CommandCommand, false);
-
-      Configuration->Usage->Inc(L"RemoteCustomCommandRuns2");
-
-      bool Capture =
-        FLAGSET(ACommand.Params, ccShowResults) ||
-        FLAGSET(ACommand.Params, ccCopyResults) ||
-        FLAGSET(ACommand.Params, ccShowResultsInMsgBox);
-      TCaptureOutputEvent OutputEvent = NULL;
-
-      DebugAssert(FCapturedLog == NULL);
-      if (Capture)
+      if (!RemoteCustomCommand.IsFileCommand(Command))
+      {
+        Terminal->AnyCommand(RemoteCustomCommand.Complete(Command, true),
+          OutputEvent);
+      }
+      else
       {
-        FCapturedLog = new TStringList();
-        OutputEvent = TerminalCaptureLog;
+        Terminal->CustomCommandOnFiles(Command, ACommand.Params, FileList, OutputEvent);
       }
 
-      try
+      if ((FCapturedLog != NULL) && (FCapturedLog->Count > 0))
       {
-        if (!RemoteCustomCommand.IsFileCommand(Command))
+        if (FLAGSET(ACommand.Params, ccCopyResults))
         {
-          Terminal->AnyCommand(RemoteCustomCommand.Complete(Command, true),
-            OutputEvent);
+          CopyToClipboard(FCapturedLog);
         }
-        else
+
+        if (FLAGSET(ACommand.Params, ccShowResults))
         {
-          Terminal->CustomCommandOnFiles(Command, ACommand.Params, FileList, OutputEvent);
+          DoConsoleDialog(Terminal, L"", FCapturedLog);
         }
-
-        if ((FCapturedLog != NULL) && (FCapturedLog->Count > 0))
+        else if (FLAGSET(ACommand.Params, ccShowResultsInMsgBox))
         {
-          if (FLAGSET(ACommand.Params, ccCopyResults))
-          {
-            CopyToClipboard(FCapturedLog);
-          }
-
-          if (FLAGSET(ACommand.Params, ccShowResults))
-          {
-            DoConsoleDialog(Terminal, L"", FCapturedLog);
-          }
-          else if (FLAGSET(ACommand.Params, ccShowResultsInMsgBox))
-          {
-            MessageDialog(FCapturedLog->Text, qtInformation, qaOK);
-          }
+          MessageDialog(FCapturedLog->Text, qtInformation, qaOK);
         }
       }
-      __finally
-      {
-        SAFE_DESTROY(FCapturedLog);
-      }
+    }
+    __finally
+    {
+      SAFE_DESTROY(FCapturedLog);
     }
   }
-  else
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::LocalCustomCommandPure(
+  TStrings * FileList, const TCustomCommandType & ACommand, const UnicodeString & Command, TStrings * ALocalFileList,
+  const TCustomCommandData & Data, bool LocalFileCommand, bool FileListCommand, UnicodeString * POutput)
+{
+  TStrings * LocalFileList = NULL;
+  TStrings * RemoteFileList = NULL;
+  try
   {
-    TLocalCustomCommand LocalCustomCommand(Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory());
-    TWinInteractiveCustomCommand InteractiveCustomCommand(
-      &LocalCustomCommand, ACommand.Name, ACommand.HomePage);
-
-    UnicodeString Command = InteractiveCustomCommand.Complete(CommandCommand, false);
+    if (LocalFileCommand)
+    {
+      if (ALocalFileList == NULL)
+      {
+        DebugAssert(HasDirView[osLocal]);
+        // Cannot have focus on both panels, so we have to call AnyFileSelected
+        // directly (instead of EnableSelectedOperation) to pass
+        // false to FocusedFileOnlyWhenFocused
+        DebugAssert(DirView(osLocal)->AnyFileSelected(false, false, false));
+        LocalFileList = DirView(osLocal)->CreateFileList(false, true, NULL);
+      }
+      else
+      {
+        LocalFileList = ALocalFileList;
+      }
 
-    bool FileListCommand = LocalCustomCommand.IsFileListCommand(Command);
-    bool LocalFileCommand = LocalCustomCommand.HasLocalFileName(Command);
+      if (FileListCommand)
+      {
+        if (LocalFileList->Count != 1)
+        {
+          throw Exception(LoadStr(CUSTOM_COMMAND_SELECTED_UNMATCH1));
+        }
+      }
+      else
+      {
+        if ((LocalFileList->Count != 1) &&
+            (FileList->Count != 1) &&
+            (LocalFileList->Count != FileList->Count))
+        {
+          throw Exception(LoadStr(CUSTOM_COMMAND_SELECTED_UNMATCH));
+        }
+      }
+    }
 
-    Configuration->Usage->Inc(L"LocalCustomCommandRuns2");
+    UnicodeString RootTempDir;
+    UnicodeString TempDir;
 
-    std::unique_ptr<UnicodeString> POutput;
-    if (FLAGSET(ACommand.Params, ccShowResultsInMsgBox) ||
-        FLAGSET(ACommand.Params, ccCopyResults))
+    bool RemoteFiles = FLAGSET(ACommand.Params, ccRemoteFiles);
+    if (!RemoteFiles)
     {
-      POutput.reset(new UnicodeString());
+      TemporarilyDownloadFiles(FileList, false, RootTempDir, TempDir, false, false, true);
     }
 
-    if (!LocalCustomCommand.IsFileCommand(Command))
-    {
-      ExecuteProcessChecked(LocalCustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
-    }
-    // remote files?
-    else if ((FCurrentSide == osRemote) || LocalFileCommand)
+    try
     {
-      TStrings * LocalFileList = NULL;
-      TStrings * RemoteFileList = NULL;
-      try
+      TDateTimes RemoteFileTimes;
+
+      if (RemoteFiles)
       {
-        if (LocalFileCommand)
-        {
-          if (ALocalFileList == NULL)
-          {
-            DebugAssert(HasDirView[osLocal]);
-            // Cannot have focus on both panels, so we have to call AnyFileSelected
-            // directly (instead of EnableSelectedOperation) to pass
-            // false to FocusedFileOnlyWhenFocused
-            DebugAssert(DirView(osLocal)->AnyFileSelected(false, false, false));
-            LocalFileList = DirView(osLocal)->CreateFileList(false, true, NULL);
-          }
-          else
-          {
-            LocalFileList = ALocalFileList;
-          }
+        RemoteFileList = FileList;
+      }
+      else
+      {
+        RemoteFileList = new TStringList();
 
-          if (FileListCommand)
-          {
-            if (LocalFileList->Count != 1)
-            {
-              throw Exception(LoadStr(CUSTOM_COMMAND_SELECTED_UNMATCH1));
-            }
-          }
-          else
-          {
-            if ((LocalFileList->Count != 1) &&
-                (FileList->Count != 1) &&
-                (LocalFileList->Count != FileList->Count))
-            {
-              throw Exception(LoadStr(CUSTOM_COMMAND_SELECTED_UNMATCH));
-            }
-          }
-        }
+        TMakeLocalFileListParams MakeFileListParam;
+        MakeFileListParam.FileList = RemoteFileList;
+        MakeFileListParam.FileTimes = &RemoteFileTimes;
+        MakeFileListParam.IncludeDirs = FLAGSET(ACommand.Params, ccApplyToDirectories);
+        MakeFileListParam.Recursive =
+          FLAGSET(ACommand.Params, ccRecursive) && !FileListCommand;
+
+        ProcessLocalDirectory(TempDir, Terminal->MakeLocalFileList, &MakeFileListParam);
+      }
 
-        UnicodeString RootTempDir;
-        UnicodeString TempDir;
+      bool NonBlocking = FileListCommand && RemoteFiles && !POutput;
 
-        bool RemoteFiles = FLAGSET(ACommand.Params, ccRemoteFiles);
-        if (!RemoteFiles)
-        {
-          TemporarilyDownloadFiles(FileList, false, RootTempDir, TempDir, false, false, true);
-        }
+      TFileOperationProgressType Progress(&OperationProgress, &OperationFinished);
 
-        try
+      if (!NonBlocking)
+      {
+        Progress.Start(foCustomCommand, osRemote, FileListCommand ? 1 : FileList->Count);
+        DebugAssert(FProgressForm != NULL);
+        FProgressForm->ReadOnly = true;
+      }
+
+      try
+      {
+        if (FileListCommand)
         {
-          TDateTimes RemoteFileTimes;
+          UnicodeString LocalFile;
+          // MakeFileList does not delimit filenames
+          UnicodeString FileList = MakeFileList(RemoteFileList);
 
-          if (RemoteFiles)
+          if (LocalFileCommand)
           {
-            RemoteFileList = FileList;
+            DebugAssert(LocalFileList->Count == 1);
+            LocalFile = LocalFileList->Strings[0];
           }
-          else
-          {
-            RemoteFileList = new TStringList();
 
-            TMakeLocalFileListParams MakeFileListParam;
-            MakeFileListParam.FileList = RemoteFileList;
-            MakeFileListParam.FileTimes = &RemoteFileTimes;
-            MakeFileListParam.IncludeDirs = FLAGSET(ACommand.Params, ccApplyToDirectories);
-            MakeFileListParam.Recursive =
-              FLAGSET(ACommand.Params, ccRecursive) && !FileListCommand;
+          TLocalCustomCommand CustomCommand(Data,
+            Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(), L"", LocalFile, FileList);
+          UnicodeString ShellCommand = CustomCommand.Complete(Command, true);
 
-            ProcessLocalDirectory(TempDir, Terminal->MakeLocalFileList, &MakeFileListParam);
+          if (NonBlocking)
+          {
+            DebugAssert(!POutput);
+            ExecuteShellChecked(ShellCommand);
           }
-
-          bool NonBlocking = FileListCommand && RemoteFiles && !POutput;
-
-          TFileOperationProgressType Progress(&OperationProgress, &OperationFinished);
-
-          if (!NonBlocking)
+          else
           {
-            Progress.Start(foCustomCommand, osRemote, FileListCommand ? 1 : FileList->Count);
-            DebugAssert(FProgressForm != NULL);
-            FProgressForm->ReadOnly = true;
+            ExecuteProcessCheckedAndWait(ShellCommand, HelpKeyword, POutput);
           }
-
-          try
+        }
+        else if (LocalFileCommand)
+        {
+          if (LocalFileList->Count == 1)
           {
-            if (FileListCommand)
-            {
-              UnicodeString LocalFile;
-              // MakeFileList does not delimit filenames
-              UnicodeString FileList = MakeFileList(RemoteFileList);
-
-              if (LocalFileCommand)
-              {
-                DebugAssert(LocalFileList->Count == 1);
-                LocalFile = LocalFileList->Strings[0];
-              }
+            UnicodeString LocalFile = LocalFileList->Strings[0];
 
+            for (int Index = 0; Index < RemoteFileList->Count; Index++)
+            {
+              UnicodeString FileName = RemoteFileList->Strings[Index];
               TLocalCustomCommand CustomCommand(Data,
-                Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(), L"", LocalFile, FileList);
-              UnicodeString ShellCommand = CustomCommand.Complete(Command, true);
-
-              if (NonBlocking)
-              {
-                DebugAssert(!POutput);
-                ExecuteShellChecked(ShellCommand);
-              }
-              else
-              {
-                ExecuteProcessCheckedAndWait(ShellCommand, HelpKeyword, POutput.get());
-              }
+                Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(), FileName, LocalFile, L"");
+              ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput);
             }
-            else if (LocalFileCommand)
-            {
-              if (LocalFileList->Count == 1)
-              {
-                UnicodeString LocalFile = LocalFileList->Strings[0];
-
-                for (int Index = 0; Index < RemoteFileList->Count; Index++)
-                {
-                  UnicodeString FileName = RemoteFileList->Strings[Index];
-                  TLocalCustomCommand CustomCommand(Data,
-                    Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(), FileName, LocalFile, L"");
-                  ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
-                }
-              }
-              else if (RemoteFileList->Count == 1)
-              {
-                UnicodeString FileName = RemoteFileList->Strings[0];
-
-                for (int Index = 0; Index < LocalFileList->Count; Index++)
-                {
-                  TLocalCustomCommand CustomCommand(
-                    Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
-                    FileName, LocalFileList->Strings[Index], L"");
-                  ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
-                }
-              }
-              else
-              {
-                if (LocalFileList->Count != RemoteFileList->Count)
-                {
-                  throw Exception(LoadStr(CUSTOM_COMMAND_PAIRS_DOWNLOAD_FAILED));
-                }
+          }
+          else if (RemoteFileList->Count == 1)
+          {
+            UnicodeString FileName = RemoteFileList->Strings[0];
 
-                for (int Index = 0; Index < LocalFileList->Count; Index++)
-                {
-                  UnicodeString FileName = RemoteFileList->Strings[Index];
-                  TLocalCustomCommand CustomCommand(
-                    Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
-                    FileName, LocalFileList->Strings[Index], L"");
-                  ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
-                }
-              }
-            }
-            else
+            for (int Index = 0; Index < LocalFileList->Count; Index++)
             {
-              for (int Index = 0; Index < RemoteFileList->Count; Index++)
-              {
-                TLocalCustomCommand CustomCommand(Data,
-                  Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
-                  RemoteFileList->Strings[Index], L"", L"");
-                ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
-              }
+              TLocalCustomCommand CustomCommand(
+                Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
+                FileName, LocalFileList->Strings[Index], L"");
+              ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput);
             }
           }
-          __finally
+          else
           {
-            if (!NonBlocking)
+            if (LocalFileList->Count != RemoteFileList->Count)
             {
-              Progress.Stop();
+              throw Exception(LoadStr(CUSTOM_COMMAND_PAIRS_DOWNLOAD_FAILED));
             }
-          }
-
-          DebugAssert(!FAutoOperation);
 
-          if (!RemoteFiles)
-          {
-            TempDir = IncludeTrailingBackslash(TempDir);
-            for (int Index = 0; Index < RemoteFileList->Count; Index++)
+            for (int Index = 0; Index < LocalFileList->Count; Index++)
             {
               UnicodeString FileName = RemoteFileList->Strings[Index];
-              if (DebugAlwaysTrue(SameText(TempDir, FileName.SubString(1, TempDir.Length()))) &&
-                  // Skip directories for now, they require recursion,
-                  // and we do not have original nested files times available here yet.
-                  // The check is redundant as FileAge fails for directories anyway.
-                  !DirectoryExists(FileName))
-              {
-                UnicodeString RemoteDir =
-                  UnixExtractFileDir(
-                    UnixIncludeTrailingBackslash(FTerminal->CurrentDirectory) +
-                    ToUnixPath(FileName.SubString(TempDir.Length() + 1, FileName.Length() - TempDir.Length())));
-
-                TDateTime NewTime;
-                if (FileAge(FileName, NewTime) &&
-                    (NewTime != RemoteFileTimes[Index]))
-                {
-                  TGUICopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
-                  TemporaryFileCopyParam(CopyParam);
-                  CopyParam.FileMask = L"";
-
-                  FAutoOperation = true;
-                  std::unique_ptr<TStrings> TemporaryFilesList(new TStringList());
-                  TemporaryFilesList->Add(FileName);
-
-                  FTerminal->CopyToRemote(TemporaryFilesList.get(), RemoteDir, &CopyParam, cpTemporary, NULL);
-                }
-              }
+              TLocalCustomCommand CustomCommand(
+                Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
+                FileName, LocalFileList->Strings[Index], L"");
+              ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput);
             }
           }
         }
-        __finally
+        else
         {
-          FAutoOperation = false;
-          if (!RootTempDir.IsEmpty() && DebugAlwaysTrue(!RemoteFiles))
+          for (int Index = 0; Index < RemoteFileList->Count; Index++)
           {
-            RecursiveDeleteFile(ExcludeTrailingBackslash(RootTempDir), false);
+            TLocalCustomCommand CustomCommand(Data,
+              Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
+              RemoteFileList->Strings[Index], L"", L"");
+            ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput);
           }
         }
       }
       __finally
       {
-        if (RemoteFileList != FileList)
-        {
-          delete RemoteFileList;
-        }
-        if (LocalFileList != ALocalFileList)
+        if (!NonBlocking)
         {
-          delete LocalFileList;
+          Progress.Stop();
         }
       }
-    }
-    // local files
-    else
-    {
-      std::unique_ptr<TStrings> SelectedFileList(DirView(osLocal)->CreateFileList(false, true, NULL));
 
-      std::unique_ptr<TStrings> LocalFileList(new TStringList());
+      DebugAssert(!FAutoOperation);
 
-      for (int Index = 0; Index < SelectedFileList->Count; Index++)
+      if (!RemoteFiles)
       {
-        UnicodeString FileName = SelectedFileList->Strings[Index];
-        if (DirectoryExists(FileName))
+        TempDir = IncludeTrailingBackslash(TempDir);
+        for (int Index = 0; Index < RemoteFileList->Count; Index++)
         {
-          if (FLAGSET(ACommand.Params, ccApplyToDirectories))
+          UnicodeString FileName = RemoteFileList->Strings[Index];
+          if (DebugAlwaysTrue(SameText(TempDir, FileName.SubString(1, TempDir.Length()))) &&
+              // Skip directories for now, they require recursion,
+              // and we do not have original nested files times available here yet.
+              // The check is redundant as FileAge fails for directories anyway.
+              !DirectoryExists(FileName))
           {
-            LocalFileList->Add(FileName);
-          }
+            UnicodeString RemoteDir =
+              UnixExtractFileDir(
+                UnixIncludeTrailingBackslash(FTerminal->CurrentDirectory) +
+                ToUnixPath(FileName.SubString(TempDir.Length() + 1, FileName.Length() - TempDir.Length())));
+
+            TDateTime NewTime;
+            if (FileAge(FileName, NewTime) &&
+                (NewTime != RemoteFileTimes[Index]))
+            {
+              TGUICopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
+              TemporaryFileCopyParam(CopyParam);
+              CopyParam.FileMask = L"";
 
-          if (FLAGSET(ACommand.Params, ccRecursive))
-          {
-            TMakeLocalFileListParams MakeFileListParam;
-            MakeFileListParam.FileList = LocalFileList.get();
-            MakeFileListParam.FileTimes = NULL;
-            MakeFileListParam.IncludeDirs = FLAGSET(ACommand.Params, ccApplyToDirectories);
-            MakeFileListParam.Recursive = true;
+              FAutoOperation = true;
+              std::unique_ptr<TStrings> TemporaryFilesList(new TStringList());
+              TemporaryFilesList->Add(FileName);
 
-            ProcessLocalDirectory(FileName, Terminal->MakeLocalFileList, &MakeFileListParam);
+              FTerminal->CopyToRemote(TemporaryFilesList.get(), RemoteDir, &CopyParam, cpTemporary, NULL);
+            }
           }
         }
-        else
-        {
-          LocalFileList->Add(FileName);
-        }
       }
-
-      if (FileListCommand)
+    }
+    __finally
+    {
+      FAutoOperation = false;
+      if (!RootTempDir.IsEmpty() && DebugAlwaysTrue(!RemoteFiles))
       {
-        UnicodeString FileList = MakeFileList(LocalFileList.get());
-        TLocalCustomCommand CustomCommand(
-          Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
-          L"", L"", FileList);
-        ExecuteProcessChecked(CustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
+        RecursiveDeleteFile(ExcludeTrailingBackslash(RootTempDir), false);
       }
-      else
+    }
+  }
+  __finally
+  {
+    if (RemoteFileList != FileList)
+    {
+      delete RemoteFileList;
+    }
+    if (LocalFileList != ALocalFileList)
+    {
+      delete LocalFileList;
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::LocalCustomCommandWithRemoteFiles(
+  const TCustomCommandType & ACommand, const UnicodeString & Command, const TCustomCommandData & Data,
+  bool FileListCommand, UnicodeString * POutput)
+{
+  std::unique_ptr<TStrings> SelectedFileList(DirView(osLocal)->CreateFileList(false, true, NULL));
+
+  std::unique_ptr<TStrings> LocalFileList(new TStringList());
+
+  for (int Index = 0; Index < SelectedFileList->Count; Index++)
+  {
+    UnicodeString FileName = SelectedFileList->Strings[Index];
+    if (DirectoryExists(FileName))
+    {
+      if (FLAGSET(ACommand.Params, ccApplyToDirectories))
       {
-        TFileOperationProgressType Progress(&OperationProgress, &OperationFinished);
+        LocalFileList->Add(FileName);
+      }
 
-        Progress.Start(foCustomCommand, osRemote, FileListCommand ? 1 : LocalFileList->Count);
-        DebugAssert(FProgressForm != NULL);
-        FProgressForm->ReadOnly = true;
+      if (FLAGSET(ACommand.Params, ccRecursive))
+      {
+        TMakeLocalFileListParams MakeFileListParam;
+        MakeFileListParam.FileList = LocalFileList.get();
+        MakeFileListParam.FileTimes = NULL;
+        MakeFileListParam.IncludeDirs = FLAGSET(ACommand.Params, ccApplyToDirectories);
+        MakeFileListParam.Recursive = true;
 
-        try
-        {
-          for (int Index = 0; Index < LocalFileList->Count; Index++)
-          {
-            UnicodeString FileName = LocalFileList->Strings[Index];
-            TLocalCustomCommand CustomCommand(
-              Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
-              FileName, L"", L"");
-            ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
-          }
-        }
-        __finally
-        {
-          Progress.Stop();
-        }
+        ProcessLocalDirectory(FileName, Terminal->MakeLocalFileList, &MakeFileListParam);
       }
     }
+    else
+    {
+      LocalFileList->Add(FileName);
+    }
+  }
+
+  if (FileListCommand)
+  {
+    UnicodeString FileList = MakeFileList(LocalFileList.get());
+    TLocalCustomCommand CustomCommand(
+      Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
+      L"", L"", FileList);
+    ExecuteProcessChecked(CustomCommand.Complete(Command, true), HelpKeyword, POutput);
+  }
+  else
+  {
+    TFileOperationProgressType Progress(&OperationProgress, &OperationFinished);
 
-    if (POutput.get() != NULL)
+    Progress.Start(foCustomCommand, osRemote, FileListCommand ? 1 : LocalFileList->Count);
+    DebugAssert(FProgressForm != NULL);
+    FProgressForm->ReadOnly = true;
+
+    try
     {
-      // If the output is single-line, we do not want the trailing CRLF, as the CopyToClipboard(TStrings *) does
-      int P = POutput->Pos(sLineBreak);
-      if (P == POutput->Length() - static_cast<int>(strlen(sLineBreak)) + 1)
+      for (int Index = 0; Index < LocalFileList->Count; Index++)
       {
-        POutput->SetLength(P - 1);
-      }
-      // Copy even empty output to clipboard
-      if (FLAGSET(ACommand.Params, ccCopyResults))
-      {
-        CopyToClipboard(*POutput);
+        UnicodeString FileName = LocalFileList->Strings[Index];
+        TLocalCustomCommand CustomCommand(
+          Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory(),
+          FileName, L"", L"");
+        ExecuteProcessCheckedAndWait(CustomCommand.Complete(Command, true), HelpKeyword, POutput);
       }
-      // But do not show an empty message box.
-      // This way the ShowResultsInMsgBox can be used to suppress a console window of commands with no output
-      if (FLAGSET(ACommand.Params, ccShowResultsInMsgBox) &&
-          !POutput->IsEmpty())
-      {
-        TClipboardHandler ClipboardHandler;
-        ClipboardHandler.Text = *POutput;
+    }
+    __finally
+    {
+      Progress.Stop();
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::LocalCustomCommand(TStrings * FileList,
+  const TCustomCommandType & ACommand, TStrings * ALocalFileList,
+  const TCustomCommandData & Data, const UnicodeString & CommandCommand)
+{
+  TLocalCustomCommand LocalCustomCommand(Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory());
+  TWinInteractiveCustomCommand InteractiveCustomCommand(
+    &LocalCustomCommand, ACommand.Name, ACommand.HomePage);
 
-        TMessageParams Params;
-        TQueryButtonAlias Aliases[1];
-        Aliases[0].Button = qaRetry;
-        Aliases[0].Alias = LoadStr(URL_LINK_COPY); // misuse
-        Aliases[0].OnClick = &ClipboardHandler.Copy;
-        Params.Aliases = Aliases;
-        Params.AliasesCount = LENOF(Aliases);
+  UnicodeString Command = InteractiveCustomCommand.Complete(CommandCommand, false);
 
-        MessageDialog(*POutput, qtInformation, qaOK | qaRetry, HelpKeyword, &Params);
-      }
+  bool FileListCommand = LocalCustomCommand.IsFileListCommand(Command);
+  bool LocalFileCommand = LocalCustomCommand.HasLocalFileName(Command);
+
+  Configuration->Usage->Inc(L"LocalCustomCommandRuns2");
+
+  std::unique_ptr<UnicodeString> POutput;
+  if (FLAGSET(ACommand.Params, ccShowResultsInMsgBox) ||
+      FLAGSET(ACommand.Params, ccCopyResults))
+  {
+    POutput.reset(new UnicodeString());
+  }
+
+  if (!LocalCustomCommand.IsFileCommand(Command))
+  {
+    ExecuteProcessChecked(LocalCustomCommand.Complete(Command, true), HelpKeyword, POutput.get());
+  }
+  // remote files?
+  else if ((FCurrentSide == osRemote) || LocalFileCommand)
+  {
+    LocalCustomCommandPure(FileList, ACommand, Command, ALocalFileList, Data, LocalFileCommand, FileListCommand, POutput.get());
+  }
+  // local files
+  else
+  {
+    LocalCustomCommandWithRemoteFiles(ACommand, Command, Data, FileListCommand, POutput.get());
+  }
+
+  if (POutput.get() != NULL)
+  {
+    // If the output is single-line, we do not want the trailing CRLF, as the CopyToClipboard(TStrings *) does
+    int P = POutput->Pos(sLineBreak);
+    if (P == POutput->Length() - static_cast<int>(strlen(sLineBreak)) + 1)
+    {
+      POutput->SetLength(P - 1);
     }
+    // Copy even empty output to clipboard
+    if (FLAGSET(ACommand.Params, ccCopyResults))
+    {
+      CopyToClipboard(*POutput);
+    }
+    // But do not show an empty message box.
+    // This way the ShowResultsInMsgBox can be used to suppress a console window of commands with no output
+    if (FLAGSET(ACommand.Params, ccShowResultsInMsgBox) &&
+        !POutput->IsEmpty())
+    {
+      TClipboardHandler ClipboardHandler;
+      ClipboardHandler.Text = *POutput;
+
+      TMessageParams Params;
+      TQueryButtonAlias Aliases[1];
+      Aliases[0].Button = qaRetry;
+      Aliases[0].Alias = LoadStr(URL_LINK_COPY); // misuse
+      Aliases[0].OnClick = &ClipboardHandler.Copy;
+      Params.Aliases = Aliases;
+      Params.AliasesCount = LENOF(Aliases);
+
+      MessageDialog(*POutput, qtInformation, qaOK | qaRetry, HelpKeyword, &Params);
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::CustomCommand(TStrings * FileList,
+  const TCustomCommandType & ACommand, TStrings * ALocalFileList)
+{
+
+  TCustomCommandData Data(Terminal);
+  UnicodeString Site = Terminal->SessionData->SessionKey;
+  UnicodeString HelpKeyword = ACommand.HomePage;
+
+  std::unique_ptr<TStrings> CustomCommandOptions(CloneStrings(WinConfiguration->CustomCommandOptions));
+  if (ACommand.AnyOptionWithFlag(TCustomCommandType::ofRun))
+  {
+    std::unique_ptr<TCustomCommand> CustomCommandForOptions;
+    if (FLAGCLEAR(ACommand.Params, ccLocal))
+    {
+      CustomCommandForOptions.reset(new TRemoteCustomCommand(Data, Terminal->CurrentDirectory));
+    }
+    else
+    {
+      CustomCommandForOptions.reset(new TLocalCustomCommand(Data, Terminal->CurrentDirectory, DefaultDownloadTargetDirectory()));
+    }
+
+    if (!DoCustomCommandOptionsDialog(
+           &ACommand, CustomCommandOptions.get(), TCustomCommandType::ofRun, CustomCommandForOptions.get(), Site))
+    {
+      Abort();
+    }
+  }
+
+  UnicodeString CommandCommand = ACommand.GetCommandWithExpandedOptions(CustomCommandOptions.get(), Site);
+
+  if (FLAGCLEAR(ACommand.Params, ccLocal))
+  {
+    RemoteCustomCommand(FileList, ACommand, Data, CommandCommand);
+  }
+  else
+  {
+    LocalCustomCommand(FileList, ACommand, ALocalFileList, Data, CommandCommand);
   }
 }
 //---------------------------------------------------------------------------

+ 12 - 0
source/forms/CustomScpExplorer.h

@@ -353,6 +353,18 @@ protected:
   bool __fastcall SetProperties(TOperationSide Side, TStrings * FileList);
   void __fastcall CustomCommand(TStrings * FileList,
     const TCustomCommandType & Command, TStrings * ALocalFileList);
+  void __fastcall RemoteCustomCommand(
+    TStrings * FileList, const TCustomCommandType & ACommand,
+    const TCustomCommandData & Data, const UnicodeString & CommandCommand);
+  void __fastcall LocalCustomCommandPure(
+    TStrings * FileList, const TCustomCommandType & ACommand, const UnicodeString & Command, TStrings * ALocalFileList,
+    const TCustomCommandData & Data, bool LocalFileCommand, bool FileListCommand, UnicodeString * POutput);
+  void __fastcall LocalCustomCommandWithRemoteFiles(
+    const TCustomCommandType & ACommand, const UnicodeString & Command, const TCustomCommandData & Data,
+    bool FileListCommand, UnicodeString * POutput);
+  void __fastcall LocalCustomCommand(TStrings * FileList,
+    const TCustomCommandType & ACommand, TStrings * ALocalFileList,
+    const TCustomCommandData & Data, const UnicodeString & CommandCommand);
   virtual void __fastcall TerminalChanging();
   virtual void __fastcall TerminalChanged();
   virtual void __fastcall QueueChanged();