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 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; } public static Dictionary<string, string?> Configuration { get; }
@@ -18,7 +18,7 @@ public class MainConfiguration
}; };
PopulateDefaultEditorPrograms(Configuration); PopulateDefaultEditorPrograms(Configuration);
PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, PopulateDefaultKeyBindings(Configuration, DefaultKeybindings.Value,
SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings)); SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings));
} }
@@ -60,7 +60,7 @@ public class MainConfiguration
new(CreateContainer.CommandName, new[] {Keys.C, Keys.C}), new(CreateContainer.CommandName, new[] {Keys.C, Keys.C}),
new(CreateElementCommand.CommandName, new[] {Keys.C, Keys.E}), new(CreateElementCommand.CommandName, new[] {Keys.C, Keys.E}),
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Keys.D, Keys.D }), //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.Comma, shift: true)),
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Question, shift: true)), new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Question, shift: true)),
new(GoBackCommand.CommandName, new KeyConfig(Keys.Left, alt: 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) 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"), 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++) for (var i = 0; i < editorPrograms.Count; i++)
{ {
if (editorPrograms[i].Path is not { } path) continue; if (editorPrograms[i].Path is not { } path) continue;
configuration.Add( configuration.Add(
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", $"{SectionNames.ProgramsSectionName}:{os}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}",
path); path);
if (editorPrograms[i].Arguments is { } arguments) if (editorPrograms[i].Arguments is { } arguments)
{ {
configuration.Add( configuration.Add(
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", $"{SectionNames.ProgramsSectionName}:{os}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}",
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.Interactions;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
using Microsoft.Extensions.Logging;
namespace FileTime.App.Core.Services.UserCommandHandler; namespace FileTime.App.Core.Services.UserCommandHandler;
@@ -22,6 +23,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly IUserCommandHandlerService _userCommandHandlerService;
private readonly IContentAccessorFactory _contentAccessorFactory; private readonly IContentAccessorFactory _contentAccessorFactory;
private readonly IContainerSizeScanProvider _containerSizeScanProvider; private readonly IContainerSizeScanProvider _containerSizeScanProvider;
private readonly IProgramsService _programsService;
private readonly ILogger<ToolUserCommandHandlerService> _logger;
private IDeclarativeProperty<IContainer?>? _currentLocation; private IDeclarativeProperty<IContainer?>? _currentLocation;
private IDeclarativeProperty<IItemViewModel?>? _currentSelectedItem; private IDeclarativeProperty<IItemViewModel?>? _currentSelectedItem;
private ITabViewModel? _currentSelectedTab; private ITabViewModel? _currentSelectedTab;
@@ -35,7 +38,9 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
ITimelessContentProvider timelessContentProvider, ITimelessContentProvider timelessContentProvider,
IUserCommandHandlerService userCommandHandlerService, IUserCommandHandlerService userCommandHandlerService,
IContentAccessorFactory contentAccessorFactory, IContentAccessorFactory contentAccessorFactory,
IContainerSizeScanProvider containerSizeScanProvider) : base(appState) IContainerSizeScanProvider containerSizeScanProvider,
IProgramsService programsService,
ILogger<ToolUserCommandHandlerService> logger) : base(appState)
{ {
_systemClipboardService = systemClipboardService; _systemClipboardService = systemClipboardService;
_userCommunicationService = userCommunicationService; _userCommunicationService = userCommunicationService;
@@ -45,6 +50,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
_userCommandHandlerService = userCommandHandlerService; _userCommandHandlerService = userCommandHandlerService;
_contentAccessorFactory = contentAccessorFactory; _contentAccessorFactory = contentAccessorFactory;
_containerSizeScanProvider = containerSizeScanProvider; _containerSizeScanProvider = containerSizeScanProvider;
_programsService = programsService;
_logger = logger;
SaveCurrentLocation(l => _currentLocation = l); SaveCurrentLocation(l => _currentLocation = l);
SaveCurrentSelectedItem(i => _currentSelectedItem = i); SaveCurrentSelectedItem(i => _currentSelectedItem = i);
SaveSelectedTab(t => _currentSelectedTab = t); SaveSelectedTab(t => _currentSelectedTab = t);
@@ -54,16 +61,68 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
new TypeUserCommandHandler<OpenInDefaultFileExplorerCommand>(OpenInDefaultFileExplorer), new TypeUserCommandHandler<OpenInDefaultFileExplorerCommand>(OpenInDefaultFileExplorer),
new TypeUserCommandHandler<CopyNativePathCommand>(CopyNativePath), new TypeUserCommandHandler<CopyNativePathCommand>(CopyNativePath),
new TypeUserCommandHandler<CopyBase64Command>(CopyBase64), new TypeUserCommandHandler<CopyBase64Command>(CopyBase64),
new TypeUserCommandHandler<EditCommand>(Edit),
new TypeUserCommandHandler<SearchCommand>(Search), new TypeUserCommandHandler<SearchCommand>(Search),
new TypeUserCommandHandler<ScanSizeCommand>(ScanSize), new TypeUserCommandHandler<ScanSizeCommand>(ScanSize),
new TypeUserCommandHandler<SortItemsCommand>(SortItems), 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() private async Task ScanSize()
{ {
if (_currentLocation?.Value is null) return; if (_currentLocation?.Value is null) return;
var searchTask = _containerSizeScanProvider.StartSizeScan(_currentLocation.Value); var searchTask = _containerSizeScanProvider.StartSizeScan(_currentLocation.Value);
var openContainerCommand = new OpenContainerCommand(new AbsolutePath(_timelessContentProvider, searchTask.SizeSizeScanContainer)); var openContainerCommand = new OpenContainerCommand(new AbsolutePath(_timelessContentProvider, searchTask.SizeSizeScanContainer));
await _userCommandHandlerService.HandleCommandAsync(openContainerCommand); await _userCommandHandlerService.HandleCommandAsync(openContainerCommand);

View File

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

View File

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