성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Java - How to use the Foreign Funct...
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Visual Studio 2015 확장 - INI 파일을 위한 사용자 정의 포맷 기능 (Syntax Highlighting)</h1> <p> 가끔은, Visual Studio에 자신이 정의한 규약을 따르는 편집 기능을 넣고 싶을 때가 있습니다. 쉬운 예로, INI 파일을 편집할 때 섹션명을 굵게 표현하고 싶다거나, 주석은 이탤릭 체로 바꿔주어 가독성을 높일 수 있습니다. 또는 자신이 만든 프로그래밍 언어의 예약어를 굵게 보여주면 좀 더 폼이 날 것입니다. ^^<br /> <br /> 사실, 몰라서 그렇지 이런 기능을 넣는 것이 그다지 어렵지 않은데요. 다음의 글 정도만 읽어도 쉽게 만들 수 있을 정도입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > LearnVSXNow! #38 - VS 2010 Editor - Text Coloring Sample Deep Dive ; <a target='tab' href='http://dotneteers.net/blogs/divedeeper/archive/2008/11/04/LearnVSXNowPart38.aspx'>http://dotneteers.net/blogs/divedeeper/archive/2008/11/04/LearnVSXNowPart38.aspx</a> </pre> <br /> 이에 기반해서 간단하게 INI 파일을 위한 syntax highlighter를 만들어 보겠습니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 먼저 할 일은 Visual Studio를 시작하고, VSIX 프로젝트를 생성합니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='colorizer_vsix_1.png' src='/SysWebRes/bbs/colorizer_vsix_1.png' /><br /> <br /> 그런 다음 C# 코드 템플릿에서 "Editor Classifier"를 추가해 줍니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='colorizer_vsix_2.png' src='/SysWebRes/bbs/colorizer_vsix_2.png' /><br /> <br /> 총 4개의 파일이 생성되는데,<br /> <br /> <ul> <li>EditorClassifier.cs</li> <li>EditorClassifierClassificationDefinition.cs</li> <li>EditorClassifierFormat.cs</li> <li>EditorClassifierProvider.cs</li> </ul> <br /> 진입점은 IClassifierProvider를 상속받은 EditorClassifierProvider.cs입니다. 해당 클래스에는 다음과 같이 ContentType 특성이 적용되어,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [Export(typeof(IClassifierProvider))] <span style='color: blue; font-weight: bold'>[ContentType("text")]</span> internal class EditorClassifierProvider : IClassifierProvider { //...[생략]... } </pre> <br /> 현재의 값이 "text"로 되어 있기 때문에 Visual Studio에서 텍스트 파일로 판정되는 파일을 열게 될 때마다 EditorClassifierProvider 인스턴스가 생성됩니다. 이 글에서는 INI 텍스트 파일을 지원할 것이므로 그냥 기본값 그대로 두면 됩니다.<br /> <br /> 이후 Visual Studio는 IClassifierProvider.GetClassifier를 호출해 주는데 기본 생성된 코드에는 EditorClassifier.cs 파일에 정의된 IClassifier를 상속받은 EditorClassifier 인스턴스를 준비하는 것만 포함되어 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public IClassifier GetClassifier(ITextBuffer buffer) { return buffer.Properties.GetOrCreateSingletonProperty<EditorClassifier>(creator: () => new EditorClassifier(this.classificationRegistry)); } </pre> <br /> 이렇게 반환하면 모든 "Plain text" 파일 유형에 우리가 만든 "Editor Classifier"가 적용되므로, INI 파일에만 한정짓는 작업이 필요합니다. 이를 위해 편집 중인 파일의 정보를 구할 수 있도록 <a target='tab' href='https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.text.itextdocumentfactoryservice'>ITextDocumentFactoryService</a>를 Visual Studio의 MEF로부터 받는 작업을 해줘야 합니다. 따라서, EditorClassifierProvider.cs 파일의 최종 코드는 다음과 같이 작성하면 됩니다.<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.ComponentModel.Composition; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Utilities; namespace IniColorizer { [Export(typeof(IClassifierProvider))] [ContentType("text")] // This classifier applies to all text files. internal class EditorClassifierProvider : IClassifierProvider { #pragma warning disable 649 [Import] private IClassificationTypeRegistryService classificationRegistry; <span style='color: blue; font-weight: bold'>private readonly ITextDocumentFactoryService _textDocumentFactoryService; [ImportingConstructor] internal EditorClassifierProvider(ITextDocumentFactoryService textDocumentFactoryService) { _textDocumentFactoryService = textDocumentFactoryService; }</span> #pragma warning restore 649 public IClassifier GetClassifier(ITextBuffer buffer) { <span style='color: blue; font-weight: bold'>if (IsINIFile(buffer) == false) { return null; }</span> return buffer.Properties.GetOrCreateSingletonProperty<EditorClassifier>(creator: () => new EditorClassifier(this.classificationRegistry)); } <span style='color: blue; font-weight: bold'>private bool IsINIFile(ITextBuffer buffer) { if (_textDocumentFactoryService == null) { return false; } ITextDocument textDocument; if (_textDocumentFactoryService.TryGetTextDocument(buffer, out textDocument) == false) { return false; } string ext = System.IO.Path.GetExtension(textDocument.FilePath); if (string.IsNullOrEmpty(ext) == true) { return false; } return ext.ToUpper() == ".INI"; }</span> } } </pre> <br /> 자, 그 다음은 EditorClassifier.cs 파일에 정의된 EditorClassifier 클래스가 작업을 담당하게 됩니다. 기본 생성된 코드는 다음과 같이 간단한데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Collections.Generic; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Classification; namespace VSIXProject1 { internal class EditorClassifier : IClassifier { private readonly IClassificationType classificationType; internal EditorClassifier(IClassificationTypeRegistryService registry) { <span style='color: blue; font-weight: bold'>this.classificationType = registry.GetClassificationType("EditorClassifier");</span> } #region IClassifier #pragma warning disable 67 public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged; #pragma warning restore 67 <span style='color: blue; font-weight: bold'>public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) { var result = new List<ClassificationSpan>() { new ClassificationSpan(new SnapshotSpan(span.Snapshot, new Span(span.Start, span.Length)), this.classificationType) }; return result; }</span> #endregion } } </pre> <br /> 사용자가 파일을 편집할 때마다 변경된 문자열 정보가 "SnapshotSpan span" 인자에 담겨 GetClassificationSpans 메서드가 호출됩니다. 그리고, 우리는 INI의 문법에 맞게 IList<ClassificationSpan> 목록에 담아 문자열 포맷 정보를 넘겨주면 됩니다. 위의 GetClassificationSpans 메서드는 사용자가 편집한 문자열을 무조건 this.classificationType으로 지정된 문자열 포맷으로 설정합니다.<br /> <br /> 그리고, this.classificationType은 생성자에서 registry.GetClassificationType("EditorClassifier"); 으로 초기화되는데, 이때의 "EditorClassifier" 문자열 값은 EditorClassifierClassificationDefinition.cs 파일에 정의된 클래스의 멤버에 등록된 [Name("....")]에 지정한 값입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // EditorClassifierClassificationDefinition.cs using System.ComponentModel.Composition; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Utilities; namespace VSIXProject1 { internal static class EditorClassifierClassificationDefinition { #pragma warning disable 169 [Export(typeof(ClassificationTypeDefinition))] <span style='color: blue; font-weight: bold'>[Name("EditorClassifier")]</span> private static ClassificationTypeDefinition typeDefinition; #pragma warning restore 169 } } </pre> <br /> 또한 이 곳의 "Name" 값은 EditorClassifierFormat.cs 파일에 문자열 포맷 양식을 정의하는 Format 클래스의 ClassificationType 특성에 지정되는 ClassificationTypeNames와 연결되는 역할도 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // EditorClassifierFormat.cs using System.ComponentModel.Composition; using System.Windows.Media; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Utilities; namespace VSIXProject1 { [Export(typeof(EditorFormatDefinition))] [ClassificationType(<span style='color: blue; font-weight: bold'>ClassificationTypeNames = "EditorClassifier"</span>)] [Name("EditorClassifier")] [UserVisible(true)] // This should be visible to the end user [Order(Before = Priority.Default)] // Set the priority to be after the default classifiers internal sealed class EditorClassifierFormat : ClassificationFormatDefinition { public EditorClassifierFormat() { this.DisplayName = "EditorClassifier"; // Human readable version of the name this.BackgroundColor = Colors.BlueViolet; this.TextDecorations = System.Windows.TextDecorations.Underline; } } } </pre> <br /> (즉, 여러분들이 이 문자열 값을 변경하려면 3군데의 값을 모두 일치시켜야 합니다. 그냥 상수로 정의해 쓰시는 것이!)<br /> <br /> 이제, 다시 EditorClassifier 클래스의 GetClassificationSpans 메서드를 보면 감이 옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) { var result = new List<ClassificationSpan>() { new ClassificationSpan(new SnapshotSpan(span.Snapshot, new Span(span.Start, span.Length)), <span style='color: blue; font-weight: bold'>this.classificationType</span>) }; return result; } </pre> <br /> this.classificationType은 결국 EditorClassifierFormat에 지정된 양식을 사용하는 것과 같습니다.<br /> <br /> 그럼, 이를 바탕으로 INI 파일의 포맷팅을 완성해 볼까요? ^^<br /> <br /> 여기서 구현하는 INI 포맷팅은 다음의 2가지만을 구현합니다.<br /> <br /> <ul> <li>섹션명은 파란색의 굵은 글씨체로 지정</li> <li>Key = Value의 Key 값은 빨간색의 굵은 글씨체로 지정</li> </ul> <br /> 이를 위해 각각의 포맷팅을 담은 클래스를 준비하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.ComponentModel.Composition; using System.Windows.Media; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Utilities; namespace IniColorizer { [Export(typeof(EditorFormatDefinition))] [ClassificationType(<span style='color: blue; font-weight: bold'>ClassificationTypeNames = "SectionNameTypeClassifier"</span>)] [Name("SectionNameFormat")] [UserVisible(true)] // This should be visible to the end user [Order(Before = Priority.Default)] // Set the priority to be after the default classifiers internal sealed class SectionNameClassifierFormat : ClassificationFormatDefinition { public SectionNameClassifierFormat() { this.DisplayName = "SectionNameClassifier"; // Human readable version of the name <span style='color: blue; font-weight: bold'>this.IsBold = true; this.ForegroundColor = Colors.Blue;</span> } } [Export(typeof(EditorFormatDefinition))] [ClassificationType(<span style='color: blue; font-weight: bold'>ClassificationTypeNames = "KeyValueTypeClassifier"</span>)] [Name("KeyValueFormat")] [UserVisible(true)] // This should be visible to the end user [Order(Before = Priority.Default)] // Set the priority to be after the default classifiers internal sealed class KeyValueClassifierFormat : ClassificationFormatDefinition { public KeyValueClassifierFormat() { this.DisplayName = "KeyValueClassifier"; // Human readable version of the name <span style='color: blue; font-weight: bold'>this.ForegroundColor = Colors.Red; this.IsBold = true;</span> } } } </pre> <br /> 각각의 클래스에 지정된 ClassificationTypeNames에 따라 ClassificationDefinition 클래스에 동일한 이름을 갖는 속성 값을 정의합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.ComponentModel.Composition; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Utilities; namespace IniColorizer { internal static class ClassificationDefinition { #pragma warning disable 169 [Export(typeof(ClassificationTypeDefinition))] [Name(<span style='color: blue; font-weight: bold'>"SectionNameTypeClassifier"</span>)] private static ClassificationTypeDefinition typeDefinition1; [Export(typeof(ClassificationTypeDefinition))] [Name(<span style='color: blue; font-weight: bold'>"KeyValueTypeClassifier"</span>)] private static ClassificationTypeDefinition typeDefinition2; #pragma warning restore 169 } } </pre> <br /> 사실 ClassificationDefinition 클래스의 정의는 별다르게 제약이 없습니다. 그래서, 위의 클래스를 다음과 같이 2개로 나눠도 상관없습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.ComponentModel.Composition; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Utilities; namespace IniColorizer { internal static class SectionNameClassificationDefinition { #pragma warning disable 169 [Export(typeof(ClassificationTypeDefinition))] [Name(<span style='color: blue; font-weight: bold'>"SectionNameTypeClassifier"</span>)] private static ClassificationTypeDefinition typeDefinition; #pragma warning restore 169 } internal static class KeyValueClassificationDefinition { #pragma warning disable 169 [Export(typeof(ClassificationTypeDefinition))] [Name(<span style='color: blue; font-weight: bold'>"KeyValueTypeClassifier"</span>)] private static ClassificationTypeDefinition typeDefinition; #pragma warning restore 169 } } </pre> <br /> 마지막으로, EditorClassifier 클래스에서는 편집된 문자열에 따라 섹션명인지, Key=Value 쌍인지 구분해서 그에 따른 포맷팅의 구분 타입만 지정해주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Collections.Generic; using Microsoft.VisualStudio.Language.StandardClassification; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Classification; namespace IniColorizer { internal class EditorClassifier : IClassifier { private readonly IClassificationType sectionNameClassifierType; private readonly IClassificationType keyValueClassifierType; internal EditorClassifier(IClassificationTypeRegistryService registry) { <span style='color: blue; font-weight: bold'>this.sectionNameClassifierType = registry.GetClassificationType("SectionNameTypeClassifier"); this.keyValueClassifierType = registry.GetClassificationType("KeyValueTypeClassifier");</span> } #region IClassifier #pragma warning disable 67 public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged; #pragma warning restore 67 public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) { var result = new List<ClassificationSpan>(); string modified = span.GetText(); do { if (AddIfSection(result, span, modified, this.sectionNameClassifierType) == true) { break; } if (AddIfKeyValue(result, span, modified, this.keyValueClassifierType) == true) { break; } } while (false); return result; } #endregion private bool AddIfKeyValue(List<ClassificationSpan> result, SnapshotSpan span, string modified, IClassificationType type) { int pos = modified.IndexOf('='); if (pos == -1) { return false; } <span style='color: blue; font-weight: bold'>result.Add(new ClassificationSpan(new SnapshotSpan(span.Snapshot, new Span(span.Start, pos)), type));</span> return true; } private bool AddIfSection(List<ClassificationSpan> result, SnapshotSpan span, string modified, IClassificationType type) { int startPos, endPos; if (RetrieveSection(modified, out startPos, out endPos) == false) { return false; } <span style='color: blue; font-weight: bold'>result.Add(new ClassificationSpan(new SnapshotSpan(span.Snapshot, new Span(span.Start, span.Length)), type));</span> return true; } private bool RetrieveSection(string modified, out int startPos, out int endPos) { endPos = 0; startPos = modified.IndexOf('['); if (startPos == -1) { return false; } endPos = modified.IndexOf(']', startPos); if (endPos == -1 || startPos > endPos) { return false; } return true; } } } </pre> <br /> 확인을 위해 F5 키를 눌러 실행된 Visual Studio 편집기에서 INI 파일을 열어 보면 다음과 같은 식으로 문자열이 포맷팅됩니다.<br /> <br /> <img alt='colorizer_vsix_3.png' src='/SysWebRes/bbs/colorizer_vsix_3.png' /><br /> <br /> <hr style='width: 50%' /><br /> <br /> 포맷팅의 경우, 비주얼 스튜디오에 이미 정의된 것들을 사용하는 것도 가능합니다. 예를 들어, 일부 포맷팅과 관련된 ClassificationTypeNames 이름을 다음의 클래스에서 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > PredefinedClassificationTypeNames Class ; <a target='tab' href='https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.language.standardclassification.predefinedclassificationtypenames'>https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.language.standardclassification.predefinedclassificationtypenames</a> </pre> <br /> 예를 들어, 우리가 만든 INIColorizer 확장에서 섹션명의 포맷을 PredefinedClassificationTypeNames.Keyword로 지정하려면 이렇게 코딩할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // EditorClassifier.cs internal EditorClassifier(IClassificationTypeRegistryService registry) { // PredefinedClassificationTypeNames 사용을 위해 Microsoft.VisualStudio.Language.StandardClassification.dll 참조 추가 필요 this.sectionNameClassifierType = registry.GetClassificationType(<span style='color: blue; font-weight: bold'>PredefinedClassificationTypeNames.Keyword</span>); } </pre> <br /> 하지만, 해당 속성값이 단순히 문자열이기 때문에 굳이 Microsoft.VisualStudio.Language.StandardClassification.dll 어셈블리를 참조 추가할 필요없이 이렇게 쓰는 것도 가능합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // EditorClassifier.cs internal EditorClassifier(IClassificationTypeRegistryService registry) { this.sectionNameClassifierType = registry.GetClassificationType(<span style='color: blue; font-weight: bold'>"keyword"</span>); } </pre> <br /> 여기에 사용되는 문자열을 좀 더 알고 싶다면 비주얼 스튜디오의 "Tools" / "Options..."에서 "Environment" / "Fonts and Colors"를 보면 됩니다.<br /> <br /> <img alt='colorizer_vsix_4.png' src='/SysWebRes/bbs/colorizer_vsix_4.png' /><br /> <br /> 이렇게 비주얼 스튜디오에 이미 정의된 포맷을 사용하면 좋은 점이, 사용자가 임의로 변경할 수 있다는 것입니다. 그리고, 개발자 입장에서도 별다르게 ClassificationDefinition.cs, EditorClassifierFormat.cs 파일을 만들지 않아도 됩니다. 그저 다음과 같이 기존 정의된 포맷을 쓰면 그만입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // EditorClassifier.cs internal EditorClassifier(IClassificationTypeRegistryService registry) { this.sectionNameClassifierType = registry.GetClassificationType("keyword"); this.keyValueClassifierType = registry.GetClassificationType("symbol definition"); } </pre> <br /> 이 정도면... 이제 여러분들이 회사에서 내부 용도로 만든 '스크립트 언어'가 있다면 비주얼 스튜디오를 이용해 쉽게 "Syntax Highlighting" 기능을 구현할 수 있을 것입니다. ^^ 그리곤 비주얼 스튜디오 갤러리에 등록해 보면 더욱 멋지겠지요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Visual Studio 제품 및 확장 기능 ; <a target='tab' href='https://marketplace.visualstudio.com/'>https://marketplace.visualstudio.com/</a> </pre> <br /> 저도 이 예제를 등록했답니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Simple INI Syntax Highlighter ; <a target='tab' href='https://marketplace.visualstudio.com/items?itemName=SeongTaeJeong.SimpleINISyntaxHighlighter'>https://marketplace.visualstudio.com/items?itemName=SeongTaeJeong.SimpleINISyntaxHighlighter</a> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, INI highlighting 용 확장은 이미 Visual Studio 갤러리에 좋은 것들이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > TextHighlighterExtension2013 ; <a target='tab' href='https://marketplace.visualstudio.com/items?itemName=FredericTorres.TextHighlighterExtension2013'>https://marketplace.visualstudio.com/items?itemName=FredericTorres.TextHighlighterExtension2013</a> </pre> <br /> Visual Studio 2010 용이지만 "Boo" 라는 언어를 위한 syntax hightlighting 확장을 만든 소스 코드도 공개된 것이 있고.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Boo syntax highlighting for Visual Studio 2010 ; <a target='tab' href='http://vs2010boo.codeplex.com/'>http://vs2010boo.codeplex.com/</a> </pre> <br /> 여기서 다루진 않았지만 다음과 같은 방법도 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Syntax Colorizing (Managed Package Framework) ; <a target='tab' href='https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/syntax-colorizing-in-a-legacy-language-service'>https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/syntax-colorizing-in-a-legacy-language-service</a> </pre> <br /> (첨부한 파일은 이 글의 예제 코드를 포함합니다. 또는 <a target='tab' href='https://github.com/stjeong/IniColorizer'>https://github.com/stjeong/IniColorizer</a>에도 올려놨으니 참고하세요. ^^)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8536
(왼쪽의 숫자를 입력해야 합니다.)