CodeEditorLib 1.0.0

dotnet add package CodeEditorLib --version 1.0.0
                    
NuGet\Install-Package CodeEditorLib -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CodeEditorLib" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CodeEditorLib" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="CodeEditorLib" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CodeEditorLib --version 1.0.0
                    
#r "nuget: CodeEditorLib, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CodeEditorLib@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CodeEditorLib&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=CodeEditorLib&version=1.0.0
                    
Install as a Cake Tool

CodeEditorLib

License: MIT .NET Framework Platform


💖 Support This Project

If CodeEditorLib saved you time or you're using it in something real, consider sponsoring. It helps me keep maintaining this and building more open source tools.

☕ Sponsor on GitHub → github.com/sponsors/arisohandriputra

Sponsor


A Windows Forms code editor control for .NET. Drop it into any WinForms project and you get a working code editor - syntax highlighting, line numbers, themes, undo/redo, auto-indent, find & replace, the whole thing. No external dependencies.

I built this because I kept rewriting the same editor boilerplate across different projects. Now I just reference the DLL and move on.


What's included

Everything works out of the box without any extra setup:

  • Syntax highlighting for 13 languages
  • Line number gutter that scrolls with the content
  • Built-in Light and Dark themes, easy to make your own
  • Undo/Redo up to 500 steps back
  • Auto-indent on Enter
  • Auto-close for (, {, [
  • Find & Replace with case-sensitive and whole-word options
  • Comment/uncomment selected lines in one shot
  • Indent and outdent multiple lines at once
  • Current line highlight
  • Go To Line dialog
  • Word wrap toggle
  • Configurable tab size

Supported languages

C#, C++, Java, JavaScript, Python, PHP, Go, Rust, Visual Basic, HTML, CSS, SQL, XML.

Need something else? You can add your own language by subclassing LanguageDefinition. There's an example near the bottom of this file.


Getting started

Build it

msbuild CodeEditorLib.sln /p:Configuration=Release

Grab bin\Release\CodeEditorLib.dll and add it as a reference in your project. Or just add CodeEditorLib.csproj directly to your solution as a project reference — whichever you prefer.

Add it to a form

using CodeEditorLib.Controls;
using CodeEditorLib.Themes;

public partial class MainForm : Form
{
    private CodeEditorControl _editor;

    public MainForm()
    {
        InitializeComponent();

        _editor = new CodeEditorControl { Dock = DockStyle.Fill };
        _editor.LanguageName = "CSharp";
        _editor.Theme = new DarkTheme();
        _editor.Code = "// start typing";

        Controls.Add(_editor);
    }
}

That's really all you need to get a fully working editor on screen.


Configuration

All of these can be changed at any point, not just at startup:

_editor.TabSize              = 4;
_editor.ShowLineNumbers      = true;
_editor.HighlightCurrentLine = true;
_editor.AutoBrackets         = true;
_editor.AutoIndent           = true;
_editor.WordWrap             = false;
_editor.ReadOnly             = false;

Switching themes

_editor.Theme = new DarkTheme();
_editor.Theme = new LightTheme();

Setting the language

// by name
_editor.LanguageName = "Python";

// by file extension
_editor.Language = LanguageRegistry.Instance.GetByExtension(".rs");

// auto-detect from a file path — handy when the user opens a file
_editor.Language = LanguageRegistry.Instance.GetByFilePath(@"C:\project\main.go");

Events

Hook into these if you need to react to what the user is doing:

// update a status bar with line/column info
_editor.CaretPositionChanged += (s, e) =>
{
    statusLabel.Text = $"Ln {e.Line}  Col {e.Column}";
};

// track content changes
_editor.CodeTextChanged += (s, e) =>
{
    titleBar.Text = "MyEditor *";
};

// know when find/replace finishes
_editor.FindReplaceCompleted += (s, e) =>
{
    statusLabel.Text = $"{e.MatchCount} replacement(s) made";
};

// react to language switches
_editor.LanguageChanged += (s, e) =>
{
    langLabel.Text = e.LanguageName;
};

Calling editor actions from your UI

If you want toolbar buttons or menu items to drive the editor:

undoButton.Click    += (s, e) => _editor.Undo();
redoButton.Click    += (s, e) => _editor.Redo();
commentButton.Click += (s, e) => _editor.ToggleComment();
indentButton.Click  += (s, e) => _editor.IndentSelection();
outdentButton.Click += (s, e) => _editor.OutdentSelection();
findButton.Click    += (s, e) => _editor.ShowFindDialog();
replaceButton.Click += (s, e) => _editor.ShowReplaceDialog();
gotoButton.Click    += (s, e) => _editor.ShowGotoDialog();

// keep undo/redo buttons in sync
undoButton.Enabled = _editor.CanUndo;
redoButton.Enabled = _editor.CanRedo;

Project structure

CodeEditorLib/
├── Controls/
│   ├── CodeEditorControl.cs      # the main UserControl
│   └── LineNumberPanel.cs        # the line number gutter
├── Core/
│   ├── CodeFormatter.cs          # indent, outdent, comment helpers
│   ├── LanguageDefinition.cs     # base class for all languages
│   ├── SyntaxHighlighter.cs      # regex-based tokenizer
│   ├── SyntaxRule.cs             # a single highlighting rule
│   ├── SyntaxToken.cs            # a matched token with position and type
│   ├── TextSelection.cs          # selection range
│   └── UndoRedoManager.cs        # stack-based undo/redo
├── Events/
│   └── CodeEditorEventArgs.cs    # event arg classes
├── Highlighting/
│   ├── HighlightScheme.cs        # collection of styles per token type
│   └── HighlightStyle.cs         # foreground color + bold/italic
├── Languages/
│   ├── LanguageRegistry.cs       # singleton, lookup by name or extension
│   └── [13 language files]
├── Themes/
│   ├── EditorTheme.cs            # abstract base
│   ├── DarkTheme.cs
│   └── LightTheme.cs
└── Properties/
    └── AssemblyInfo.cs

Adding a custom language

Subclass LanguageDefinition, define your regex rules, and register it once at startup. Here's Lua as an example:

using System.Text.RegularExpressions;
using CodeEditorLib.Core;

public class LuaLanguage : LanguageDefinition
{
    public LuaLanguage()
    {
        Name = "Lua";
        AddExtension(".lua");

        CommentSingleLine     = "--";
        CommentMultiLineStart = "--[[";
        CommentMultiLineEnd   = "]]";

        AddRule(new SyntaxRule(
            new Regex(@"\b(and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b"),
            TokenType.Keyword, priority: 10));

        AddRule(new SyntaxRule(
            new Regex(@"--[^\n]*"),
            TokenType.Comment, priority: 20));

        AddRule(new SyntaxRule(
            new Regex(@"""[^""\\]*(?:\\.[^""\\]*)*""|'[^'\\]*(?:\\.[^'\\]*)*'"),
            TokenType.String, priority: 15));

        AddRule(new SyntaxRule(
            new Regex(@"\b\d+(\.\d+)?\b"),
            TokenType.Number, priority: 5));
    }
}

Register it once when your app starts:

LanguageRegistry.Instance.Register(new LuaLanguage());

After that it works exactly like any built-in language — by name, by extension, by file path.


Making a custom theme

Subclass EditorTheme, fill in the colors, and build the highlight scheme:

using System.Drawing;
using CodeEditorLib.Highlighting;
using CodeEditorLib.Themes;

public class SolarizedDarkTheme : EditorTheme
{
    public SolarizedDarkTheme() : base("Solarized Dark") { }

    public override Color BackgroundColor            => Color.FromArgb(0, 43, 54);
    public override Color DefaultTextColor           => Color.FromArgb(131, 148, 150);
    public override Color SelectionColor             => Color.FromArgb(7, 54, 66);
    public override Color CurrentLineColor           => Color.FromArgb(7, 54, 66);
    public override Color LineNumberBackColor        => Color.FromArgb(0, 43, 54);
    public override Color LineNumberForeColor        => Color.FromArgb(88, 110, 117);
    public override Color LineNumberBorderColor      => Color.FromArgb(7, 54, 66);
    public override Color CaretColor                 => Color.White;
    public override Color BracketMatchColor          => Color.FromArgb(88, 110, 117);
    public override Color AutoCompleteBackColor      => Color.FromArgb(7, 54, 66);
    public override Color AutoCompleteForeColor      => Color.FromArgb(131, 148, 150);
    public override Color AutoCompleteSelectionColor => Color.FromArgb(38, 139, 210);

    protected override void BuildScheme(HighlightScheme scheme)
    {
        scheme.Set(TokenType.Keyword,  new HighlightStyle(Color.FromArgb(133, 153, 0)));
        scheme.Set(TokenType.String,   new HighlightStyle(Color.FromArgb(42, 161, 152)));
        scheme.Set(TokenType.Comment,  new HighlightStyle(Color.FromArgb(88, 110, 117), italic: true));
        scheme.Set(TokenType.Number,   new HighlightStyle(Color.FromArgb(211, 54, 130)));
        scheme.Set(TokenType.Type,     new HighlightStyle(Color.FromArgb(181, 137, 0)));
        scheme.Set(TokenType.Operator, new HighlightStyle(Color.FromArgb(131, 148, 150)));
    }
}

Then just set it:

_editor.Theme = new SolarizedDarkTheme();

Requirements

  • Windows (WinForms dependency)
  • .NET Framework 2.0 or higher
  • Visual Studio 2005+ or any MSBuild-compatible toolchain

Contributing

Pull requests are welcome. If you're adding a language, subclass LanguageDefinition and register it in LanguageRegistry.RegisterDefaults(). Keep the PR focused on one thing and make sure existing behavior still works.

For bugs, a small reproducible snippet is worth more than a paragraph of description.


License

MIT. See LICENSE for the full text.

Copyright (c) 2026 Ari Sohandri Putra

Product Compatible and additional computed target framework versions.
.NET Framework net20 is compatible.  net35 was computed.  net40 is compatible.  net403 was computed.  net45 was computed.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 2.0

    • No dependencies.
  • .NETFramework 4.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 89 5/12/2026