Trebuie sa realizez un editor xml/xhtml care sa aiba suport pentru dcmi, foaf, doap, sioc. M-am gandit la Visual Studio si, citind putinele tutoriale despre code completion (la asta sunt acum) m-am blocat. Incercand sa fac ceva de test, mi-am zis sa includ in "limbaj" cuvintele using, system, io. Prima data cand apas pe tasta 'u' imi apare o lista care contine doar cuvantul using, apoi scriu s, si apare o lista cu "system". Toate bune si frumoase dar cand apas .(punct) ar trebui sa imi apara o lista care sa imi descrie toate cuvintele ce se potrivesc acestui context(adica doar io). Iar asta nu se intampla. Evident, pentru ca nu am implementat asa ceva(yet). Intrebarea mea este: cum as putea sa aflu ultimul cuvant care a fost auto-completed?
Astfel as putea retine un arbore si de fiecare data cand fac matching la system de exemplu ma pot uita in arbore si vad ca are ca fiu doar pe io. si afisez astfel toti fii lui system in lista de auto-complete...
Urmeaza cele 3 fisiere de cod:
TestCompletionSource.cs
Cod sursă:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
namespace EditorClassifier1
{
internal class TestCompletionSource : ICompletionSource
{
private TestCompletionSourceProvider m_sourceProvider;
private ITextBuffer m_textBuffer;
private List m_compList;
public TestCompletionSource(TestCompletionSourceProvider sourceProvider, ITextBuffer textBuffer)
{
m_sourceProvider = sourceProvider;
m_textBuffer = textBuffer;
}
void ICompletionSource.AugmentCompletionSession(ICompletionSession session, IList completionSets)
{
List strList = new List();
strList.Add("using");
strList.Add("system");
strList.Add("io");
m_compList = new List();
foreach (string str in strList)
m_compList.Add(new Completion(str, str, str, null, null));
completionSets.Add(new CompletionSet(
"Tokens", //the non-localized title of the tab
"Tokens", //the display title of the tab
FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer),
session),
m_compList,
null));
}
private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session)
{
SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1;
ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer);
TextExtent extent = navigator.GetExtentOfWord(currentPoint);
return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
}
private bool m_isDisposed;
public void Dispose()
{
if (!m_isDisposed)
{
GC.SuppressFinalize(this);
m_isDisposed = true;
}
}
}
}
TestCompletionSourceProvider.cs
Cod sursă:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
namespace EditorClassifier1
{
[Export(typeof(ICompletionSourceProvider))]
[ContentType("plaintext")]
[Name("token completion")]
internal class TestCompletionSourceProvider : ICompletionSourceProvider
{
[Import]
internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer)
{
return new TestCompletionSource(this, textBuffer);
}
}
}
TestCompletionCommandHandler.cs
Cod sursă:
using System;
using System.IO;
using System.ComponentModel.Composition;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
namespace EditorClassifier1
{
[Export(typeof(IVsTextViewCreationListener))]
[Name("token completion handler")]
[ContentType("plaintext")]
[TextViewRole(PredefinedTextViewRoles.Editable)]
internal class TestCompletionHandlerProvider : IVsTextViewCreationListener
{
[Import]
internal IVsEditorAdaptersFactoryService AdapterService = null;
[Import]
internal ICompletionBroker CompletionBroker { get; set; }
[Import]
internal SVsServiceProvider ServiceProvider { get; set; }
public void VsTextViewCreated(IVsTextView textViewAdapter)
{
ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
if (textView == null)
return;
Func createCommandHandler = delegate() { return new TestCompletionCommandHandler(textViewAdapter, textView, this); };
textView.Properties.GetOrCreateSingletonProperty(createCommandHandler);
}
}
internal class TestCompletionCommandHandler : IOleCommandTarget
{
String currentWord = "";
String lastWord = "";
private IOleCommandTarget m_nextCommandHandler;
private ITextView m_textView;
private TestCompletionHandlerProvider m_provider;
private ICompletionSession m_session;
internal TestCompletionCommandHandler(IVsTextView textViewAdapter, ITextView textView, TestCompletionHandlerProvider provider)
{
this.m_textView = textView;
this.m_provider = provider;
//add the command to the command chain
textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
}
public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
private bool TriggerCompletion()
{
//the caret must be in a non-projection location
SnapshotPoint? caretPoint =
m_textView.Caret.Position.Point.GetPoint(
textBuffer => (!textBuffer.ContentType.IsOfType("projection")), PositionAffinity.Predecessor);
if (!caretPoint.HasValue)
{
return false;
}
m_session = m_provider.CompletionBroker.CreateCompletionSession
(m_textView,
caretPoint.Value.Snapshot.CreateTrackingPoint(caretPoint.Value.Position, PointTrackingMode.Positive),
true);
//subscribe to the Dismissed event on the session
m_session.Dismissed += this.OnSessionDismissed;
m_session.Start();
currentWord = "";
// get current word ...
lastWord = currentWord;
currentWord = "";
// create a writer and open the file
TextWriter tw = new StreamWriter("C:datecommandhandler.txt");
// write a line of text to the file
tw.WriteLine("A: " + lastWord);
// close the stream
tw.Close();
return true;
}
private void OnSessionDismissed(object sender, EventArgs e)
{
m_session.Dismissed -= this.OnSessionDismissed;
m_session = null;
}
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
{
if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
{
return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
}
//make a copy of this so we can look at it after forwarding some commands
uint commandID = nCmdID;
char typedChar = char.MinValue;
//make sure the input is a char before getting it
if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
{
typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
}
//check for a commit character
if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN
|| nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB
|| (char.IsWhiteSpace(typedChar) /*|| char.IsPunctuation(typedChar)*/))
{
//check for a selection
if (m_session != null && !m_session.IsDismissed)
{
//if the selection is fully selected, commit the current session
if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
{
m_session.Commit();
//also, don't add the character to the buffer
return VSConstants.S_OK;
}
else
{
//if there is no selection, dismiss the session
m_session.Dismiss();
}
}
}
if (m_session != null && !m_session.IsDismissed)
{
if (char.IsPunctuation(typedChar))
{
this.TriggerCompletion();
m_session.Filter();
return VSConstants.S_OK;
}
}
//pass along the command so the char is added to the buffer
int retVal = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
bool handled = false;
if (!typedChar.Equals(char.MinValue)/* && char.IsLetterOrDigit(typedChar)*/)
{
if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion
{
this.TriggerCompletion();
m_session.Filter();
}
else //the completion session is already active, so just filter
{
m_session.Filter();
}
handled = true;
}
else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE //redo the filter if there is a deletion
|| commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
{
if (m_session != null && !m_session.IsDismissed)
m_session.Filter();
handled = true;
}
if (handled) return VSConstants.S_OK;
return retVal;
}
}
}