@@ -180,14 +180,43 @@ protected override void Initialize()
180
180
var commandService = GetService ( typeof ( IMenuCommandService ) ) as OleMenuCommandService ;
181
181
if ( commandService != null )
182
182
{
183
- var menuCommandID = new CommandID ( GuidList . guidClangFormatCmdSet , ( int ) PkgCmdIDList . cmdidClangFormat ) ;
184
- var menuItem = new MenuCommand ( MenuItemCallback , menuCommandID ) ;
185
- commandService . AddCommand ( menuItem ) ;
183
+ {
184
+ var menuCommandID = new CommandID ( GuidList . guidClangFormatCmdSet , ( int ) PkgCmdIDList . cmdidClangFormatSelection ) ;
185
+ var menuItem = new MenuCommand ( MenuItemCallback , menuCommandID ) ;
186
+ commandService . AddCommand ( menuItem ) ;
187
+ }
188
+
189
+ {
190
+ var menuCommandID = new CommandID ( GuidList . guidClangFormatCmdSet , ( int ) PkgCmdIDList . cmdidClangFormatDocument ) ;
191
+ var menuItem = new MenuCommand ( MenuItemCallback , menuCommandID ) ;
192
+ commandService . AddCommand ( menuItem ) ;
193
+ }
186
194
}
187
195
}
188
196
#endregion
189
197
190
198
private void MenuItemCallback ( object sender , EventArgs args )
199
+ {
200
+ var mc = sender as System . ComponentModel . Design . MenuCommand ;
201
+ if ( mc == null )
202
+ return ;
203
+
204
+ switch ( mc . CommandID . ID )
205
+ {
206
+ case ( int ) PkgCmdIDList . cmdidClangFormatSelection :
207
+ FormatSelection ( ) ;
208
+ break ;
209
+
210
+ case ( int ) PkgCmdIDList . cmdidClangFormatDocument :
211
+ FormatDocument ( ) ;
212
+ break ;
213
+ }
214
+ }
215
+
216
+ /// <summary>
217
+ /// Runs clang-format on the current selection
218
+ /// </summary>
219
+ private void FormatSelection ( )
191
220
{
192
221
IWpfTextView view = GetCurrentView ( ) ;
193
222
if ( view == null )
@@ -197,24 +226,40 @@ private void MenuItemCallback(object sender, EventArgs args)
197
226
int start = view . Selection . Start . Position . GetContainingLine ( ) . Start . Position ;
198
227
int end = view . Selection . End . Position . GetContainingLine ( ) . End . Position ;
199
228
int length = end - start ;
229
+
200
230
// clang-format doesn't support formatting a range that starts at the end
201
231
// of the file.
202
232
if ( start >= text . Length && text . Length > 0 )
203
233
start = text . Length - 1 ;
204
234
string path = GetDocumentParent ( view ) ;
205
235
string filePath = GetDocumentPath ( view ) ;
236
+
237
+ RunClangFormatAndApplyReplacements ( text , start , length , path , filePath , view ) ;
238
+ }
239
+
240
+ /// <summary>
241
+ /// Runs clang-format on the current document
242
+ /// </summary>
243
+ private void FormatDocument ( )
244
+ {
245
+ IWpfTextView view = GetCurrentView ( ) ;
246
+ if ( view == null )
247
+ // We're not in a text view.
248
+ return ;
249
+
250
+ string filePath = GetDocumentPath ( view ) ;
251
+ var path = Path . GetDirectoryName ( filePath ) ;
252
+ string text = view . TextBuffer . CurrentSnapshot . GetText ( ) ;
253
+
254
+ RunClangFormatAndApplyReplacements ( text , 0 , text . Length , path , filePath , view ) ;
255
+ }
256
+
257
+ private void RunClangFormatAndApplyReplacements ( string text , int offset , int length , string path , string filePath , IWpfTextView view )
258
+ {
206
259
try
207
260
{
208
- var root = XElement . Parse ( RunClangFormat ( text , start , length , path , filePath ) ) ;
209
- var edit = view . TextBuffer . CreateEdit ( ) ;
210
- foreach ( XElement replacement in root . Descendants ( "replacement" ) )
211
- {
212
- var span = new Span (
213
- int . Parse ( replacement . Attribute ( "offset" ) . Value ) ,
214
- int . Parse ( replacement . Attribute ( "length" ) . Value ) ) ;
215
- edit . Replace ( span , replacement . Value ) ;
216
- }
217
- edit . Apply ( ) ;
261
+ string replacements = RunClangFormat ( text , offset , length , path , filePath ) ;
262
+ ApplyClangFormatReplacements ( replacements , view ) ;
218
263
}
219
264
catch ( Exception e )
220
265
{
@@ -304,6 +349,27 @@ private string RunClangFormat(string text, int offset, int length, string path,
304
349
return output ;
305
350
}
306
351
352
+ /// <summary>
353
+ /// Applies the clang-format replacements (xml) to the current view
354
+ /// </summary>
355
+ private void ApplyClangFormatReplacements ( string replacements , IWpfTextView view )
356
+ {
357
+ // clang-format returns no replacements if input text is empty
358
+ if ( replacements . Length == 0 )
359
+ return ;
360
+
361
+ var root = XElement . Parse ( replacements ) ;
362
+ var edit = view . TextBuffer . CreateEdit ( ) ;
363
+ foreach ( XElement replacement in root . Descendants ( "replacement" ) )
364
+ {
365
+ var span = new Span (
366
+ int . Parse ( replacement . Attribute ( "offset" ) . Value ) ,
367
+ int . Parse ( replacement . Attribute ( "length" ) . Value ) ) ;
368
+ edit . Replace ( span , replacement . Value ) ;
369
+ }
370
+ edit . Apply ( ) ;
371
+ }
372
+
307
373
/// <summary>
308
374
/// Returns the currently active view if it is a IWpfTextView.
309
375
/// </summary>
0 commit comments