Skip to content

Commit 0f5f7d8

Browse files
committed
Merge branch 'jaredpar-port-EditorConfig'
2 parents 240a689 + 5f9f856 commit 0f5f7d8

9 files changed

+661
-1
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.ComponentModel.Composition;
2+
using Microsoft.VisualStudio.Text;
3+
using Microsoft.VisualStudio.Text.Classification;
4+
using Microsoft.VisualStudio.Utilities;
5+
using EditorConfig.VisualStudio.ContentType;
6+
7+
namespace EditorConfig.VisualStudio.Classify
8+
{
9+
[Export(typeof(IClassifierProvider))]
10+
[ContentType(EditorConfigContentTypeDefinition.EditorConfigContentType)]
11+
class EditorConfigClassifierProvider : IClassifierProvider
12+
{
13+
[Import]
14+
public IClassificationTypeRegistryService Registry { get; set; }
15+
16+
public IClassifier GetClassifier(ITextBuffer textBuffer)
17+
{
18+
return textBuffer.Properties.GetOrCreateSingletonProperty(() => new EditorConfigClassifier(Registry));
19+
}
20+
}
21+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text.RegularExpressions;
5+
using Microsoft.VisualStudio.Language.StandardClassification;
6+
using Microsoft.VisualStudio.Text;
7+
using Microsoft.VisualStudio.Text.Classification;
8+
9+
namespace EditorConfig.VisualStudio.Classify
10+
{
11+
class EditorConfigClassifier : IClassifier
12+
{
13+
private static Regex _rxKeywords = new Regex(@"(?<=\=\s?)([a-zA-Z0-9-]+)\b", RegexOptions.Compiled);
14+
private static Regex _rxIdentifier = new Regex(@"^([^=]+)\b(?=\=?)", RegexOptions.Compiled);
15+
private static Regex _rxString = new Regex(@"\[([^\]]+)\]", RegexOptions.Compiled);
16+
private static Regex _rxComment = new Regex(@"#.*", RegexOptions.Compiled);
17+
private static List<Tuple<Regex, IClassificationType>> _map;
18+
19+
public EditorConfigClassifier(IClassificationTypeRegistryService registry)
20+
{
21+
if (_map == null)
22+
_map = new List<Tuple<Regex, IClassificationType>>
23+
{
24+
{Tuple.Create(_rxComment, registry.GetClassificationType(PredefinedClassificationTypeNames.Comment))},
25+
{Tuple.Create(_rxString, registry.GetClassificationType(PredefinedClassificationTypeNames.String))},
26+
{Tuple.Create(_rxIdentifier, registry.GetClassificationType(PredefinedClassificationTypeNames.SymbolDefinition))},
27+
{Tuple.Create(_rxKeywords, registry.GetClassificationType(PredefinedClassificationTypeNames.Literal))},
28+
};
29+
}
30+
31+
public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
32+
{
33+
IList<ClassificationSpan> list = new List<ClassificationSpan>();
34+
ITextSnapshotLine line = span.Start.GetContainingLine();
35+
string text = line.GetText();
36+
37+
foreach (var tuple in _map)
38+
foreach (Match match in tuple.Item1.Matches(text))
39+
{
40+
var str = new SnapshotSpan(line.Snapshot, line.Start.Position + match.Index, match.Length);
41+
42+
// Make sure we don't double classify
43+
if (list.Any(s => s.Span.IntersectsWith(str)))
44+
continue;
45+
46+
list.Add(new ClassificationSpan(str, tuple.Item2));
47+
}
48+
49+
return list;
50+
}
51+
52+
public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged
53+
{
54+
add { }
55+
remove { }
56+
}
57+
}
58+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace EditorConfig.VisualStudio
5+
{
6+
class CompletionItem
7+
{
8+
private static List<CompletionItem> _dic = new List<CompletionItem>
9+
{
10+
{new CompletionItem("root", "Special property that should be specified at the top of the file outside of any sections. Set to “true” to stop .editorconfig files search on current file.", "true")},
11+
{new CompletionItem("indent_style", "Indentation Style", "tab", "space")},
12+
{new CompletionItem("indent_size", "Indentation Size (in single-spaced characters)", "tab") },
13+
{new CompletionItem("tab_width", "Width of a single tabstop character") },
14+
{new CompletionItem("end_of_line", "Line ending file format (Unix, DOS, Mac)", "lf", "crlf", "cr") },
15+
{new CompletionItem("charset", "File character encoding", "latin1", "utf-8", "utf-1be", "utf-1le")},
16+
{new CompletionItem("trim_trailing_whitespace", "Denotes whether whitespace is allowed at the end of lines", "true", "false")},
17+
{new CompletionItem("insert_final_newline", "Denotes whether file should end with a newline", "true", "false")},
18+
{new CompletionItem("max_line_length", "Forces hard line wrapping after the amount of characters specified")},
19+
};
20+
21+
private CompletionItem(string name, string description, params string[] values)
22+
{
23+
this.Name = name;
24+
this.Description = description;
25+
this.Values = values;
26+
}
27+
28+
public static IEnumerable<CompletionItem> Items
29+
{
30+
get { return _dic; }
31+
}
32+
33+
public static CompletionItem GetCompletionItem(string name)
34+
{
35+
return _dic.SingleOrDefault(c => c.Name == name);
36+
}
37+
38+
public string Name { get; set; }
39+
public string Description { get; set; }
40+
public IEnumerable<string> Values { get; set; }
41+
}
42+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using Microsoft.VisualStudio;
4+
using Microsoft.VisualStudio.Language.Intellisense;
5+
using Microsoft.VisualStudio.OLE.Interop;
6+
using Microsoft.VisualStudio.Text;
7+
using Microsoft.VisualStudio.Text.Editor;
8+
9+
namespace EditorConfig.VisualStudio
10+
{
11+
internal sealed class CommandFilter : IOleCommandTarget
12+
{
13+
private ICompletionSession _currentSession;
14+
15+
public CommandFilter(IWpfTextView textView, ICompletionBroker broker)
16+
{
17+
_currentSession = null;
18+
19+
TextView = textView;
20+
Broker = broker;
21+
}
22+
23+
public IWpfTextView TextView { get; private set; }
24+
public ICompletionBroker Broker { get; private set; }
25+
public IOleCommandTarget Next { get; set; }
26+
27+
private static char GetTypeChar(IntPtr pvaIn)
28+
{
29+
return (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
30+
}
31+
32+
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
33+
{
34+
bool handled = false;
35+
int hresult = VSConstants.S_OK;
36+
37+
// 1. Pre-process
38+
if (pguidCmdGroup == VSConstants.VSStd2K)
39+
{
40+
switch ((VSConstants.VSStd2KCmdID)nCmdID)
41+
{
42+
case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
43+
case VSConstants.VSStd2KCmdID.COMPLETEWORD:
44+
case VSConstants.VSStd2KCmdID.SHOWMEMBERLIST:
45+
handled = StartSession();
46+
break;
47+
case VSConstants.VSStd2KCmdID.RETURN:
48+
handled = Complete(false);
49+
break;
50+
case VSConstants.VSStd2KCmdID.TAB:
51+
handled = Complete(true);
52+
break;
53+
case VSConstants.VSStd2KCmdID.CANCEL:
54+
handled = Cancel();
55+
break;
56+
}
57+
}
58+
59+
if (!handled)
60+
hresult = Next.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
61+
62+
if (ErrorHandler.Succeeded(hresult))
63+
{
64+
if (pguidCmdGroup == VSConstants.VSStd2K)
65+
{
66+
switch ((VSConstants.VSStd2KCmdID)nCmdID)
67+
{
68+
case VSConstants.VSStd2KCmdID.TYPECHAR:
69+
char ch = GetTypeChar(pvaIn);
70+
if (ch == '=' || ch == ' ')
71+
Cancel();
72+
else if (!char.IsPunctuation(ch) && !char.IsControl(ch))
73+
StartSession();
74+
else if (_currentSession != null)
75+
Filter();
76+
break;
77+
case VSConstants.VSStd2KCmdID.BACKSPACE:
78+
if (_currentSession == null)
79+
StartSession();
80+
81+
Filter();
82+
break;
83+
}
84+
}
85+
}
86+
87+
return hresult;
88+
}
89+
90+
private void Filter()
91+
{
92+
if (_currentSession == null)
93+
return;
94+
95+
_currentSession.SelectedCompletionSet.SelectBestMatch();
96+
_currentSession.SelectedCompletionSet.Recalculate();
97+
}
98+
99+
bool Cancel()
100+
{
101+
if (_currentSession == null)
102+
return false;
103+
104+
_currentSession.Dismiss();
105+
106+
return true;
107+
}
108+
109+
bool Complete(bool force)
110+
{
111+
if (_currentSession == null)
112+
return false;
113+
114+
if (!_currentSession.SelectedCompletionSet.SelectionStatus.IsSelected && !force)
115+
{
116+
_currentSession.Dismiss();
117+
return false;
118+
}
119+
else
120+
{
121+
_currentSession.Commit();
122+
return true;
123+
}
124+
}
125+
126+
bool StartSession()
127+
{
128+
if (_currentSession != null)
129+
return false;
130+
131+
SnapshotPoint caret = TextView.Caret.Position.BufferPosition;
132+
ITextSnapshot snapshot = caret.Snapshot;
133+
134+
if (!Broker.IsCompletionActive(TextView))
135+
{
136+
_currentSession = Broker.CreateCompletionSession(TextView, snapshot.CreateTrackingPoint(caret, PointTrackingMode.Positive), true);
137+
}
138+
else
139+
{
140+
_currentSession = Broker.GetSessions(TextView)[0];
141+
}
142+
_currentSession.Dismissed += (sender, args) => _currentSession = null;
143+
144+
if (!_currentSession.IsStarted)
145+
_currentSession.Start();
146+
147+
return true;
148+
}
149+
150+
public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
151+
{
152+
if (pguidCmdGroup == VSConstants.VSStd2K)
153+
{
154+
switch ((VSConstants.VSStd2KCmdID)prgCmds[0].cmdID)
155+
{
156+
case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
157+
case VSConstants.VSStd2KCmdID.COMPLETEWORD:
158+
case VSConstants.VSStd2KCmdID.SHOWMEMBERLIST:
159+
prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED;
160+
return VSConstants.S_OK;
161+
}
162+
}
163+
return Next.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
164+
}
165+
}
166+
}

0 commit comments

Comments
 (0)