Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Merge pull request #42 from kamilskoracki/jump-to-word
Browse files Browse the repository at this point in the history
Jump to word
  • Loading branch information
Kraviecc authored May 29, 2019
2 parents 1d4abd5 + fdd524d commit ed3ce45
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 369 deletions.
1 change: 1 addition & 0 deletions CocoJumper.Base/CocoJumper.Base.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<Compile Include="EventModels\SearchEvent.cs" />
<Compile Include="EventModels\SearchResultEvent.cs" />
<Compile Include="EventModels\StartNewSearchEvent.cs" />
<Compile Include="Exception\NotFoundException.cs" />
<Compile Include="Exception\InvalidStateException.cs" />
<Compile Include="Logic\ICocoJumperLogic.cs" />
<Compile Include="Logic\TaggerCommon.cs" />
Expand Down
9 changes: 9 additions & 0 deletions CocoJumper.Base/Exception/NotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace CocoJumper.Base.Exception
{
public class NotFoundException : System.Exception
{
public NotFoundException(string message) : base(message)
{
}
}
}
1 change: 1 addition & 0 deletions CocoJumper/CocoJumper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Compile Include="CodeHighlighterTag\CodeHighlighterTaggerProvider.cs" />
<Compile Include="CodeMarkerTag\CodeMarkerTagger.cs" />
<Compile Include="CodeMarkerTag\CodeMarkerTaggerProvider.cs" />
<Compile Include="Commands\CocoJumperBaseCommand.cs" />
<Compile Include="Commands\CocoJumperMultiSearchCommand.cs" />
<Compile Include="Commands\CocoJumperCommandPackage.cs" />
<Compile Include="Commands\CocoJumperOptions.cs">
Expand Down
114 changes: 114 additions & 0 deletions CocoJumper/Commands/CocoJumperBaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using CocoJumper.Base.Enum;
using CocoJumper.Base.Events;
using CocoJumper.Base.Exception;
using CocoJumper.Base.Logic;
using CocoJumper.Events;
using CocoJumper.Extensions;
using CocoJumper.Listeners;
using CocoJumper.Logic;
using CocoJumper.Provider;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using System;
using System.ComponentModel.Design;
using System.Threading.Tasks;

namespace CocoJumper.Commands
{
internal abstract class CocoJumperBaseCommand
{
protected ICocoJumperLogic Logic;
private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService;
private readonly AsyncPackage _package;
private readonly IVsTextManager _vsTextManager;
private InputListener _inputListener;

protected CocoJumperBaseCommand(AsyncPackage package,
OleMenuCommandService commandService,
IVsTextManager textManager,
IVsEditorAdaptersFactoryService editorAdaptersFactoryService,
IEventAggregator eventAggregator,
Guid commandSet,
int commandId)
{
_package = package ?? throw new ArgumentNullException(nameof(package));

_vsTextManager = textManager ?? throw new ArgumentNullException(nameof(textManager));
_editorAdaptersFactoryService = editorAdaptersFactoryService ?? throw new ArgumentNullException(nameof(editorAdaptersFactoryService));

eventAggregator.AddListener(new DelegateListener<ExitEvent>(OnExit), true);

commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
CommandID menuCommandID = new CommandID(commandSet, commandId);
MenuCommand menuItem = new MenuCommand(Execute, menuCommandID);
commandService.AddCommand(menuItem);
}

protected IAsyncServiceProvider ServiceProvider
{
get { return _package; }
}

protected static async
Task<(OleMenuCommandService commandService,
IVsTextManager vsTextManager,
IVsEditorAdaptersFactoryService editor,
IEventAggregator eventAggregator)> GetServicesAsync(AsyncPackage package)
{
OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
IVsTextManager vsTextManager = await package.GetServiceAsync(typeof(SVsTextManager)) as IVsTextManager;
IComponentModel componentModel = await package.GetServiceAsync(typeof(SComponentModel)) as IComponentModel
?? throw new NotFoundException($"{nameof(IComponentModel)} not found.");
IVsEditorAdaptersFactoryService editor = componentModel.GetService<IVsEditorAdaptersFactoryService>();
IEventAggregator eventAggregator = componentModel.GetService<IEventAggregator>();

await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

return (commandService, vsTextManager, editor, eventAggregator);
}

protected void Execute(object sender, EventArgs e)
{
ThreadHelper.ThrowIfNotOnUIThread();
IVsTextView textView = _vsTextManager.GetActiveView();
IWpfTextView wpfTextView = _editorAdaptersFactoryService.GetWpfTextView(textView);
CocoJumperCommandPackage cocoJumperCommandPackage = (CocoJumperCommandPackage)_package;

CleanupLogicAndInputListener();
WpfViewProvider renderer = new WpfViewProvider(wpfTextView);

Logic = new CocoJumperLogic(renderer, cocoJumperCommandPackage);
_inputListener = new InputListener(textView);
_inputListener.KeyPressEvent += OnKeyboardAction;

ExecutePostAction();
}

protected abstract void ExecutePostAction();

protected void OnExit(ExitEvent e)
{
CleanupLogicAndInputListener();
}

protected void OnKeyboardAction(object oSender, char? key, KeyEventType eventType)
{
Logic = Logic ?? throw new Exception($"{nameof(OnKeyboardAction)} in {nameof(CocoJumperBaseCommand)}, {nameof(Logic)} is null");
if (Logic.KeyboardAction(key, eventType) == CocoJumperKeyboardActionResult.Finished)
{
CleanupLogicAndInputListener();
}
}

private void CleanupLogicAndInputListener()
{
Logic?.Dispose();
_inputListener?.Dispose();
Logic = null;
_inputListener = null;
}
}
}
53 changes: 27 additions & 26 deletions CocoJumper/Commands/CocoJumperCommandPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,84 +11,85 @@ namespace CocoJumper.Commands
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[ProvideOptionPage(typeof(CocoJumperOptions), "Environment\\Keyboard", "CocoJumper", 0, 0, true, ProvidesLocalizedCategoryName = false)]
[ProvideOptionPage(typeof(CocoJumperOptions), "Environment\\Keyboard", "CocoJumper",
0, 0, true, ProvidesLocalizedCategoryName = false)]
[Guid(PackageGuidString)]
public sealed class CocoJumperCommandPackage : AsyncPackage
{
public const string PackageGuidString = "cd8f3565-1f57-4c09-b5c1-01fe488ab080";

protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
MefProvider.ComponentModel = await GetServiceAsync(typeof(SComponentModel)) as IComponentModel;
await CocoJumperMultiSearchCommand.InitializeAsync(this);
await CocoJumperSingleSearchCommand.InitializeAsync(this);
await CocoJumperSingleSearchHighlightCommand.InitializeAsync(this);
await base.InitializeAsync(cancellationToken, progress);
await CocoJumper.Commands.CocoJumperWordSearchCommand.InitializeAsync(this);
}

public int LimitResults
public int AutomaticallyExitInterval
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.LimitResults;
return page.AutomaticallyExitInterval;
}
}

public int TimerInterval
public bool DisableHighlightForMultiSearch
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.TimerInterval;
return page.DisableHighlightForMultiSearch;
}
}

public bool JumpAfterChoosedElement
public bool DisableHighlightForSingleHighlight
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.JumpAfterChoosedElement;
return page.DisableHighlightForSingleHighlight;
}
}

public int AutomaticallyExitInterval
public bool DisableHighlightForSingleSearch
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.AutomaticallyExitInterval;
return page.DisableHighlightForSingleSearch;
}
}

public bool DisableHighlightForMultiSearch
public bool JumpAfterChosenElement
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.DisableHighlightForMultiSearch;
return page.JumpAfterChosenElement;
}
}

public bool DisableHighlightForSingleHighlight
public int LimitResults
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.DisableHighlightForSingleHighlight;
return page.LimitResults;
}
}

public bool DisableHighlightForSingleSearch
public int TimerInterval
{
get
{
CocoJumperOptions page = (CocoJumperOptions)GetDialogPage(typeof(CocoJumperOptions));
return page.DisableHighlightForSingleSearch;
return page.TimerInterval;
}
}

protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
MefProvider.ComponentModel = await GetServiceAsync(typeof(SComponentModel)) as IComponentModel;
await CocoJumperMultiSearchCommand.InitializeAsync(this);
await CocoJumperSingleSearchCommand.InitializeAsync(this);
await CocoJumperSingleSearchHighlightCommand.InitializeAsync(this);
await CocoJumperWordSearchCommand.InitializeAsync(this);
await base.InitializeAsync(cancellationToken, progress);
}
}
}
85 changes: 12 additions & 73 deletions CocoJumper/Commands/CocoJumperMultiSearchCommand.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,24 @@
using CocoJumper.Base.Enum;
using CocoJumper.Base.Events;
using CocoJumper.Base.Logic;
using CocoJumper.Events;
using CocoJumper.Extensions;
using CocoJumper.Listeners;
using CocoJumper.Logic;
using CocoJumper.Provider;
using Microsoft;
using Microsoft.VisualStudio.ComponentModelHost;
using CocoJumper.Events;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using System;
using System.ComponentModel.Design;
using Task = System.Threading.Tasks.Task;

namespace CocoJumper.Commands
{
internal class CocoJumperMultiSearchCommand
internal class CocoJumperMultiSearchCommand : CocoJumperBaseCommand
{
public const int CommandId = 0x0100;

public static readonly Guid CommandSet = new Guid("29fda481-672d-4ce9-9793-0bebf8b4c6c8");
private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService;
private readonly AsyncPackage _package;
private readonly IVsTextManager _vsTextManager;
private InputListener _inputListener;
private ICocoJumperLogic _logic;

private CocoJumperMultiSearchCommand(AsyncPackage package, OleMenuCommandService commandService, IVsTextManager textManager, IVsEditorAdaptersFactoryService editorAdaptersFactoryService, IEventAggregator eventAggregator)
private CocoJumperMultiSearchCommand(AsyncPackage package, OleMenuCommandService commandService,
IVsTextManager textManager, IVsEditorAdaptersFactoryService editorAdaptersFactoryService,
IEventAggregator eventAggregator)
: base(package, commandService, textManager, editorAdaptersFactoryService,
eventAggregator, CommandSet, CommandId)
{
this._package = package ?? throw new ArgumentNullException(nameof(package));
commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
_vsTextManager = textManager ?? throw new ArgumentNullException(nameof(textManager));
this._editorAdaptersFactoryService = editorAdaptersFactoryService ?? throw new ArgumentNullException(nameof(editorAdaptersFactoryService));
eventAggregator.AddListener(new DelegateListener<ExitEvent>(OnExit), true);

CommandID menuCommandId = new CommandID(CommandSet, CommandId);
MenuCommand menuItem = new MenuCommand(Execute, menuCommandId);
commandService.AddCommand(menuItem);
}

public static CocoJumperMultiSearchCommand Instance
Expand All @@ -48,57 +27,17 @@ public static CocoJumperMultiSearchCommand Instance
private set;
}

private IAsyncServiceProvider ServiceProvider => _package;

public static async Task InitializeAsync(AsyncPackage package)
{
OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
IVsTextManager vsTextManager = await package.GetServiceAsync(typeof(SVsTextManager)) as IVsTextManager;
IComponentModel componentModel = await package.GetServiceAsync(typeof(SComponentModel)) as IComponentModel;
Assumes.Present(componentModel);
IVsEditorAdaptersFactoryService editor = componentModel.GetService<IVsEditorAdaptersFactoryService>();
IEventAggregator eventAggregator = componentModel.GetService<IEventAggregator>();

await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
Instance = new CocoJumperMultiSearchCommand(package, commandService, vsTextManager, editor, eventAggregator);
}

private void CleanupLogicAndInputListener()
{
_logic?.Dispose();
_inputListener?.Dispose();
_logic = null;
_inputListener = null;
}
var (commandService, vsTextManager, editor, eventAggregator) = await GetServicesAsync(package);

private void Execute(object sender, EventArgs e)
{
ThreadHelper.ThrowIfNotOnUIThread();
IVsTextView textView = _vsTextManager.GetActiveView();
IWpfTextView wpfTextView = _editorAdaptersFactoryService.GetWpfTextView(textView);
CocoJumperCommandPackage cocoJumperCommandPackage = (CocoJumperCommandPackage)_package;

CleanupLogicAndInputListener();
WpfViewProvider renderer = new WpfViewProvider(wpfTextView);
_logic = new CocoJumperLogic(renderer, cocoJumperCommandPackage);

_inputListener = new InputListener(textView);
_inputListener.KeyPressEvent += OnKeyboardAction;
_logic.ActivateSearching(false, false, false);
}

private void OnExit(ExitEvent e)
{
CleanupLogicAndInputListener();
Instance = new CocoJumperMultiSearchCommand(package, commandService,
vsTextManager, editor, eventAggregator);
}

private void OnKeyboardAction(object oSender, char? key, KeyEventType eventType)
protected override void ExecutePostAction()
{
_logic = _logic ?? throw new Exception($"{nameof(OnKeyboardAction)} in {nameof(CocoJumperMultiSearchCommand)}, {nameof(_logic)} is null");
if (_logic.KeyboardAction(key, eventType) == CocoJumperKeyboardActionResult.Finished)
{
CleanupLogicAndInputListener();
}
Logic.ActivateSearching(false, false, false);
}
}
}
2 changes: 1 addition & 1 deletion CocoJumper/Commands/CocoJumperOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class CocoJumperOptions : DialogPage
[DisplayName("Jump after choosed element")]
[Description("If set to True, logic will move caret to the end of choosed element.")]
[DefaultValue(false)]
public bool JumpAfterChoosedElement { get; set; } = false;
public bool JumpAfterChosenElement { get; set; } = false;

[Category(GeneralCategory)]
[DisplayName("Limit results")]
Expand Down
Loading

0 comments on commit ed3ce45

Please sign in to comment.