Информация об изменениях

Сообщение Re: А почему бы нам не сделать что-нибудь полезное? от 28.03.2025 15:25

Изменено 28.03.2025 15:30 VladD2

Re: А почему бы нам не сделать что-нибудь полезное?
Здравствуйте, Codealot, Вы писали:

C>Например, простая и полезная фича — сделать опцию, чтобы числа в VS показывались с сепараторами тысяч. Запрос на фичу добавили давно, но как обычно, разрабы не будут ничего делать, пока пользователи не прорвут им новую дырку в заднице.


Попросил ДипСика:

Напиши плагин к VS 2022 реализующий отображение в коде чисел с разделителями тысяч.


Он выдал готовый код плагина. Остается только добавить во VSIX-проект, скомпилировать и проинсталлировать плагин. Пробуй, если интересно.



using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Operations;
using System;
using System.Text.RegularExpressions;

namespace ThousandsSeparatorExtension
{
    [Export(typeof(IWpfTextViewCreationListener))]
    [ContentType("CSharp")]
    [ContentType("Basic")]
    [TextViewRole(PredefinedTextViewRoles.Document)]
    public sealed class NumberAdornment : IWpfTextViewCreationListener
    {
        [Import]
        public ITextUndoHistoryRegistry UndoHistoryRegistry { get; set; }

        [Import]
        public ITextBufferFactoryService TextBufferFactoryService { get; set; }

        public void TextViewCreated(IWpfTextView textView)
        {
            textView.TextBuffer.Changed += OnTextBufferChanged;
        }

        private void OnTextBufferChanged(object sender, TextContentChangedEventArgs e)
        {
            if (e.Changes.Count == 0) return;

            var buffer = sender as ITextBuffer;
            if (buffer.Properties.TryGetProperty("IsProcessing", out bool isProcessing) && isProcessing)
                return;

            buffer.Properties["IsProcessing"] = true;

            using (ITextEdit edit = buffer.CreateEdit())
            {
                foreach (var change in e.Changes)
                {
                    var line = buffer.CurrentSnapshot.GetLineFromPosition(change.NewPosition);
                    string text = line.GetText();

                    foreach (Match match in Regex.Matches(text, @"\b\d{4,}\b"))
                    {
                        string formatted = FormatNumber(match.Value);
                        if (formatted != match.Value)
                        {
                            Span span = new Span(line.Start.Position + match.Index, match.Length);
                            edit.Replace(span, formatted);
                        }
                    }
                }

                if (edit.HasEffectiveChanges)
                {
                    edit.Apply();
                }
            }

            buffer.Properties["IsProcessing"] = false;
        }

        private string FormatNumber(string number)
        {
            int cursor = number.Length - 1;
            var result = new System.Collections.Generic.Stack<char>();
            int count = 0;

            while (cursor >= 0)
            {
                result.Push(number[cursor]);
                count++;
                if (count % 3 == 0 && cursor > 0)
                    result.Push('_');
                cursor--;
            }

            return new string(result.ToArray()).Trim('_');
        }
    }
}


Re: А почему бы нам не сделать что-нибудь полезное?
Здравствуйте, Codealot, Вы писали:

C>Например, простая и полезная фича — сделать опцию, чтобы числа в VS показывались с сепараторами тысяч. Запрос на фичу добавили давно, но как обычно, разрабы не будут ничего делать, пока пользователи не прорвут им новую дырку в заднице.


Попросил ДипСика:

Напиши плагин к VS 2022 реализующий отображение в коде чисел с разделителями тысяч.


Он выдал готовый код плагина. Остается только добавить во VSIX-проект, скомпилировать и проинсталлировать плагин. Пробуй, если интересно.



using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Operations;
using System;
using System.Text.RegularExpressions;

namespace ThousandsSeparatorExtension
{
    [Export(typeof(IWpfTextViewCreationListener))]
    [ContentType("CSharp")]
    [ContentType("Basic")]
    [TextViewRole(PredefinedTextViewRoles.Document)]
    public sealed class NumberAdornment : IWpfTextViewCreationListener
    {
        [Import]
        public ITextUndoHistoryRegistry UndoHistoryRegistry { get; set; }

        [Import]
        public ITextBufferFactoryService TextBufferFactoryService { get; set; }

        public void TextViewCreated(IWpfTextView textView)
        {
            textView.TextBuffer.Changed += OnTextBufferChanged;
        }

        private void OnTextBufferChanged(object sender, TextContentChangedEventArgs e)
        {
            if (e.Changes.Count == 0) return;

            var buffer = sender as ITextBuffer;
            if (buffer.Properties.TryGetProperty("IsProcessing", out bool isProcessing) && isProcessing)
                return;

            buffer.Properties["IsProcessing"] = true;

            using (ITextEdit edit = buffer.CreateEdit())
            {
                foreach (var change in e.Changes)
                {
                    var line = buffer.CurrentSnapshot.GetLineFromPosition(change.NewPosition);
                    string text = line.GetText();

                    foreach (Match match in Regex.Matches(text, @"\b\d{4,}\b"))
                    {
                        string formatted = FormatNumber(match.Value);
                        if (formatted != match.Value)
                        {
                            Span span = new Span(line.Start.Position + match.Index, match.Length);
                            edit.Replace(span, formatted);
                        }
                    }
                }

                if (edit.HasEffectiveChanges)
                {
                    edit.Apply();
                }
            }

            buffer.Properties["IsProcessing"] = false;
        }

        private string FormatNumber(string number)
        {
            int cursor = number.Length - 1;
            var result = new System.Collections.Generic.Stack<char>();
            int count = 0;

            while (cursor >= 0)
            {
                result.Push(number[cursor]);
                count++;
                if (count % 3 == 0 && cursor > 0)
                    result.Push('_');
                cursor--;
            }

            return new string(result.ToArray()).Trim('_');
        }
    }
}




Попросил его сгенерить и source.extension.vsixmanifest (единственная более менее сложная часть проекта):
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
  <Metadata>
    <Identity 
      Id="ThousandsSeparatorExtension.YourName.6a5d04a1-1234-5678-90ab-cdef01234567"
      Version="1.0"
      Language="en-US"
      Publisher="Your Name" />

    <DisplayName>Thousands Separator Formatter</DisplayName>
    <Description>Adds thousand separators to numeric literals in code. Example: 12345 → 12_345</Description>
    <MoreInfo>https://github.com/yourname/vs-thousands-separator</MoreInfo>
    <License>LICENSE.txt</License>
    <Icon>icon.png</Icon>
    <Tags>formatting, numbers, readability</Tags>
  </Metadata>

  <Installation>
    <InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.0, 18.0)" />
  </Installation>

  <Dependencies>
    <Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" Version="[4.7.2,)" />
  </Dependencies>

  <Assets>
    <Asset Type="Microsoft.VisualStudio.MefComponent" Path="ThousandsSeparatorExtension.dll" />
  </Assets>

  <Prerequisites>
    <Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[17.0,)" DisplayName="Visual Studio core editor" />
  </Prerequisites>
</PackageManifest>