Saturday, October 30, 2010

Emacs and ReSharper keybindings in Visual Studio

Since committing to Emacs as the text editor to supplement my primary (integrated) development environment, Visual Studio, Emacs has become an indispensable part of my computing life. I run it on any machine I use on a regular basis and sorely miss it when it's not there. It has lived up to its long standing reputation as an extremely powerful text editor that it is more than just a text editor.

I use Visual Studio for C# and .NET coding and Emacs for everything else. Emacs functions as my shell environment (via Eshell with a major assist from Cygwin) when working with file systems local or otherwise. Emacs is where writing and editing Python files, shell scripts, config files, todo lists (with org-mode), notes, and other tasks too trivial to list all take place.

Parsing log files, interacting with source control, and connecting to and running queries on SQL Server have found their way into my Emacs sessions. Also, since editing JavaScript code using Visual Studio 2005 was as mundane and constraining as using Notepad, with no intellisense and no ReSharper magic, Emacs became a more nurturing environment for manipulating JS code. (At least until making the upgrade to Visual Studio 2010 where JavaScript support is vastly improved thereby displacing Emacs in this one activity.)

When using Visual Studio for day-to-day coding sessions in C#, Emacs style keybindings are a must for me. While not as precise as Vim, they do provide me with greater control over the text than the default keybinding most others use in VS or in any other modern, popular IDE or text editor.

ReSharper is what chiefly keeps me relying on Visual Studio to do .NET development. This robust and powerful commercial plug-in for Visual Studio has refactoring and navigation features that are not just superb but they give such control over the code and source files analogous to the power Emacs grants its user with text manipulation.

Initially, adopting Emacs key strokes for Visual Studio was not going to be easy without allowing peaceful co-existence with ReSharper's own extensive list of keyboard shortcuts. Conflicts were inevitable. (These conflicts and how to smoothly resolve them will be covered in more detail.)

Prior to the release of VS2010, the native Emacs keyboard scheme in VS2005 sufficed for coding. To enable it, select on the menu
Tools -> Options -> Environment -> Keyboard -> Apply the following additional keyboard mapping scheme -> Emacs
It provides most of the basic motions and text editing commands found in Emacs ranging from deleting all characters from the cursor to the end of the current line via C-k to moving between words using M-f and M-b. Thus, it gave me the same comforting, familiar experience as coding in Emacs itself.

Unfortunately, upon learning VS2010 would no longer support Emacs keybindings, I needed to find a suitable alternative when upgrading to it from VS2005 (and skipping over Emacs-enabled VS2008). I briefly considered learning VIM either by trying out ViEmu, a commercial VIM emulator for VS, or VsVim, a similar but free extension for VS2010. Fortunately, sanity prevailed and I decided to use XKeymacs, a utility app that applies Emacs style keybindings to any Windows application or program whether it be Word, Outlook, Notepad, Windows Explorer, or cmd.exe. I'd already been using XKeymacs for some time for those other places that I cannot (easily) reach with Emacs itself including composing emails and editing text in web browsers (although I've had some luck with the Firefox add-in, It's All Text!). XKeymacs is far from perfect but works reasonably well.

After using XKeymacs in VS2010 for a bit, I realized that it did a better job than the old native version in VS2005. While XKeymacs has its problems, the built-in Emacs VS keybindings were relatively worse and more aggravating to use in comparison. (Again this will be dissected in more detail.)

Whether you use XKeymacs or the built-in Emacs VS keybindings, I recommend configuring ReSharper to use the "Visual Studio Scheme" and not the "ReSharper 2.x/IDEA scheme" provided in the default install. At first, I did learn and used the (IntelliJ) IDEA scheme when I started with ReSharper mainly because I thought that if I ever were to use the IDEA IDE then the transition would be easier. But, prematurely optimizing for something that might never happen is something to be avoided not just when developing software (if I find myself needing to code in Java I'd probably use Eclipse with Emacs keybindings or Emacs itself).

Choosing the VS scheme over ReSharper's allows for Emacs keybindings to have precedence over the ReSharper keyboard shortcuts whenever possible. The rationale is that Emacs keybindings are far more ubiquitous than ReSharper's. Resharper is limited to Visual Studio (and the aforementioned IntelliJ) while Emacs key shortcuts can be found on a multitude of OS platforms, IDEs, text editors, and shell consoles. It is best to stick with the consistency and prevalence of Emacs style key chords rather than with ones from a niche commercial add-on tool.

Using the Visual Studio scheme for ReSharper does cause problems when working with other team members who use the other ReSharper/IDEA scheme. It's bad enough Emacs keybindings are annoying for someone who sits at my machine and it has not been turned off by the time they type their first character ("Hey, can't I copy? Is Ctrl+C broken? Oh yeah, I forgot, you are using those goofy Emacs keys.").

What's worse (with deeper implications) is when another teammate, knowing a different set of ReSharper shortcuts than I do, attempts to specify a command for me to run. This is likely to occur when pair programming or during code reviews. For example, they might say type Ctrl + n to find the 'Foo' class they recently refactored and it disrupts the flow before we finally figure out that they meant for me to run 'Go to Type' which I know as Ctrl + t. It's like we're speaking to each other in a foreign language. Not good for fostering fluid team collaboration and communication. (This tooling gap occurs with shell commands too since I am fond of using bash on Windows via Cygwin while others are cmd.exe wizards. Typing 'ls' in cmd.exe instead of 'dir' gets odd looks at times.)

Shortly after switching to XKeymacs in VS, a new Emacs Emulation extension for VS2010 was announced that more or less brings back the same old Emacs keyboard scheme from VS2005 (and Visual Studio 2008.) With this new Emacs extension, I was hoping some of the problems that irritated me in the old one which were subsequently magnified when switching to XKeymacs were fixed. But, with the exception of a few things, these annoyances are either still there or behave worse in some cases.

Reasons why I prefer XKeymacs over the VS Emacs keybindings in VS2005 and VS2010:
  • Tabbing and indenting works sanely.
  • Auto formatting works consistently. For example, curly braces line up properly and blocks of code are smartly indented after hitting ENTER. This is not how it behaves in either VS2005 or VS2010 Emacs scheme.
  • DELETE button works by simply pressing it and not requiring to also hit CTRL. Seems blasphemous to care about a key that is not fundamental to Emacs and contradicts my efforts to map the keys faithfully but it's dead simple functionality that should work for any Windows application even if ported from another OS platform. Another nicety of XKeymacs is after selecting text, it supports C-d to delete the entire text not just with the conventional kill command C-w. With VS Emacs, you are limited to just C-w. Granted this is how it also functions in Emacs but it is a nice feature that I would not mind if Emacs supported too out-of-the-box (without requiring adding an Elisp command to remap the key in your .emacs file).
  • Able to overwrite selected text simply by typing and not killing it first (this is the same issue as in the previous item). For example, ReSharper's live templates such as the 'if-statement' code snippet highlights text as contextual placeholders to type custom variable names and values. VS Emacs bindings requires cutting the text via C-w before writing any new text. XKeymacs allows you to just start typing away without that extra step.
  • Copying/yanking text from other applications to VS works as expected (especially from Emacs itself). I never figured out how to get it to work properly in VS2005 Emacs scheme. I suspect the source of the problem was perhaps VS maintaining its own internal kill ring (clipboard) that did not interact well with the Windows clipboard. Sometimes hitting ESC before pasting would help but even that was not reliable. Far worse, VS2010 does not support any copy and paste from external applications (for example, try copying some text from Notepad and then do C-y in VS. You'll see nothing is pasted other than the last yank/kill from within VS)
  • ReSharper's Multiple Entries Clipboard works. It was buggy with the Emacs emulation in VS2005 and in VS2010 it does not work at all.
  • Not limited to just the text editor but able to use XKeymacs everywhere in Visual Studio such as in dialog boxes (e.g. ReSharper's Rename and Find/Replace features), in ReSharper's Navigation and Search features (e.g. in 'Go To Type' and 'View Recent Files'), in other window panes (e.g. the Immediate Window and Solution Explorer) and in textboxes on the menubar (e.g. the extended command-line).
  • Can navigate quickly in Intellisense's dropdown list using C-p and C-n in lieu of the arrows keys (although hitting CTRL for some reason makes the list of values transparent)
  • Does not disable the graphical menu of all open files and window panes when typing CTRL + TAB. It is completely gone from both VS2005 and VS2010 when using VS Emacs scheme.
Despite all of this praise, XKeymacs has a few faults. On occasion it can behave flakey requiring either resetting or closing and then re-running the XKeymacs exe. Another problem is sometimes the ALT key will trigger the file menu instead of (or in addition to) the normal key command.

Regardless, these peculiarities are not enough to keep me from using XKeymacs. However, I use the VS Emacs scheme as fallback whenever XKeymacs acts unbearably goofy. Switching between the two "modes" is fairly quick in my enviroment. XKeymacs has the key command C-q that toggles between disabling and enabling it. In addition, I have created and defined a VS macro that can toggle between the Emacs scheme and the "Default" VS scheme via the key command M-q which I bound to the macro. By combining these two commands, hitting C-q M-q (or M-q C-q) allows me to go back and forth when necessary.

Speaking of macros both XKeymacs and VS Emacs scheme support recording and running macros via the same keys commands used in Emacs proper:
C-x (  recording a macro
    C-x )  stop recording a macro
    C-x e  run the macro
XKeymacs' macro feature works in places you would not expect including applications like Notepad, Outlook, and Word. VS Emacs scheme's macro key chords are hooked into Visual Studio's built-in macro functionality. Discovering both to have support was a surprise to me. I use macros in Emacs quite often. It's great to have this powerful functionality with the same key commands I'm already familiar with.

However, I limit the use of XKeymacs' macros to the simplest of text editing scenarios before turning to alternatives. Sometimes it does behave strangely at which time I might switch over to using VS's macros via Emacs scheme which tends to be a bit more smooth. For more complex editing situations, I'll just open the file in Emacs itself for heavy duty text manipulation.

Configuring Keybindings in Visual Studio

Now follows a list of conflicts and missing keybindings and how best to resolve them. I will include not just how XKeymacs can be configured in VS with ReSharper but also the built-in Emacs VS schemes for both VS2005 and VS2010 (I assume this applies for VS2008 but no guarantees since I've never used it and can not confirm it can be configured the same.)

All key combinations are presented in the traditional Emacs style and format. Specifically, "C-" for "CTRL" and "M-" for "ALT". For example, 'Kill to end of line' is shown as
C-k
instead of
CTRL + k
Also, SHIFT will correspond to the capitalized version of a character such as
C-K
instead of
SHIFT + CTRL + k
To change any key settings in VS go to:
Tools -> Options -> Keyboard 
This is where you'll configure keyboard shortcuts. Generally, you should set the value for 'Use new shortcut in:' to be "Text Editor" (and, if necessary, "HTML Editor") since it overrides any other commands with the same pre-existing key shortcuts that are set to be "Global". If no other commands are using the keybindings (this is evident if any values appear in 'Shortcut currently used by:' dropdown list after pressing the desired keys in 'Press shortcut keys:') then it's safe to just use "Global".

Configuring Keybindings in XKeymacs

When configuring XKeymacs, make certain to select 'devenv.exe' as the specific setting and not the 'Default' value setting. Initially opening XKeymacs' properties always reverts to 'Default' so it is easy to overlook this.

To configure XKeymacs:
In Windows System Tray -> right-click XKeymacs icon (or double-click will automatically open 'Properties) ->
 Properties -> from dropdown list at top of screen, select 'Microsoft Visual Studio .NET (devenv.exe) ->
 select 'Use Specific Setting'
For the 'devenv.exe' setting, I recommend removing all extraneous key commands that serve as duplicates for the basic Emacs commands. These alternate key strokes might include an extra 'SHIFT' (or 'ALT') key press which could override existing non-Emacs VS commands. For example, the command 'forward-char' is typically just C-f but in XKeymacs it can also be called by Shift + Ctrl + f. (In VS, this command is belongs to 'Find All Files' which I use frequently. I'd rather keep it unchanged since I don't need another (more cumbersome) way to move forward one character.

To remove these key commands:
In XKeymacs -> Properties -> change combobox from "Default" to "Microsoft Visual Studio .NET (devenv.exe)" -> Change from 'Use Default Setting' to 'Use Specific Setting' ->
Click 'Advanced' tab -> under 'Category' select "Motion" -> under 'Commands' select "foward-char" -> 
under 'Current keys' select "Ctrl+Shift+B" -> click 'Remove' button
Repeat this for all other commands found under the categories:
  • Search
  • Motion
  • Killing and Deleting
  • Other
Commands that have two or more key bindings associated with them should have their key shortcuts using SHIFT removed. There are a lot of them. Once removed, it should free up some default shortcuts for other VS and ReSharper commands that use the same keys.


Delete Next Character: C-d

XKeymacs Mode:

XKeymacs' command C-d overrides ReSharper's Duplicate Line or Selection command. Instead, set
ReSharper.ReSharper_DuplicateText
to use:
C-D
As mentioned, make sure that XKeymacs is configured to no longer use SHIFT for killing forward characters thus making this available for ReSharper's duplicate text command.

While forward character delete is consistent with Emacs, backward character delete is not only bound to the expected BACKSPACE button as in Emacs, but also bound to C-h. I tend to forget that this exists in XKeymacs since in Emacs proper it is bound to 'Help'. C-h is a better fit for backward delete rather than the infrequently called Help command since it keeps your fingers on home row.

VS Emacs Scheme:

When first hitting C-d and then prompted with 'ReSharper Shortcut Conflict' dialog box, I selected "Use Visual Studio commands" but this does not automatically bind to the 'delete next character' command. The reason is that C-d is reserved for other commands in VS including the family of Debug.* commands. Looking at the documented list of VS Emacs shortcuts, C-Delete is what is expected to be used. This is not consistent with Emacs.

Therefore, manually set the following VS command (using "Text Editor" and not "Global" setting)
Edit.Delete 
to
C-d
Then follow the same steps as XKeymacs mode for reassigning ReSharper's duplicate text command.


Move to the end of the line: C-e

XKeymacs Mode:

Some conflicts with existing ReSharper bindings including 'Insert Live' template, 'Surround With' template, and Code Cleanup. Some of these I use regularly and some I don't. Here are two I do use:

Bind 'Surround With' template command
ReSharper.ReSharper_SurroundWith
to
C-M-j  
The above keybindings is borrowed from the ReSharper 2.x/IDEA scheme.

Bind 'Code Cleanup' command
ReSharper.ReSharper_CleanupCode
to
M-j
The above keybinding is not based on anything other than to be consistent with the previous 'Surround With' command.

VS Emacs Scheme:

When hitting
C-e
you'll be prompted by ReSharper to select which scheme to use whether default VS or ReSharper's (IDEA). Select VS scheme and not ReSharper's. This should be sufficient but make sure that:
Edit.EmacsLineEnd
is bound to
C-e   


Kill region: C-w

XKeymacs Mode:

N/A. Works as expected.

VS Emacs Scheme:

Bind the VS command:
Edit.Cut
to
C-w
Oddly, this standard keybinding of Emacs is not part of the VS Emacs emulation. As an alternative, it recommends using Shift + DELETE. Meanwhile, C-w is bound to Edit.SelectCurrentWord which I thought was ReSharper's similar function but it is actually the native one for VS.

I recommend removing the binding from Edit.SelectCurrentWord and just use ReSharper's equivalent version, 'Extend selection', which already works with C-M-Right Arrow (and conversely 'Shrink Selection' set to C-M-Left Arrow).


Delete (kill) from cursor (point) to end of line: C-k

XKeymacs Mode:

N/A. Works as expected.

VS Emacs Scheme:

Bind the VS command:
Edit.EmacsDeleteToEOL
to
C-k
No (apparent) conflict with ReSharper, but for some reason did not seem bound at all even though according to the list of VS Emacs key shortcuts it should be. Instead, it is by default bound to a whole class of commands such as Edit.CommentSelection.


Tab and Indentation: C-i

XKeymacs Mode:

This works as expected. Hitting ENTER automatically indents the next line to match the previous line.

XKeymacs does not support C-j which inserts newline and indents but it does support C-m which is an alternate to ENTER and only inserts newline. C-m works the same as ENTER in Visual Studio meaning it does smart indenting too and has the advantage that it is easier to hit than ENTER. Regardless, I also bound C-j to Edit.Breakline to use for consistency and convenience.

VS Emacs Scheme:

This is the messy. Tabbing and indenting is one of the weakest and most confusing areas of the VS Emacs scheme. It does not behave how you would expect including interfering with smart indentation.

In both VS2005 and VS2010 Emacs schemes, if you write a line of code and then hit ENTER, the new line will not automatically indent. Instead, ENTER takes the point (cursor) to the first column of the line. You have to hit TAB again to get it to indent. Otherwise, after you start typing some new code, hitting ";" will automatically indent the line to match the preceding one. Both options are not optimal.

Instead, you need to get in the habit of using C-j. This key command is bound to Edit.EmacsBreakLineIndent' which will insert a new line and indent the line correctly.

Hitting TAB on an existing line with text behaves strangely. In VS2010, it toggles tabbing if already tabbed. In VS2005, it does nothing- the line remains unchanged. Once a line is indented, you cannot further indent the line by pressing TAB in either versions of Visual Studio.

To address this issue, I originally bound:
Edit.IncreaseLineIndent 
to
C-M-TAB  
and
Edit.DescreaseLineIndent 
to
Shift-C-M-TAB  
This was really helpful in JS files in VS2005 since no smart indent supported.

However, I then saw this suggested solution to inject additional tabs by using:
C-q TAB
It relies on the Emacs' quoted insert text functionality that VS Emacs scheme also supports via Edit.EmacsQuotedInsert which is bound to C-q.

Unfortunately, C-q conflicts with XKeymacs key command to enable and disable itself which I use fairly heavily. Therefore, I assigned C-Q to Edit.EmacsQuotedInsert and removed the extra keybind from XKeymacs.
XKeymacs -> Under Categories "Other" -> under 'Commands' select "Enable or Disable XKeymacs" -> under 'Current Keys' select Ctrl+ Shift + Q -> click 'Remove'

Finally, for completeness on all-things-tabbing, I thought I could bind
C-i
to
Edit.Indent
but that is reserved by 'Incremental Search' in the default, non-Emacs scheme. I just left it "as is" since it is convenient to have when pair programming with Emacs keybindings turned off.


Delete spaces and tabs around point M-\

XKeymacs Mode:

Bind the VS command:
Edit.DeleteHorizontalWhiteSpace
to
M-\
XKeymacs does not support this command but I use it all the time in Emacs. However, it conflicts with ReSharper's 'Go to File Member'. Therefore I re-mapped
ReSharper.ReSharper_GotoFileMember
to
M-|
VS Emacs Scheme:

Follow the same steps as described for XKeymacs mode.


Expand the word in the buffer before point as a dynamic abbrev: M-/

XKeymacs Mode:

Does not support this command so bind Visual Studio Intellisense/AutoComplete command:
Edit.CompleteWord
to
M-/
VS Emacs Scheme:

N/A. Works as expected.


Running commands by name: M-x

XKeymacs Mode:

XKeymacs supports the keybinding M-x for running external commands in cmd.exe shell, but I never found much use for it since it is awkward to use with no visual feedback of what you just ran.

Therefore, I removed from 'devenv.exe' settings:
In XKeymacs -> under 'Category' select "Other" -> under 'Commands' select 'execute-extended-command' -> under 'Current keys' select "Meta-X" -> click 'Remove' button
Then bind the VS command:
Tools.GoToCommandLine
to
M-x

I use this VS command line feature frequently particularly for TFS source control commands such as
  • File.TfsCompare
  • File.TfsUndoCheckout
  • File.TfsHistory

and to call other commands from the Application Menu such as
  • Tools.Options
  • Tools.AttachProcess
  • File.CopyFullPath (pasting in other applications like emacs itself)
  • bl (alias for Debug.Breakpoints)
  • callstack
  • View.BookmarkWindow (precedes ReSharper 5.0 bookmark)
VS Emacs Scheme:

N/A. Works as expected.


Incremental search forward: C-s

XKeymacs Mode:

Works as expected hooking into VS's
Edit.IncrementalSearch
although not sure how it is automatically bound to it. It is a different command than the traditional 'Find/Replace' command that XKeymacs usually uses in most other Windows application. Regardless, one less thing to bind manually.

VS Emacs Scheme:

N/A. Works as expected.


Incremental search backward: C-r

XKeymacs Mode:

N/A. Works unexpectedly just as incremental search forward.

VS Emacs Scheme:

This is not bound to C-r although C-s is bound to search forward. Instead, the default key shortcut is C-I which is awkward to use when toggling with incremental search forward (C-s). Therefore, mapped the VS command:
Edit.ReverseIncrementalSearch
to
C-r
C-r conflicts with numerous ReSharper refactor mode commands particularly all of the refactoring commands. However, since I tend to use C-R to get list of contextual refactorings and never was in the habit of calling individual refactoring commands, remapping C-r is preferable.


Scroll the selected window so that the current line is the center-most text line: C-l

XKeymacs Mode:

XKeymacs does support this command but it does not work properly in VS. Instead of centering the screen on the current line, it keeps moving the screen one line down.

Therefore, I mapped the following the VS command:
Edit.ScrollLineCenter
to
C-l
and then removed the C-l keybinding from XKeymacs 'devenv.exe' setting by:
XKeymacs -> Advanced -> under 'Category' select "Motion" -> under 'Commands' select "recenter" -> under 'Current keys:' select "Ctrl + L" -> click 'Remove' button
VS Emacs Scheme:

N/A. Works as expected.


Tranpose character: C-t

XKeymacs Mode:

One of the rare circumstances where I chose ReSharper's default key shortcut and ignoring an existing Emacs keybinding. I removed XKeymacs binding of C-t by going into its settings and configuring:
XKeymacs -> Advanced -> under 'Category' select "Killing and Deleting" -> under 'Commands' select "transpose-chars" -> under 'Current keys:' select "Ctrl + T" -> click 'Remove' button
I hardly encounter situations where I need to transpose single characters (although words and lines are more common.) On the other hand, I use Resharper's 'Go to Type' command all the time so I make an exception to keep C-t assigned to it.

Make certain the VS command:
Resharper.Resharper_GoToType
is bound to
C-t
VS Emacs Scheme:

Follow the same steps as described for XKeymacs mode.


Numeric Argument: C--

XKeymacs Mode:

The VS command for navigating backwards is another situation where a VS keybinding wins over an existing Emacs' keybinding:
View.NavigateBackward
is already bound to
C--
However, this conflicts with XKeymacs command 'numeric argument -' for passing negative arguments related to the C-u repetition counts. I never use this and if I do then I would call it via M--. So, kept it unchanged in VS and removed the conflict from XKeymacs 'devenv.exe' settings:
XKeymacs -> Advanced -> under 'Category' select "Other" -> under 'Commands' select "numeric argument -" -> under 'Current keys:' select "Ctrl + -" -> click 'Remove' button
The 'cycle through mark ring' command in Emacs, C-x C-SPC, reminded me of the VS command, View.NavigateBackward. Although not quite the same as VS's feature, it is similar enough for me to also bind these keybindings for consistency.

To do this, find the .xkeymacs config file in the XKeymacs directory.
...\xkeymacs347\etc\English (United States).xkeymacs
Add the line:
(fset 'cycle-mark-ring "\Ctrl+-")
Then configure
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab -> Category 'Original Command' -> 
you should now see the new command, 'cycle-mark-ring', previously added in the config file in the list of commands. To continue:
Under 'Press new shortcut key:' -> check 'Ctrl-X' -> in text field below it, press 'Ctrl-SPACEBAR' -> click 'Assign' -> 'Current keys:' list should now include 'Ctrl-X Ctrl-Space'.
Now in VS, along with C--, C-x C-SPC will also run the navigate backward command when XKeymacs is enabled.

I initially tried to bind to C-u C-SPC but XKeymacs limits prefixing commands with C-x. However, this is for the best since C-x C-SPC is more appropriate because it cycles through all buffers just as the View.NavigateBackward command navigates through all open documents in Visual Studio. That other command only cycles through ones in the current buffer.

I generally stick to using C-- since it is less awkward to type and it is consistent and more fluid to use when switching back and forth with View.NavigateForward which is C-_ (a.k.a. Shift+Ctrl+ -)

VS Emacs Scheme:

Follow same steps as XKeymacs mode.


Undo: C-_

XKeymacs Mode:

The complimentary VS command to previous item 'navigate backward' is of 'navigate forward'
View.NavigateForward
is bound to
C-_

This keybinding conflicts with one of the three existing XKeymacs commands for 'Undo'. Since I always use C-/ for Undo then removed that unnecessary conflicting keybinding:
XKeymacs -> Advanced -> under 'Category' select "Error Recovery" -> under 'Commands' select "undo" -> under 'Current keys:' select "Ctrl + Shift + -" -> click 'Remove' button
VS Emacs Scheme:

A conflict exists since under the VS Emacs scheme
Edit.Undo
is bound to
C-_
Again, since Edit.Undo is also bound to C-/ which is what I only use then remove that binding from the Emacs scheme.


Delete blank lines: C-x C-o

XKeymacs Mode:

This is not supported in XKeymacs but Visual Studio does have this command. It behaves slightly different in VS than in Emacs. In VS, it removes all blanks lines from the cursor and below. Any blank lines above the current blank lines will be ignored. To remove those, you need to call the delete blank lines command again. In Emacs, the equivalent command removes all of the blank lines below and above but leaves the current blank line. To get rid of this line, you need to repeat the same command again.

Now, to use the C-x C-o keybindings requires reconfiguring XKeymacs. First, assign in VS:
Edit.DeleteBlankLines
to
M-o
I would have preferred using C-x C-o but C-x is the common command for Edit.Cut and rather not mess with it to leave it available when pair programming. Therefore, arbitrarily chose M-o as an alternative.

In XKeymacs, you can map key commands to custom ones to use while running XKeymacs.

Find the .xkeymacs config file in the XKeymacs directory. For example, mine is found under Program Files:
C:\Program Files\xkeymacs\xkeymacs347\etc\English (United States).xkeymacs
Add the line:
(fset 'delete-blank-lines "\Alt+o")
Then configure
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab -> Category 'Original Command' -> 
you should now see the new command, 'delete-blank-lines', previously added in the config file in the list of commands. To continue:
Under 'Press new shortcut key:' -> check 'Ctrl-X' -> in text field below it, press 'Ctrl-o' -> click 'Assign'
'Current keys:' list should now include 'Ctrl-X Ctrl-O'. Now in VS, C-x C-o will run delete blank lines command (as well as M-o the original bindings in VS) when XKeymacs is enabled.

VS Emacs Scheme:

N/A. Works as expected.


Split the selected window into two windows, one above the other: C-x 2

XKeymacs Mode:

As with the previous item, XKeymacs does not support this but VS does have this command. However, just like before, I'm unable (or unwilling) to bind to C-x 1 since it interferes with Edit.Cut (C-x) in non-Emacs mode. Therefore, need to map the binding in XKeymacs.

First, in VS make sure:
Window.Split
is bound to
Ctrl + F6
Then in XKeymacs config file, '.xkeymacs':
...\xkeymacs347\etc\English (United States).xkeymacs
add line:
(fset 'split-window-vertically [?\Ctrl+f6])
Then configure XKeymacs
Properties -> select 'devenv.exe' -> 'Advanced' tab -> under Category 'Original Command' -> 
should now see new command, 'split-window-vertically', in the list of commands
Under 'Press new shortcut key:', check 'Ctrl-X' -> in text field below it, press '2' -> click 'Assign' 
'Current keys:' list should now include 'Ctrl-X 2'. Now in VS, C-x 2 will run 'window split' command (as well as Ctrl + F6 the original bindings in VS).

Although I don't use splitting windows that often, it is useful on those rare occasions when I need to view one part of a file while editing another part of that same file.

VS Emacs Scheme:

N/A. Works as expected.


Remove other windows (remove split): C-x 1

XKeymacs Mode:

Continuing from the previous item, we need a way to remove the split window too. In VS, the same command 'Windows.Split' that initially splits the window also removes it. It toggles the two states.

Follow all of the same steps as descibed in the previous item for window split specifically adding the new mapping in .xkeymacs config file.

Now go back into XKeymacs to add an additional keybinding for the same 'window split' command:
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab -> Category 'Original Command' -> 
should now see (new) command, 'split-window-vertically', in the list of commands
under 'Press new shortcut key:, check 'Ctrl-X' -> in text field below it, press '1' -> click 'Assign' -> 
'Current keys:' list should now include 'Ctrl-X 1' along with 'Ctrl-X 2' added previously. Now in VS, C-x 1 will run 'window split' command (as well as Ctrl + F6 the original bindings in VS) to remove the window split.

VS Emacs Scheme:

N/A. Works as expected.


Select another window: C-x o

XKeymacs Mode:

This command is available once a window for a file has been split (see the two previous items). It allows one to move the cursor and focus back and forth between the two views.

In VS, check to see if
Window.NextSplitPane
is assign to
F6
If not, then set it as F6.

Then in XKeymacs config file, '.xkeymacs':
...\xkeymacs347\etc\English (United States).xkeymacs
add line:
(fset 'other-window [f6])

Then configure
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab  -> under Category 'Original Command',
should now see new command, 'other-window', in the list of commands
Under 'Press new shortcut key:', check 'Ctrl-X' -> in text field below it, press 'o' -> click 'Assign'
'Current keys:' list should now include 'Ctrl-X o'. Now in VS with XKeymacs, C-x o will run 'next split pane' command (as well as F6 the original keybinding in VS)

VS Emacs Scheme:

N/A. Works as expected.


Go to line: M-g g

XKeymacs Mode:

In VS, check to see if:
Edit.GoTo
is assign to
C-g
If not, then set it as C-g.

Then in XKeymacs config file, '.xkeymacs':
...\xkeymacs347\etc\English (United States).xkeymacs
add line:
(fset 'goto-line "\Ctrl+g")
Then configure
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab  -> under Category 'Original Command'  ->
should now see new command, 'goto-line', in the list of commands
Under 'Press new shortcut key:' -> in text field below it, press 'Alt + g' -> click 'Assign'
'Current keys:' list should now include 'Meta + G'.

However, sometimes this keybinding does not always work. Therefore, assign an alternate keybinding. Go back to
'Press new shortcut key:'  -> in text field below it, press 'Ctrl+Alt+g' -> click 'Assign'
'Current keys:' list should now include 'Ctrl+Meta+G' along with 'Meta+G' added previously.

In VS, C-g or C-M-g will run 'goto line' command.

VS Emacs Scheme:

N/A. Works as expected.


Delete from beginning of line to point: M-0 C-k

XKeymacs Mode:

N/A. Works as expected.

VS Emacs Scheme:

M-0 C-k kills from point (cursor) to the beginning of the current line. It is the opposite command of C-k which kills from point to the end of line. Unlike XKeymacs, the equivalent VS command, Edit.DeleteToBOL, removes all text to the start of the line which includes the non-blank spaces.

In VS assign:
Edit.DeleteToBOL
to
M-0 C-k


Open line above: C-M-Enter

XKeymacs Mode:

Emacs does not have a single command to insert a newline above the current line. To perform this requires calling multiple commands: C-a C-o. However, VS has a command, Edit.LineOpenAbove, that inserts a newline above regardless of your location on the current line. This behavior is reminiscent of VIM's 'O' command.

In VS assign:
Edit.LineOpenAbove 
to
C-M-Enter
VS also has the command, Edit.LineOpenBelow, that inserts a newline below the current one. It is automatically bound to Shift + Ctrl + Enter. This is similar to Emacs' C-o command but does not drag the rest of the text after the point down to the newline. Instead, this behaves like the 'o' command in VIM. Unfortunately, although a handy shorter command, I rarely use this VS command since I am accustomed to doing C-e C-m to achieve the same functionality.

VS Emacs Scheme:

Follow the same steps as XKeymacs mode.


Swap point and mark: C-x C-x

XKeymacs Mode:

Suprisingly, XKeymacs does not support this command. Therefore, in Visual Studio assign the keybindings to the equivalent 'swap anchor' command:
Edit.SwapAnchor
to
C-k C-a 
Then in XKeymacs config file, '.xkeymacs':
...\xkeymacs347\etc\English (United States).xkeymacs
add line:
(fset 'exchange-point-and-mark "\Ctrl+k\Ctrl+a")
Then configure
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab  -> under Category 'Original Command'  ->
should now see new command, 'exchange-point-and-mark', in the list of commands
Under 'Press new shortcut key:', check 'Ctrl-X' -> in text field below it, press 'C-x' -> click 'Assign'
'Current keys:' list should now include 'Ctrl-X Ctrl-X'.

VS Emacs Scheme:

N/A. Works as expected.


List buffer: C-x C-b

XKeymacs Mode:
The ReSharper command 'View Recent Files' (C-,) reminded me of Emacs' list-buffers command. Therefore, thought I might bind Emacs' key shortcuts to it too.

In XKeymacs config file, '.xkeymacs':
...\xkeymacs347\etc\English (United States).xkeymacs
add line:
(fset 'list-buffers "\Ctrl+,")
Then configure
XKeymacs Properties -> select 'devenv.exe' -> 'Advanced' tab  -> under Category 'Original Command'  ->
should now see new command, 'list-buffers', in the list of commands
Under 'Press new shortcut key:', check 'Ctrl-X' -> in text field below it, press 'C-b' -> click 'Assign'
'Current keys:' list should now include 'Ctrl-X Ctrl-B'.

This is helpful to those who first learned Emacs before using ReSharper. I still generally use C-, since it is more convenient and I've been using that ReSharper command shortcut for a long time. However, nice to have alternatives there for consistency.

VS Emacs Scheme:

Follow same steps as XKeymacs mode.


Back to indentation: M-m

XKeymacs Mode:

Although C-a does a reliable of job of moving from anywhere on the current line to the first indention (i.e. first non-space character on the line), I am in the habit of using M-m to do that in Emacs. For example, I use it frequently when coding in Python using Emacs (indentation being core to the Python language) so mapping the equivalent VS command to M-m provides further consistency for me.

In VS, assign:
Edit.LineStartAfterIndentation
to
M-m
VS Emacs Scheme:

Unlike XKeymacs, C-a does not move the point to the start of the first (non-blank) character in the line but instead moves it to the beginning of the line. Therefore, binding M-m to Edit.LineStartAfterIndentation is extremely useful. So, follow the steps described in XKeymacs mode.


Join Lines: M-^

XKeymacs Mode:

XKeymacs does not have this command nor does Visual Studio. I hadn't really gave much thought about it until answering this question, does Visual Studio 2010 not have a “join lines” keyboard shortcut?, on StackOverflow. Truthfully, I don't find myself needed this when coding in C# with ReSharper but now that I made the effort to create a macro then it will now be included as part of my general keybindings configuration.

Essentially create a macro named something like "JoinLines" and I recommend using the code from my original answer since it behaves more like the Emacs version. The subsequent updated answer for joining lines follows more of the VIM equivalent.

Once the VS macro is created then assign the keybindings:
Tools -> Options -> Environment -> Keyboard -> in text field for 'Show commands containing:', type "JoinLines" and the new macro command should display. 
then assign this command to
M-^ 
This approach opens the door to creating other VS macros for missing commands in VS and are found in Emacs. Currently, join lines is one so I need to keep this mind next time when I need to port over some Emacs function to VS.

VS Emacs Scheme:

Follow same steps as XKeymacs mode.

3 comments:

Anonymous said...

same here. I use XKeymacs with VS 2010. way better, becuase you can also do CTRL+n (down) which works in alot of "go to type" mini-dialogs.

Anonymous said...

Thanks for this, I am having to start doing a lot of c# development and coming from emacs it has been painful to transition. Xkeymacs and Resharper will be godsends.
Cheers

Alexey said...

Great tool! Great article! Thank you.

I'm trying to replace the C-S-s binding for "File.SaveAll" command to C-x C-S-s. But I can't find the right way to write the last argument for fset. I've tried several guesses including [?\Ctrl-\Shift-s], but they all fail. Could you suggest a solution, please?