protected abstract SyntaxAnalyser CreateSyntaxAnalyser ();
public abstract IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode currentNode, CharLocation loc);
- /// <summary>
- /// complete current token with selected item from the suggestion overlay.
- /// It may set a new position or a new selection.
- /// </summary>
- /// <param name="suggestion">selected object of suggestion overlay</param>
- /// /// <param name="change">the text change to apply</param>
- /// <param name="newSelection">new position or selection, null if normal position after text changes</param>
- /// <returns>true if successed</returns>
- //public abstract bool TryCompleteToken (Token CurrentToken, SyntaxNode CurrentNode, object suggestion, out TextChange change, out TextSpan? newSelection);
- //protected bool previousTokHasFlag(TokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
void parse () {
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
root = syntaxAnalyser?.Process ();
public TextChange Change;
public TextSpan? NextSelection;
- public Suggestion(string caption, TextChange change = default, TextSpan? nextSelection = null) {
+ public Suggestion(string caption, TextChange change = default, int finalPositionOffset = 0) {
Caption = caption;
Change = change;
- NextSelection = nextSelection;
+ NextSelection = finalPositionOffset < 0 ? TextSpan.FromStartAndLength(change.End2 + finalPositionOffset) : null;
}
}
public class SourceEditor : Editor {
if (currentLoc.HasValue && Document is SourceDocument srcDoc && srcDoc.IsParsed) {
int pos = srcDoc.GetAbsolutePosition(CurrentLoc.Value);
Suggestions = srcDoc.GetSuggestions (pos, currentTokenIndex, currentNode, CurrentLoc.Value);
-
- /*Token tok = CurrentToken;
- if (suggs != null && suggs.Count == 1 && (
- (suggs[0] is System.Reflection.MemberInfo mi && mi.Name == srcDoc.GetText(tok.Span)) ||
- (suggs[0].ToString() == srcDoc.GetText(tok.Span))
- )){
- Suggestions = null;
- }else
- Suggestions = suggs;*/
} else
Suggestions = null;
}
void showOverlay () {
lock (IFace.UpdateMutex) {
if (overlay == null) {
- overlay = IFace.LoadIMLFragment<ListBox>(@"
- <ListBox Style='suggestionsListBox' Data='{Suggestions}' UseLoadingThread = 'false'>
- <ItemTemplate>
- <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
- Selected = '{Background=${ControlHighlight}}'
- Unselected = '{Background=Transparent}'>
- <Label Text='{Caption}' HorizontalAlignment='Left' />
- </ListItem>
- </ItemTemplate>
- <ItemTemplate DataType='System.Reflection.MemberInfo'>
- <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
- Selected = '{Background=${ControlHighlight}}'
- Unselected = '{Background=Transparent}'>
- <HorizontalStack>
- <!--<Image Picture='{GetIcon}' Width='16' Height='16'/>-->
- <Label Text='{Name}' HorizontalAlignment='Left' />
- </HorizontalStack>
- </ListItem>
- </ItemTemplate>
- <ItemTemplate DataType='Crow.Colors'>
- <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
- Selected = '{Background=${ControlHighlight}}'
- Unselected = '{Background=Transparent}'>
- <HorizontalStack>
- <Widget Background='{}' Width='20' Height='14'/>
- <Label Text='{}' HorizontalAlignment='Left' />
- </HorizontalStack>
- </ListItem>
- </ItemTemplate>
- </ListBox>
- ");
+ overlay = IFace.Load<ListBox>(@"#ui.SuggestionsOverlay.crow");
overlay.DataSource = this;
overlay.Loaded += (sender, arg) => (sender as ListBox).SelectedIndex = 0;
} else
}
}
-
- //double spacePixelWidth = gr.TextExtents (" ").XAdvance;
double pixX = cb.Left,
pixY = cb.Top;
ReadOnlySpan<char> sourceBytes = doc.source;
Span<byte> bytes = stackalloc byte[128];
TextExtents extents;
-
-
-
ReadOnlySpan<char> buff = sourceBytes;
-
int printedLines = 0;
int linesToSkip = (int)Math.Floor(ScrollY / lineHeight);
<?xml version="1.0"?>
<Border BorderWidth="1" Background="{./Background}" Height="Stretched" Focusable="false">
<HorizontalStack Margin="1">
- <Scroller Name="ItemsScroller" Margin="2">
+ <Scroller Name="ItemsScroller" Margin="0">
<VerticalStack Height="Fit" MinimumSize="10,10"
Name="ItemsContainer" Margin="0" VerticalAlignment="Top"/>
</Scroller>
<ScrollBar Name="scrollbar1" Value="{²../ItemsScroller.ScrollY}"
LargeIncrement="{../ItemsScroller.PageHeight}" SmallIncrement="30" CursorSize="{../ItemsScroller.ChildHeightRatio}"
Maximum="{../ItemsScroller.MaxScrollY}" Orientation="Vertical"
- Width="12" />
+ Width="10" />
</HorizontalStack>
</Border>
--- /dev/null
+<?xml version="1.0"?>
+<ListBox Style='suggestionsListBox' Data='{Suggestions}' UseLoadingThread = 'false'>
+ <ItemTemplate>
+ <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
+ Selected = '{Background=${ControlHighlight}}'
+ Unselected = '{Background=Transparent}'>
+ <Label Text='{Caption}' HorizontalAlignment='Left' Margin="2"/>
+ </ListItem>
+ </ItemTemplate>
+ <ItemTemplate DataType='System.Reflection.MemberInfo'>
+ <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
+ Selected = '{Background=${ControlHighlight}}'
+ Unselected = '{Background=Transparent}'>
+ <HorizontalStack>
+ <!--<Image Picture='{GetIcon}' Width='16' Height='16'/>-->
+ <Label Text='{Name}' HorizontalAlignment='Left' />
+ </HorizontalStack>
+ </ListItem>
+ </ItemTemplate>
+ <ItemTemplate DataType='Crow.Colors'>
+ <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
+ Selected = '{Background=${ControlHighlight}}'
+ Unselected = '{Background=Transparent}'>
+ <HorizontalStack>
+ <Widget Background='{}' Width='20' Height='14'/>
+ <Label Text='{}' HorizontalAlignment='Left' />
+ </HorizontalStack>
+ </ListItem>
+ </ItemTemplate>
+</ListBox>
\ No newline at end of file
return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
}
- public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
+ protected override IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change)
+ {
+ IEnumerable<Type> widgetTypes = typeof (Widget).Assembly.GetExportedTypes ().Where(t=>typeof(Widget).IsAssignableFrom (t));
+ int curNameLength = 0;
+ if (!string.IsNullOrEmpty(curName)) {
+ widgetTypes = widgetTypes.Where(t=>t.Name.StartsWith(curName, StringComparison.OrdinalIgnoreCase));
+ curNameLength = curName.Length;
+ }
+ int endPosOffset = change.HasNewText ? -change.ChangedText.Length : 0;
+ return widgetTypes.Select (t
+ => new Suggestion(t.Name,
+ new TextChange(change.Start, change.Length, t.Name + change.ChangedText), endPosOffset));
+ }
+ /*public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
IList sugs = base.GetSuggestions (absoluteTextPos, currentTokenIndex, CurrentNode, loc);
if (sugs != null)
return sugs;
- //Token tok = currentToken.Length == 0 || currentToken.Type.HasFlag(TokenType.Trivia) ? previousToken : currentToken;
- /*Token tok = GetTokenByIndex(currentTokenIndex);
+
+ Token tok = GetTokenByIndex(currentTokenIndex);
if (tok.GetTokenType() == XmlTokenType.ElementOpen)
return new List<string> (allWidgetNames);
//else if (tok.Type == TokenType.ElementName)
// Suggestions = getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source)).ToList ();
} else {
- }*/
+ }
return null;
- }
+ }*/
public override Color GetColorForToken(TokenType tokType)
{
using System.Collections.Generic;
using System;
using Crow;
+using System.Linq;
namespace CrowEdit.Xml
{
public XmlDocument (string fullPath, string editorPath) : base (fullPath, editorPath) { }
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new XmlSyntaxAnalyser (this);
public override string GetTokenTypeString (TokenType tokenType) => ((XmlTokenType)tokenType).ToString();
+
+ protected virtual IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change) {
+
+ return null;
+ }
public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
Token tok = GetTokenByIndex(currentTokenIndex);
Token prevTok = GetTokenByIndex(currentTokenIndex-1);
- if (!tok.Is(XmlTokenType.ClosingSign) &&
- CurrentNode is ElementEndTagSyntax eltEndTag &&
- eltEndTag.Parent is ElementSyntax elt &&
- elt.StartTag?.Name != null) {
+ if (CurrentNode is ElementEndTagSyntax eltEndTag) {
+ if (!prevTok.Is(XmlTokenType.ClosingSign) &&
+ eltEndTag.Parent is ElementSyntax elt &&
+ elt.StartTag?.Name != null) {
+
+ Suggestion sug = new Suggestion(elt.StartTag.Name);
+ string curEndName = null;
+
+
+ if (tok.Is(XmlTokenType.ElementName)) {
+ curEndName = root.GetTokenString(tok);
+ sug.Change = new TextChange (tok.Start, tok.Length, sug.Caption);
+ } else if (prevTok.Is(XmlTokenType.ElementName)) {
+ curEndName = root.GetTokenString(prevTok);
+ sug.Change = new TextChange (prevTok.Start, prevTok.Length, sug.Caption);
+ } else if (prevTok.Is(XmlTokenType.EndElementOpen)) {
+ curEndName = "";
+ sug.Change = new TextChange (prevTok.End, 0, sug.Caption);
+ }
- Suggestion sug = new Suggestion(elt.StartTag.Name);
- string curEndName = null;
-
+ if (!(tok.Is(XmlTokenType.ClosingSign) || sug.Change.IsEmpty ||
+ GetTokenByIndex(currentTokenIndex+1).Is(XmlTokenType.ClosingSign)))
+ sug.Change.ChangedText += ">";
- if (tok.Is(XmlTokenType.ElementName)) {
- curEndName = root.GetTokenString(tok);
- sug.Change = new TextChange (tok.Start, tok.Length, sug.Caption);
- } else if (prevTok.Is(XmlTokenType.ElementName)) {
- curEndName = root.GetTokenString(prevTok);
- sug.Change = new TextChange (prevTok.Start, prevTok.Length, sug.Caption);
- } else if (prevTok.Is(XmlTokenType.EndElementOpen)) {
- curEndName = "";
- sug.Change = new TextChange (prevTok.End, 0, sug.Caption);
+ if (curEndName != null && elt.StartTag.Name.StartsWith (
+ curEndName, StringComparison.OrdinalIgnoreCase)
+ && !elt.StartTag.Name.Equals(curEndName, StringComparison.Ordinal))
+ return new List<Suggestion> ([sug]);
}
-
- if (!(sug.Change.IsEmpty || GetTokenByIndex(currentTokenIndex+1).Is(XmlTokenType.ClosingSign)))
- sug.Change.ChangedText += ">";
-
- if (curEndName != null && elt.StartTag.Name.StartsWith (
- curEndName, StringComparison.OrdinalIgnoreCase)
- && !elt.StartTag.Name.Equals(curEndName, StringComparison.Ordinal))
- return new List<Suggestion> ([sug]);
+ } else if (CurrentNode is ElementStartTagSyntax eltStartTag) {
+ TextChange change = default;
+ if (tok.Is(XmlTokenType.ElementName))
+ change = new TextChange (tok.Start, tok.Length);
+ else if (prevTok.Is(XmlTokenType.ElementName))
+ change = new TextChange (prevTok.Start, prevTok.Length);
+ else if (tok.Is(XmlTokenType.ElementOpen))
+ change = new TextChange (tok.End, 0);
+ else if (prevTok.Is(XmlTokenType.ElementOpen))
+ change = new TextChange (prevTok.End, 0);
+ else
+ return null;
+
+ if (!(tok.Is(XmlTokenType.ClosingSign) ||
+ GetTokenByIndex(currentTokenIndex+1).Is(XmlTokenType.ClosingSign)))
+ change.ChangedText = ">";
+
+ return getElementNameSuggestions(eltStartTag.Name, change).ToList();
}
+
return null;
}
/*
eltEndTag.close = tokIdx - eltEndTag.TokenIndexBase;
ElementSyntax es = eltEndTag.Parent as ElementSyntax;
string eltEndTagName = eltEndTag.Name;
- if (string.Equals(es.StartTag.Name, eltEndTagName, StringComparison.Ordinal)) {
- es.EndTag = eltEndTag;
- //go up 2 times
- finishCurrentNode (); finishCurrentNode ();
- } else {
+ es.EndTag = eltEndTag;
+ finishCurrentNode ();
+ if (!string.Equals(es.StartTag.Name, eltEndTagName, StringComparison.Ordinal)) {
+ addException ("Open/Close element name mismatch");
+ }
+ finishCurrentNode ();
+ /*else {
addException ("Open/Close element name mismatch");
finishCurrentNode ();//finish eltEndTag->curNode is parent elt
currentNode.RemoveChild(eltEndTag);
finishCurrentNode (-eltEndTag.TokenCount);
}
}
- }
+ }*/
} else {
addException ("Unexpected Token");
finishCurrentNode (-1);