다음을 통해 공유


편집기에서 텍스트 작업

확장 코드는 다양한 진입점(사용자가 Visual Studio와 상호 작용할 때 발생하는 상황)에 대한 응답으로 실행되도록 구성할 수 있습니다. 편집기 확장성은 현재 수신기, EditorExtensibility 서비스 개체 및 명령의 세 가지 진입점을 지원합니다.

이벤트 수신기는 편집기 창에서 특정 작업이 발생할 때 트리거되며 TextView코드로 표시됩니다. 예를 들어 사용자가 편집기에 항목을 입력하면 TextViewChanged 이벤트가 발생합니다. 편집기 창을 열거나 닫으면 TextViewOpenedTextViewClosed 이벤트가 발생합니다.

편집기 서비스 개체는 텍스트 편집 수행과 같은 실시간 편집기 기능을 노출하는 EditorExtensibility 클래스의 인스턴스입니다.

명령 메뉴, 상황에 맞는 메뉴 또는 도구 모음에 배치할 수 있는 항목을 클릭하여 사용자가 시작합니다.

텍스트 보기 수신기 추가

두 가지 유형의 수신기가 있습니다: ITextViewChangedListenerITextViewOpenClosedListener입니다. 이러한 수신기를 함께 사용하여 텍스트 편집기의 열기, 닫기 및 수정을 관찰할 수 있습니다.

그런 다음 새 클래스를 만들고 ExtensionPart 기본 클래스 및 ITextViewChangedListener, ITextViewOpenClosedListener또는 둘 다를 구현하고 VisualStudioContribution 특성을 추가합니다.

그런 다음, C# 파일을 편집할 때 리스너가 적용되도록 ITextViewChangedListenerITextViewOpenClosedListener필요에 따라 TextViewExtensionConfiguration 속성을 구현합니다.

public TextViewExtensionConfiguration TextViewExtensionConfiguration => new()
{
    AppliesTo = new[] { DocumentFilter.FromDocumentType("CSharp") },
};

다른 프로그래밍 언어 및 파일 형식에 사용할 수 있는 문서 형식은 이 문서 뒷부분에나열되며 필요한 경우 사용자 지정 파일 형식도 정의할 수 있습니다.

두 수신기를 모두 구현하기로 결정한 경우 완성된 클래스 선언은 다음과 같아야 합니다.

  [VisualStudioContribution]                
  public sealed class TextViewOperationListener :
      ExtensionPart, // This is the extension part base class containing infrastructure necessary to use VS services.
      ITextViewOpenClosedListener, // Indicates this part listens for text view lifetime events.
      ITextViewChangedListener // Indicates this part listens to text view changes.
  {
      public TextViewExtensionConfiguration TextViewExtensionConfiguration => new()
      {
          // Indicates this part should only light up in C# files.
          AppliesTo = new[] { DocumentFilter.FromDocumentType("CSharp") },
      };
      ...

ITextViewOpenClosedListenerITextViewChangedListenerTextViewExtensionConfiguration 속성을 선언하므로 구성은 두 수신기에 모두 적용됩니다.

확장을 실행하면 다음이 표시됩니다.

이러한 각 메서드는 사용자가 작업을 호출할 때 텍스트 보기 및 텍스트 문서의 상태를 포함하는 ITextViewSnapshot 전달되고 IDE가 보류 중인 작업을 취소하려고 할 때 IsCancellationRequested == true CancellationToken이 전달됩니다.

확장이 관련 있는 시기 정의

확장은 일반적으로 지원되는 특정 문서 유형 및 시나리오와만 관련이 있으므로 해당 적용 가능성을 명확하게 정의하는 것이 중요합니다. 여러 가지 방법으로 AppliesTo 구성)을 사용하여 확장의 적용 가능성을 명확하게 정의할 수 있습니다. 확장 프로그램에서 지원하는 코드 언어와 같은 파일 형식을 지정하거나 파일 이름 또는 경로에 따라 패턴에 일치하여 확장 프로그램의 적용 가능성을 더욱 구체화할 수 있습니다.

AppliesTo 구성을 사용하여 프로그래밍 언어 지정

AppliesTo 구성은 확장이 활성화되어야 하는 프로그래밍 언어 시나리오를 나타냅니다. 기록 형식은 AppliesTo = new[] { DocumentFilter.FromDocumentType("CSharp") }으로, Visual Studio에 내장된 언어의 알려진 이름이거나 Visual Studio 확장에서 사용자 정의한 것입니다.

잘 알려진 문서 유형은 다음 표에 나와 있습니다.

문서 유형 묘사
"CSharp" C#
"C/C++" C, C++, 헤더 및 IDL
"TypeScript" TypeScript 및 JavaScript 형식 언어입니다.
"HTML" HTML
"JSON" JSON
"텍스트" "text"에서 내림차순인 "code"의 계층적 하위 항목을 포함하는 텍스트 파일입니다.
코드 C, C++, C#등입니다.

DocumentType은 계층적입니다. 즉, C# 및 C++는 모두 "코드"에서 내림차순이므로 "코드"를 선언하면 모든 코드 언어, C#, C, C++등에 대해 확장이 활성화됩니다.

새 문서 형식 정의

예를 들어 확장 프로젝트의 모든 클래스에 정적 DocumentTypeConfiguration 속성을 추가하고 속성을 VisualStudioContribution 특성으로 표시하여 사용자 지정 코드 언어를 지원하기 위해 새 문서 형식을 정의할 수 있습니다.

DocumentTypeConfiguration 새 문서 형식을 정의하고, 하나 이상의 다른 문서 형식을 상속하도록 지정하고, 파일 형식을 식별하는 데 사용되는 파일 확장자를 하나 이상 지정할 수 있습니다.

using Microsoft.VisualStudio.Extensibility.Editor;

internal static class MyDocumentTypes
{
    [VisualStudioContribution]
    internal static DocumentTypeConfiguration MarkdownDocumentType => new("markdown")
    {
        FileExtensions = new[] { ".md", ".mdk", ".markdown" },
        BaseDocumentType = DocumentType.KnownValues.Text,
    };
}

문서 형식 정의는 레거시 Visual Studio 확장성에서 제공하는 콘텐츠 형식 정의와 병합되므로 추가 파일 확장자를 기존 문서 형식에 매핑할 수 있습니다.

문서 선택기

DocumentFilter.FromDocumentType 외에도 documentFilter.FromGlobPattern 문서의 파일 경로가 glob(와일드카드) 패턴과 일치하는 경우에만 활성화하여 확장의 적용 가능성을 추가로 제한할 수 있습니다.

[VisualStudioContribution]                
public sealed class TextViewOperationListener
    : ExtensionPart, ITextViewOpenClosedListener, ITextViewChangedListener
{
    public TextViewExtensionConfiguration TextViewExtensionConfiguration => new()
    {
        AppliesTo = new[]
        {
            DocumentFilter.FromDocumentType("CSharp"),
            DocumentFilter.FromGlobPattern("**/tests/*.cs"),
        },
    };
[VisualStudioContribution]                
public sealed class TextViewOperationListener
    : ExtensionPart, ITextViewOpenClosedListener, ITextViewChangedListener
{
    public TextViewExtensionConfiguration TextViewExtensionConfiguration => new()
    {
        AppliesTo = new[]
        {
            DocumentFilter.FromDocumentType(MyDocumentTypes.MarkdownDocumentType),
            DocumentFilter.FromGlobPattern("docs/*.md", relativePath: true),
        },
    };

pattern 매개 변수는 문서의 절대 경로와 일치하는 glob 패턴을 나타냅니다.

Glob 패턴에는 다음 구문이 있을 수 있습니다.

  • *는 경로 세그먼트에서 0개 이상의 문자와 일치하도록 합니다.
  • 경로 세그먼트 내에서 한 문자를 일치시키는 데 사용되는 ?
  • 경로 세그먼트가 없거나 여러 개일 수 있는 경우를 포함하여 **과(와) 일치하도록
  • 그룹 조건에 {}(예: 모든 TypeScript 및 JavaScript 파일과 일치하는 **​/*.{ts,js})
  • 경로 세그먼트에서 일치시킬 문자 범위를 선언하기 위한 [] (예: example.0, example.1, ...에서 일치하도록 example.[0-9]).
  • 경로 세그먼트에서 일치시킬 문자 범위를 부정하는 [!...](예: example.a, example.bexample.[!0-9] 일치하지만 example.0아님)

백슬래시(\)는 glob 패턴 내에서 유효하지 않습니다. glob 패턴을 만들 때 백슬래시를 슬래시로 변환해야 합니다.

편집기의 기능에 접근하기

편집기 확장 클래스가 ExtensionPart를 상속합니다. ExtensionPart 클래스는 확장성 속성을 노출합니다. 이 속성을 사용하여 EditorExtensibility 개체의 인스턴스를 요청할 수 있습니다. 이 개체를 사용하여 편집 수행과 같은 실시간 편집기 기능에 액세스할 수 있습니다.

EditorExtensibility editorService = this.Extensibility.Editor();

명령 내의 편집기 상태 액세스

Command에서 ExecuteCommandAsync()는 명령이 호출될 때 IDE 상태의 스냅샷을 포함하는 IClientContext를 전달받습니다. 비동기 메서드 GetActiveTextViewAsync를 호출하여 EditorExtensibility 개체에서 가져온 ITextViewSnapshot 인터페이스를 통해 활성 문서에 액세스할 수 있습니다.

using ITextViewSnapshot textView = await this.Extensibility.Editor().GetActiveTextViewAsync(clientContext, cancellationToken);

ITextViewSnapshot있으면 편집기 상태에 액세스할 수 있습니다. ITextViewSnapshot 특정 시점에 편집기 상태를 변경할 수 없는 보기이므로 편집을 위해 Editor 개체 모델 다른 인터페이스를 사용해야 합니다.