Editor command

This commit is contained in:
2023-08-22 10:23:52 +02:00
parent 43c9d3ce76
commit 506636789c
8 changed files with 204 additions and 10 deletions

View File

@@ -0,0 +1,7 @@
namespace FileTime.App.Core.Configuration;
public class ProgramsConfigurationRoot
{
public ProgramsConfiguration Linux { get; set; } = new();
public ProgramsConfiguration Windows { get; set; } = new();
}

View File

@@ -0,0 +1,9 @@
using FileTime.App.Core.Configuration;
namespace FileTime.App.Core.Services;
public interface IProgramsService
{
ProgramConfiguration? GetEditorProgram(bool getNext = false);
void ResetLastGoodEditor();
}

View File

@@ -0,0 +1,14 @@
namespace FileTime.App.Core.UserCommand;
public class EditCommand : IIdentifiableUserCommand
{
public const string CommandName = "edit";
public static readonly EditCommand Instance = new();
private EditCommand()
{
}
public string UserCommandID => CommandName;
public string Title => "Edit";
}

View File

@@ -6,7 +6,7 @@ namespace FileTime.App.Core.Configuration;
public class MainConfiguration
{
private static readonly Lazy<List<CommandBindingConfiguration>> _defaultKeybindings = new(InitDefaultKeyBindings);
private static readonly Lazy<List<CommandBindingConfiguration>> DefaultKeybindings = new(InitDefaultKeyBindings);
public static Dictionary<string, string?> Configuration { get; }
@@ -18,7 +18,7 @@ public class MainConfiguration
};
PopulateDefaultEditorPrograms(Configuration);
PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value,
PopulateDefaultKeyBindings(Configuration, DefaultKeybindings.Value,
SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings));
}
@@ -60,7 +60,7 @@ public class MainConfiguration
new(CreateContainer.CommandName, new[] {Keys.C, Keys.C}),
new(CreateElementCommand.CommandName, new[] {Keys.C, Keys.E}),
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Keys.D, Keys.D }),
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Keys.F4)),
new(EditCommand.CommandName, new[] {Keys.F4}),
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Comma, shift: true)),
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Question, shift: true)),
new(GoBackCommand.CommandName, new KeyConfig(Keys.Left, alt: true)),
@@ -120,23 +120,35 @@ public class MainConfiguration
private static void PopulateDefaultEditorPrograms(Dictionary<string, string?> configuration)
{
var editorPrograms = new List<ProgramConfiguration>()
var linuxEditorPrograms = new List<ProgramConfiguration>
{
new(@"gedit"),
};
var windowsEditorPrograms = new List<ProgramConfiguration>
{
new(@"c:\Program Files\Notepad++\notepad++.exe"),
new("notepad.exe"),
};
PopulateDefaultEditorPrograms(configuration, linuxEditorPrograms, nameof(ProgramsConfigurationRoot.Linux));
PopulateDefaultEditorPrograms(configuration, windowsEditorPrograms, nameof(ProgramsConfigurationRoot.Windows));
}
private static void PopulateDefaultEditorPrograms(
Dictionary<string, string?> configuration,
List<ProgramConfiguration> editorPrograms,
string os)
{
for (var i = 0; i < editorPrograms.Count; i++)
{
if (editorPrograms[i].Path is not { } path) continue;
configuration.Add(
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}",
$"{SectionNames.ProgramsSectionName}:{os}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}",
path);
if (editorPrograms[i].Arguments is { } arguments)
{
configuration.Add(
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}",
$"{SectionNames.ProgramsSectionName}:{os}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}",
arguments);
}
}

View File

@@ -0,0 +1,91 @@
using System.Runtime.InteropServices;
using FileTime.App.Core.Configuration;
using Microsoft.Extensions.Options;
namespace FileTime.App.Core.Services;
public class ProgramsService : IProgramsService
{
private enum Os
{
Linux,
Windows,
}
private readonly Os _os;
private readonly IOptionsMonitor<ProgramsConfigurationRoot> _configuration;
private int _lastGoodEditorProgramIndex;
private readonly List<ProgramConfiguration> _lastEditorPrograms = new();
public ProgramsService(IOptionsMonitor<ProgramsConfigurationRoot> configuration)
{
_configuration = configuration;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_os = Os.Windows;
}
else
{
_os = Os.Linux;
}
}
public ProgramConfiguration? GetEditorProgram(bool getNext = false)
{
GeneratePrograms();
if (getNext)
{
_lastGoodEditorProgramIndex++;
}
if (_lastGoodEditorProgramIndex < 0)
{
_lastGoodEditorProgramIndex = 0;
}
if (_lastEditorPrograms.Count <= _lastGoodEditorProgramIndex)
{
ResetLastGoodEditor();
return null;
}
return _lastEditorPrograms[_lastGoodEditorProgramIndex];
}
private void GeneratePrograms()
{
var programsConfig = _os switch
{
Os.Windows => _configuration.CurrentValue.Windows,
_ => _configuration.CurrentValue.Linux
};
var programConfigs = programsConfig.EditorPrograms.Count == 0
? programsConfig.DefaultEditorPrograms
: programsConfig.EditorPrograms.Concat(programsConfig.DefaultEditorPrograms).ToList();
var generateNew = programConfigs.Count != _lastEditorPrograms.Count;
if (!generateNew)
{
for (var i = 0; i < programConfigs.Count; i++)
{
if (programConfigs[i].Path != _lastEditorPrograms[i].Path
|| programConfigs[i].Arguments != _lastEditorPrograms[i].Arguments)
{
generateNew = true;
break;
}
}
}
if (generateNew)
{
_lastEditorPrograms.Clear();
_lastEditorPrograms.AddRange(programConfigs);
_lastGoodEditorProgramIndex = -1;
}
}
public void ResetLastGoodEditor() => _lastGoodEditorProgramIndex = -1;
}

View File

@@ -9,6 +9,7 @@ using FileTime.Core.Enums;
using FileTime.Core.Interactions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using Microsoft.Extensions.Logging;
namespace FileTime.App.Core.Services.UserCommandHandler;
@@ -22,6 +23,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
private readonly IUserCommandHandlerService _userCommandHandlerService;
private readonly IContentAccessorFactory _contentAccessorFactory;
private readonly IContainerSizeScanProvider _containerSizeScanProvider;
private readonly IProgramsService _programsService;
private readonly ILogger<ToolUserCommandHandlerService> _logger;
private IDeclarativeProperty<IContainer?>? _currentLocation;
private IDeclarativeProperty<IItemViewModel?>? _currentSelectedItem;
private ITabViewModel? _currentSelectedTab;
@@ -35,7 +38,9 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
ITimelessContentProvider timelessContentProvider,
IUserCommandHandlerService userCommandHandlerService,
IContentAccessorFactory contentAccessorFactory,
IContainerSizeScanProvider containerSizeScanProvider) : base(appState)
IContainerSizeScanProvider containerSizeScanProvider,
IProgramsService programsService,
ILogger<ToolUserCommandHandlerService> logger) : base(appState)
{
_systemClipboardService = systemClipboardService;
_userCommunicationService = userCommunicationService;
@@ -45,6 +50,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
_userCommandHandlerService = userCommandHandlerService;
_contentAccessorFactory = contentAccessorFactory;
_containerSizeScanProvider = containerSizeScanProvider;
_programsService = programsService;
_logger = logger;
SaveCurrentLocation(l => _currentLocation = l);
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
SaveSelectedTab(t => _currentSelectedTab = t);
@@ -54,16 +61,68 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
new TypeUserCommandHandler<OpenInDefaultFileExplorerCommand>(OpenInDefaultFileExplorer),
new TypeUserCommandHandler<CopyNativePathCommand>(CopyNativePath),
new TypeUserCommandHandler<CopyBase64Command>(CopyBase64),
new TypeUserCommandHandler<EditCommand>(Edit),
new TypeUserCommandHandler<SearchCommand>(Search),
new TypeUserCommandHandler<ScanSizeCommand>(ScanSize),
new TypeUserCommandHandler<SortItemsCommand>(SortItems),
});
}
private Task Edit()
{
if ( _currentSelectedTab?.CurrentSelectedItem.Value?.BaseItem is not IElement {NativePath: { } filePath})
return Task.CompletedTask;
var getNext = false;
while (true)
{
string? execPath = null;
try
{
var editorProgram = _programsService.GetEditorProgram(getNext);
if (editorProgram is null)
{
break;
}
if (editorProgram.Path is { } executablePath)
{
execPath = executablePath;
if (string.IsNullOrWhiteSpace(editorProgram.Arguments))
{
Process.Start(executablePath, "\"" + filePath + "\"");
}
else
{
var parts = editorProgram.Arguments.Split("%%1");
var arguments = string.Join("%%1", parts.Select(p => p.Replace("%1", "\"" + filePath + "\""))).Replace("%%1", "%1");
Process.Start(executablePath, arguments);
}
}
//TODO: else
break;
}
catch (System.ComponentModel.Win32Exception e)
{
_logger.LogError(e, "Error while running editor program, possible the executable path does not exists. {ExecutablePath}", execPath);
}
catch (Exception e)
{
_logger.LogError(e, "Unknown error while running editor program");
}
getNext = true;
}
//TODO: else
return Task.CompletedTask;
}
private async Task ScanSize()
{
if (_currentLocation?.Value is null) return;
var searchTask = _containerSizeScanProvider.StartSizeScan(_currentLocation.Value);
var openContainerCommand = new OpenContainerCommand(new AbsolutePath(_timelessContentProvider, searchTask.SizeSizeScanContainer));
await _userCommandHandlerService.HandleCommandAsync(openContainerCommand);

View File

@@ -36,6 +36,7 @@ public static class Startup
serviceCollection.TryAddSingleton<ICommandKeysHelperService, CommandKeysHelperService>();
serviceCollection.TryAddSingleton<IPossibleCommandsService, PossibleCommandsService>();
serviceCollection.TryAddSingleton<IPossibleCommandsViewModel, PossibleCommandsViewModel>();
serviceCollection.TryAddSingleton<IProgramsService, ProgramsService>();
return serviceCollection
.AddCommandHandlers()
@@ -53,7 +54,7 @@ public static class Startup
internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection, IConfigurationRoot configuration) =>
serviceCollection
.Configure<ProgramsConfiguration>(configuration.GetSection(SectionNames.ProgramsSectionName))
.Configure<ProgramsConfigurationRoot>(configuration.GetSection(SectionNames.ProgramsSectionName))
.Configure<KeyBindingConfiguration>(configuration.GetSection(SectionNames.KeybindingSectionName))
.AddSingleton<IConfiguration>(configuration);
}

View File

@@ -20,6 +20,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
AddUserCommand(CreateElementCommand.Instance);
AddUserCommand(DeleteCommand.HardDelete);
AddUserCommand(DeleteCommand.SoftDelete);
AddUserCommand(EditCommand.Instance);
AddUserCommand(EnterRapidTravelCommand.Instance);
AddUserCommand(ExitRapidTravelCommand.Instance);
AddUserCommand(GoBackCommand.Instance);