Skip to content

Instantly share code, notes, and snippets.

@citizenmatt
Created August 21, 2012 15:03
Show Gist options
  • Save citizenmatt/3416292 to your computer and use it in GitHub Desktop.
Save citizenmatt/3416292 to your computer and use it in GitHub Desktop.
ReSharper plugin example to intercept enter key presses in a C# file
using System.Reflection;
using JetBrains.ActionManagement;
using JetBrains.Application.PluginSupport;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TypingAssistManagerTest")]
[assembly: AssemblyDescription("Example of how to hook into typing assist handler chain")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Matt Ellis (JetBrains s.r.o)")]
[assembly: AssemblyProduct("TypingAssistManagerTest")]
[assembly: AssemblyCopyright("Copyright © Matt Ellis (JetBrains s.r.o), 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ActionsXml("TypingAssistManagerTest.Actions.xml")]
// The following information is displayed by ReSharper in the Plugins dialog
[assembly: PluginTitle("TypingAssistManager example")]
[assembly: PluginDescription("Example of how to hook into typing assist handler chain")]
[assembly: PluginVendor("Matt Ellis (JetBrains s.r.o)")]
using JetBrains.DataFlow;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.TypingAssist;
using JetBrains.ReSharper.Psi;
using JetBrains.TextControl;
using JetBrains.TextControl.Actions;
namespace TypingAssistManagerTest
{
[SolutionComponent]
public class TypingAssistManagerExample : ITypingHandler
{
public TypingAssistManagerExample(Lifetime lifetime, ITypingAssistManager typingAssistManager)
{
typingAssistManager.AddActionHandler(lifetime, TextControlActions.ENTER_ACTION_ID, this, HandleEnterPressed);
}
private bool HandleEnterPressed(IActionContext context)
{
// See CSharpTypingAssistBase.HandleEnterPressed for more examples of what you can do here
// e.g. retrieving the text control from context.TextControl, getting a lexer for the contents
// of the file, inserting text and moving the caret
var document = context.TextControl.Document;
var line = context.TextControl.Caret.PositionValue.ToDocLineColumn().Line;
var text = document.GetLineText(line);
if (text.Contains("stop"))
{
// Return true to say that we've handled it. No other handlers will see this enter keypress
return true;
}
if (text.Contains("after"))
{
// Let the other handlers have a go, and do something after they have (e.g. format what they inserted)
// If we call CallNext, we *must* return true, or the remaining handlers in the chain will get called twice
context.CallNext();
context.TextControl.Document.InsertText(context.TextControl.Caret.Offset(), "inserted after");
return true;
}
// Return false. We didn't handle it, let the other handlers have a go
return false;
}
public bool QuickCheckAvailability(ITextControl textControl, IPsiSourceFile projectFile)
{
return projectFile.LanguageType.Is<CSharpProjectFileType>();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0FAF70E9-8598-4A01-8D7D-5D3D97193747}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TypingAssistManagerTest</RootNamespace>
<AssemblyName>TypingAssistManagerTest</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>JET_MODE_ASSERT;DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TypingAssistManagerExample.cs" />
</ItemGroup>
<PropertyGroup>
<ReSharperSdkTargets Condition=" '$(ReSharperSdkTargets)' == '' ">$(MSBuildExtensionsPath)\JetBrains\ReSharper.SDK\v7.0</ReSharperSdkTargets>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(ReSharperSdkTargets)\Plugin.Targets" />
</Project>

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TypingAssistManagerTest", "TypingAssistManagerTest.csproj", "{0FAF70E9-8598-4A01-8D7D-5D3D97193747}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0FAF70E9-8598-4A01-8D7D-5D3D97193747}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FAF70E9-8598-4A01-8D7D-5D3D97193747}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FAF70E9-8598-4A01-8D7D-5D3D97193747}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FAF70E9-8598-4A01-8D7D-5D3D97193747}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@citizenmatt
Copy link
Author

Simple ReSharper example plugin to show how to intercept key presses. Called when the enter key is pressed in C# files.

Checks to see if the current line contains the word "stop". If so, no other handlers are allowed. The best place to see this work is in an xml doc comment. Hitting enter will normally start a newline, add some indent and then add the "/// " xml doc comment indicator. When you add the word "stop" in an xml doc comment, this no longer happens.

Also looks to see if the current line contains "after". If so, calls the remaining handlers, and then appends some text at the caret position. Again, in an xml doc comment, this will cause the newline and comment "/// " symbol to be added to the text, and then the handler adds the text "inserted after"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment