The shortcut key Ctrl+K,Ctrl+D can format all the code. #423

Open
opened 2024-03-07 03:09:44 -06:00 by Philorrine · 1 comment
Philorrine commented 2024-03-07 03:09:44 -06:00 (Migrated from github.com)

When we use Visual Studio and press Ctrl+K, Ctrl+D, the code will be formatted. And how can we achieve this functionality in avalonedit? And when we press Ctrl+D after Ctrl+K, the line where the cursor is located will be deleted.

When we use Visual Studio and press Ctrl+K, Ctrl+D, the code will be formatted. And how can we achieve this functionality in avalonedit? And when we press Ctrl+D after Ctrl+K, the line where the cursor is located will be deleted.
blakepell commented 2024-08-20 18:06:00 -05:00 (Migrated from github.com)

I can answer half the question. I don't think AvalonEdit (or WPF) supports "chords" like Visual Studio out of the box (or if I does I'm unaware). To listen for Chords with AvalonEdit I use this code (you can use this for WPF in general). Here is an example to comment and uncomment code with Ctrl+K Ctrl+C and Ctrl+K Ctrl+U (I've gotten a lot of mileage out of this class).

public class KeyChordGesture : KeyGesture
{
    private readonly Key _key;
    private bool _gotFirstGesture;
    private readonly InputGesture _firstGesture;

    public KeyChordGesture(ModifierKeys modifier, Key firstKey, Key secondKey) : base(Key.None)
    {
        _firstGesture = new KeyGesture(firstKey, modifier);
        _key = secondKey;
    }

    public override bool Matches(object obj, InputEventArgs inputEventArgs)
    {
        var keyArgs = inputEventArgs as KeyEventArgs;

        if (keyArgs == null || keyArgs.IsRepeat)
        {
            return false;
        }

        if (_gotFirstGesture)
        {
            _gotFirstGesture = false;

            if (keyArgs.Key == _key)
            {
                inputEventArgs.Handled = true;
            }

            return keyArgs.Key == _key;
        }

        _gotFirstGesture = _firstGesture.Matches(null, inputEventArgs);

        if (_gotFirstGesture)
        {
            inputEventArgs.Handled = true;
        }

        return false;
    }
}

Then you would setup your key bindings like this (I pass it two relay commands in this example):

// Comment command
Editor.TextArea.InputBindings.Add(new KeyBinding(this.ViewModel.CommentCommand,
    new KeyChordGesture(ModifierKeys.Control, Key.K, Key.C)));

// Uncomment command.
Editor.TextArea.InputBindings.Add(new KeyBinding(this.ViewModel.UncommentCommand,
    new KeyChordGesture(ModifierKeys.Control, Key.K, Key.U)));

Then here is the relay commands those calls (these might need a little work but they mostly work):

/// <summary>
/// Comments out the selected section of code.
/// </summary>
public void Comment()
{
    if (this.Editor.SelectionLength <= 1)
    {
        return;
    }

    var sb = StringBuilderPool.Take();
    var lines = this.Editor.SelectedText.Split('\n');

    foreach (var line in lines)
    {
        string codeLine = line.TrimEnd();

        if (codeLine.StartsWith("//"))
        {
            sb.AppendLine(codeLine);
        }
        else
        {
            sb.Append("//").Append(codeLine).Append("\r\n");
        }
    }

    this.Editor.SelectedText = sb.ToString().TrimEnd('\r', '\n').TrimEnd("//");

    StringBuilderPool.Return(sb);
}

/// <summary>
/// Uncomment out the selected section of code.
/// </summary>
public ICommand UncommentCommand => new RelayCommand(Uncomment);

/// <summary>
/// Uncomment out the selected section of code.
/// </summary>
public void Uncomment()
{
    if (this.Editor.SelectionLength <= 1)
    {
        return;
    }

    var sb = StringBuilderPool.Take();
    var lines = this.Editor.SelectedText.Split('\n');

    foreach (var line in lines)
    {
        string codeLine = line.TrimEnd();

        if (codeLine.StartsWith("//"))
        {
            sb.AppendLine(codeLine.Substring(2));
        }
        else
        {
            sb.Append(codeLine).Append("\r\n");
        }
    }

    this.Editor.SelectedText = sb.ToString().TrimEnd('\r', '\n');

    StringBuilderPool.Return(sb);
}
I can answer half the question. I don't think AvalonEdit (or WPF) supports "chords" like Visual Studio out of the box (or if I does I'm unaware). To listen for Chords with AvalonEdit I use this code (you can use this for WPF in general). Here is an example to comment and uncomment code with <kbd>Ctrl+K</kbd> <kbd>Ctrl+C</kbd> and <kbd>Ctrl+K</kbd> <kbd>Ctrl+U</kbd> (I've gotten a lot of mileage out of this class). ``` csharp public class KeyChordGesture : KeyGesture { private readonly Key _key; private bool _gotFirstGesture; private readonly InputGesture _firstGesture; public KeyChordGesture(ModifierKeys modifier, Key firstKey, Key secondKey) : base(Key.None) { _firstGesture = new KeyGesture(firstKey, modifier); _key = secondKey; } public override bool Matches(object obj, InputEventArgs inputEventArgs) { var keyArgs = inputEventArgs as KeyEventArgs; if (keyArgs == null || keyArgs.IsRepeat) { return false; } if (_gotFirstGesture) { _gotFirstGesture = false; if (keyArgs.Key == _key) { inputEventArgs.Handled = true; } return keyArgs.Key == _key; } _gotFirstGesture = _firstGesture.Matches(null, inputEventArgs); if (_gotFirstGesture) { inputEventArgs.Handled = true; } return false; } } ``` Then you would setup your key bindings like this (I pass it two relay commands in this example): ``` csharp // Comment command Editor.TextArea.InputBindings.Add(new KeyBinding(this.ViewModel.CommentCommand, new KeyChordGesture(ModifierKeys.Control, Key.K, Key.C))); // Uncomment command. Editor.TextArea.InputBindings.Add(new KeyBinding(this.ViewModel.UncommentCommand, new KeyChordGesture(ModifierKeys.Control, Key.K, Key.U))); ``` Then here is the relay commands those calls (these might need a little work but they mostly work): ``` csharp /// <summary> /// Comments out the selected section of code. /// </summary> public void Comment() { if (this.Editor.SelectionLength <= 1) { return; } var sb = StringBuilderPool.Take(); var lines = this.Editor.SelectedText.Split('\n'); foreach (var line in lines) { string codeLine = line.TrimEnd(); if (codeLine.StartsWith("//")) { sb.AppendLine(codeLine); } else { sb.Append("//").Append(codeLine).Append("\r\n"); } } this.Editor.SelectedText = sb.ToString().TrimEnd('\r', '\n').TrimEnd("//"); StringBuilderPool.Return(sb); } /// <summary> /// Uncomment out the selected section of code. /// </summary> public ICommand UncommentCommand => new RelayCommand(Uncomment); /// <summary> /// Uncomment out the selected section of code. /// </summary> public void Uncomment() { if (this.Editor.SelectionLength <= 1) { return; } var sb = StringBuilderPool.Take(); var lines = this.Editor.SelectedText.Split('\n'); foreach (var line in lines) { string codeLine = line.TrimEnd(); if (codeLine.StartsWith("//")) { sb.AppendLine(codeLine.Substring(2)); } else { sb.Append(codeLine).Append("\r\n"); } } this.Editor.SelectedText = sb.ToString().TrimEnd('\r', '\n'); StringBuilderPool.Return(sb); } ```
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-icsharpcode/AvalonEdit#423
No description provided.