Skip to content

Commit b9dd37c

Browse files
committed
Merge branch 'CodeExplorer' of https://github.com/retailcoder/Rubberduck.git
2 parents 810b421 + 81fc844 commit b9dd37c

File tree

102 files changed

+14996
-4764
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+14996
-4764
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ LibGit2Sharp is the library that has allowed us to integrate Git right into the
105105
106106
Which basically means it's a reimplementation of Git in C. It also [happens to be the technology Microsoft uses for their own Git integration with Visual Studio](http://www.hanselman.com/blog/GitSupportForVisualStudioGitTFSAndVSPutIntoContext.aspx).
107107

108+
###[Smart Indenter](http://www.oaltd.co.uk/Indenter/)
109+
110+
**What is Smart Indenter?**
111+
112+
> *The Smart Indenter is a utility to tidy up VBA code by rebuilding the indentation of each line. Most developers naturally indent code within control structures, such as For...Next, If...End If, etc. Many developers also indent all the code within a procedure, to ease identification of line labels, error handling blocks etc. From that point on, there is much more variety in indenting styles, ranging from how to treat declaration lines to handling end-of-line comments.*
113+
114+
The Rubberduck project was graciously offered the source code for this formidable tool by Stephen Bullen and Rob Bovey. We've translated the VB6 source code to C# and embedded a managed indenting API that Rubberduck calls into, while decoupling the indenter logic from the Windows Registry so we could store indenter options together with the Rubberduck settings, and configure the indenter from Rubberduck's options dialog.
115+
116+
If you're already using Smart Indenter, Rubberduck's options dialog allow importing the settings from the registry. If we did our part well, you can uninstall Smart Indenter after installing Rubberduck 2.0, and still benefit from the smartest indenting tool available for VBA.
117+
108118
##Icons
109119

110120
We didn't come up with these icons ourselves! Here's who did what:

RetailCoder.VBE/App.cs

Lines changed: 96 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
22
using System.Collections.Concurrent;
3-
using System.Collections.Generic;
43
using System.Globalization;
54
using System.Linq;
6-
using System.Runtime.InteropServices;
75
using System.Threading;
86
using System.Threading.Tasks;
97
using System.Windows.Forms;
@@ -13,6 +11,7 @@
1311
using Rubberduck.Inspections;
1412
using Rubberduck.Parsing;
1513
using Rubberduck.Settings;
14+
using Rubberduck.SmartIndenter;
1615
using Rubberduck.UI;
1716
using Rubberduck.UI.Command.MenuItems;
1817
using Rubberduck.UI.ParserErrors;
@@ -30,7 +29,8 @@ public class App : IDisposable
3029
private readonly IGeneralConfigService _configService;
3130
private readonly IAppMenu _appMenus;
3231
private readonly ParserStateCommandBar _stateBar;
33-
private readonly IKeyHook _hook;
32+
private readonly IIndenter _indenter;
33+
private readonly IRubberduckHooks _hooks;
3434

3535
private readonly Logger _logger;
3636

@@ -46,7 +46,8 @@ public App(VBE vbe, IMessageBox messageBox,
4646
IGeneralConfigService configService,
4747
IAppMenu appMenus,
4848
ParserStateCommandBar stateBar,
49-
IKeyHook hook)
49+
IIndenter indenter,
50+
IRubberduckHooks hooks)
5051
{
5152
_vbe = vbe;
5253
_messageBox = messageBox;
@@ -56,36 +57,104 @@ public App(VBE vbe, IMessageBox messageBox,
5657
_configService = configService;
5758
_appMenus = appMenus;
5859
_stateBar = stateBar;
59-
_hook = hook;
60+
_indenter = indenter;
61+
_hooks = hooks;
6062
_logger = LogManager.GetCurrentClassLogger();
6163

62-
_hook.KeyPressed += _hook_KeyPressed;
64+
_hooks.MessageReceived += hooks_MessageReceived;
6365
_configService.SettingsChanged += _configService_SettingsChanged;
6466
_parser.State.StateChanged += Parser_StateChanged;
6567
_stateBar.Refresh += _stateBar_Refresh;
6668
}
6769

68-
private void _stateBar_Refresh(object sender, EventArgs e)
70+
private Keys _firstStepHotKey;
71+
private bool _isAwaitingTwoStepKey;
72+
private bool _skipKeyUp;
73+
74+
private async void hooks_MessageReceived(object sender, HookEventArgs e)
75+
{
76+
if (sender is LowLevelKeyboardHook)
77+
{
78+
if (_skipKeyUp)
79+
{
80+
_skipKeyUp = false;
81+
return;
82+
}
83+
84+
if (_isAwaitingTwoStepKey)
85+
{
86+
// todo: use _firstStepHotKey and e.Key to run 2-step hotkey action
87+
if (_firstStepHotKey == Keys.I && e.Key == Keys.M)
88+
{
89+
_indenter.IndentCurrentModule();
90+
}
91+
92+
AwaitNextKey();
93+
return;
94+
}
95+
96+
var component = _vbe.ActiveCodePane.CodeModule.Parent;
97+
ParseComponentAsync(component);
98+
99+
AwaitNextKey();
100+
return;
101+
}
102+
103+
var hotKey = sender as IHotKey;
104+
if (hotKey == null)
105+
{
106+
AwaitNextKey();
107+
return;
108+
}
109+
110+
if (hotKey.IsTwoStepHotKey)
111+
{
112+
_firstStepHotKey = hotKey.HotKeyInfo.Keys;
113+
AwaitNextKey(true, hotKey.HotKeyInfo);
114+
}
115+
else
116+
{
117+
// todo: use e.Key to run 1-step hotkey action
118+
_firstStepHotKey = Keys.None;
119+
AwaitNextKey();
120+
}
121+
}
122+
123+
private void AwaitNextKey(bool eatNextKey = false, HotKeyInfo info = default(HotKeyInfo))
69124
{
70-
Task.Run(() => ParseAll());
125+
_isAwaitingTwoStepKey = eatNextKey;
126+
foreach (var hook in _hooks.Hooks.OfType<ILowLevelKeyboardHook>())
127+
{
128+
hook.EatNextKey = eatNextKey;
129+
}
130+
131+
_skipKeyUp = eatNextKey;
132+
if (eatNextKey)
133+
{
134+
_stateBar.SetStatusText("(" + info + ") was pressed. Waiting for second key...");
135+
}
136+
else
137+
{
138+
_stateBar.SetStatusText(_parser.State.Status.ToString());
139+
}
71140
}
72141

73-
private void Parser_StateChanged(object sender, EventArgs e)
142+
private void _stateBar_Refresh(object sender, EventArgs e)
74143
{
75-
_appMenus.EvaluateCanExecute(_parser.State);
144+
ParseAll();
76145
}
77146

78-
private async void _hook_KeyPressed(object sender, KeyHookEventArgs e)
147+
private void Parser_StateChanged(object sender, EventArgs e)
79148
{
80-
await ParseComponentAsync(e.Component);
149+
_appMenus.EvaluateCanExecute(_parser.State);
81150
}
82151

83-
private async Task ParseComponentAsync(VBComponent component, bool resolve = true)
152+
private void ParseComponentAsync(VBComponent component, bool resolve = true)
84153
{
85154
var tokenSource = RenewTokenSource(component);
86155

87156
var token = tokenSource.Token;
88-
await _parser.ParseAsync(component, token);
157+
_parser.ParseAsync(component, token);
89158

90159
if (resolve && !token.IsCancellationRequested)
91160
{
@@ -102,8 +171,11 @@ private CancellationTokenSource RenewTokenSource(VBComponent component)
102171
{
103172
CancellationTokenSource existingTokenSource;
104173
_tokenSources.TryRemove(component, out existingTokenSource);
105-
existingTokenSource.Cancel();
106-
existingTokenSource.Dispose();
174+
if (existingTokenSource != null)
175+
{
176+
existingTokenSource.Cancel();
177+
existingTokenSource.Dispose();
178+
}
107179
}
108180

109181
var tokenSource = new CancellationTokenSource();
@@ -124,15 +196,18 @@ public void Startup()
124196
ParseAll();
125197
});
126198

127-
_hook.Attach();
199+
//_hooks.AddHook(new LowLevelKeyboardHook(_vbe));
200+
//_hooks.AddHook(new HotKey((IntPtr)_vbe.MainWindow.HWnd, "%^R", Keys.R));
201+
//_hooks.AddHook(new HotKey((IntPtr)_vbe.MainWindow.HWnd, "%^I", Keys.I));
202+
//_hooks.Attach();
128203
}
129204

130205
private void ParseAll()
131206
{
132207
var components = _vbe.VBProjects.Cast<VBProject>()
133208
.SelectMany(project => project.VBComponents.Cast<VBComponent>());
134209

135-
var result = Parallel.ForEach(components, async component => { await ParseComponentAsync(component, false); });
210+
var result = Parallel.ForEach(components, component => { ParseComponentAsync(component, false); });
136211

137212
if (result.IsCompleted)
138213
{
@@ -182,10 +257,12 @@ private void Setup()
182257

183258
public void Dispose()
184259
{
185-
_hook.KeyPressed -= _hook_KeyPressed;
260+
_hooks.MessageReceived -= hooks_MessageReceived;
186261
_configService.SettingsChanged -= _configService_SettingsChanged;
187262
_parser.State.StateChanged -= Parser_StateChanged;
188263

264+
_hooks.Dispose();
265+
189266
if (_tokenSources.Any())
190267
{
191268
foreach (var tokenSource in _tokenSources)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Windows.Forms;
3+
4+
namespace Rubberduck.Common
5+
{
6+
public class HookEventArgs : EventArgs
7+
{
8+
private readonly Keys _key;
9+
private static readonly Lazy<HookEventArgs> _empty = new Lazy<HookEventArgs>(() => new HookEventArgs(Keys.None));
10+
11+
public HookEventArgs(Keys key)
12+
{
13+
_key = key;
14+
}
15+
16+
public Keys Key { get { return _key; } }
17+
18+
public new static HookEventArgs Empty {get { return _empty.Value; }}
19+
}
20+
}

0 commit comments

Comments
 (0)