using Crow.Text;
using System.Diagnostics;
using System.Collections;
+using System.Collections.Generic;
namespace CrowEditBase
{
protected Token[] tokens;
protected SyntaxNode RootNode;
protected LineCollection lines;
- protected Token currentToken;
- protected SyntaxNode currentNode;
+ protected Token currentToken => currentTokenIndex < 0 ? default : tokens[currentTokenIndex];
+ SyntaxNode currentNode;
+ public SyntaxNode CurrentNode {
+ get => currentNode;
+ set {
+ if (currentNode == value)
+ return;
+ currentNode = value;
+ NotifyValueChanged ("CurrentNode", currentNode);
+ }
+ }
+ public string CurrentTokenString => RootNode?.Root.GetTokenStringByIndex (currentTokenIndex);
+ public Token CurrentToken => currentToken;
+
+ //public SyntaxNode EditedNode { get; protected set; }
+ protected int currentTokenIndex;
public Token[] Tokens => tokens;
public SyntaxNode SyntaxRootNode => RootNode;
+ public IEnumerable<SyntaxNode> SyntaxRootChildNodes => RootNode?.children;
public LineCollection Lines => lines;
public Token FindTokenIncludingPosition (int pos) {
if (pos == 0 || tokens == null || tokens.Length == 0)
return default;
return RootNode.FindNodeIncludingPosition<T> (pos);
}
+ public SyntaxNode FindNodeIncludingSpan (TextSpan span) {
+ if (RootNode == null)
+ return null;
+ if (!RootNode.Contains (span))
+ return null;
+ return RootNode.FindNodeIncludingSpan (span);
+ }
protected override void reloadFromFile () {
base.reloadFromFile ();
parse ();
}
protected override void apply(TextChange change)
{
+ SyntaxNode editedNode = FindNodeIncludingSpan (new TextSpan (change.Start, change.End));
+
base.apply(change);
- parse ();
+
+ Tokenizer tokenizer = CreateTokenizer ();
+ tokens = tokenizer.Tokenize (Source);
+ SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
+ syntaxAnalyser.Process ();
+
+ SyntaxNode newNode = syntaxAnalyser.Root.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
+
+ if (editedNode == null) {
+ //System.Diagnostics.Debugger.Break ();
+ RootNode = syntaxAnalyser.Root;
+ } else if (newNode.IsSimilar (editedNode)) {
+ if (!tryReplaceNode (editedNode, newNode))
+ RootNode = syntaxAnalyser.Root;
+ } else if (newNode.Parent != null && newNode.Parent.IsSimilar (editedNode)) {
+ if (!tryReplaceNode (editedNode, newNode.Parent))
+ RootNode = syntaxAnalyser.Root;
+ } else if (editedNode.Parent != null && newNode.IsSimilar (editedNode.Parent)) {
+ if (!tryReplaceNode (editedNode.Parent, newNode))
+ RootNode = syntaxAnalyser.Root;
+ } else if (newNode.Parent != null && editedNode.Parent != null && newNode.Parent.IsSimilar (editedNode.Parent)) {
+ if (!tryReplaceNode (editedNode.Parent, newNode.Parent))
+ RootNode = syntaxAnalyser.Root;
+ } else {
+ //System.Diagnostics.Debugger.Break ();
+ RootNode = syntaxAnalyser.Root;
+ }
+
+ //updateCurrentTokAndNode (change.End2);
+ //EditedNode = editedNode;
+
+ //Console.WriteLine ($"CurrentToken: idx({currentTokenIndex}) {currentToken} {RootNode.Root.GetTokenStringByIndex(currentTokenIndex)}");
+ }
+ static bool tryReplaceNode (SyntaxNode editedNode, SyntaxNode newNode) {
+ if (newNode is SyntaxRootNode || editedNode is SyntaxRootNode)
+ return false;
+ editedNode.Replace (newNode);
+ return true;
+ }
+
+ internal void updateCurrentTokAndNode (int pos) {
+ if (tokens.Length > 0) {
+ currentTokenIndex = FindTokenIndexIncludingPosition (pos);
+ CurrentNode = FindNodeIncludingSpan (currentToken.Span);
+ NotifyValueChanged ("CurrentTokenString", (object)CurrentTokenString);
+ }else {
+ currentTokenIndex = -1;
+ CurrentNode = null;
+ NotifyValueChanged ("CurrentTokenString", (object)"no token");
+ }
}
public virtual Crow.Color GetColorForToken (TokenType tokType) {
/// 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>the TextChange to apply to the source</returns>
- public abstract TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection);
+ /// <returns>true if successed</returns>
+ public abstract bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection);
void parse () {
Tokenizer tokenizer = CreateTokenizer ();
tokens = tokenizer.Tokenize (Source);
using System.Collections.Generic;
using System.Linq;
using Crow.Text;
+using Crow;
namespace CrowEditBase
{
this.source = source;
}
public override int TokenIndexBase => 0;
- public override int? LastTokenOffset { get => source.Tokens.Length - 1; set {} }
+ public override int? LastTokenOffset { get => Math.Max (0, source.Tokens.Length - 1); internal set {} }
public override SyntaxRootNode Root => this;
public override bool IsFoldable => false;
public override SyntaxNode NextSiblingOrParentsNextSibling => null;
public override void UnfoldToTheTop() {}
+ public string GetTokenStringByIndex (int idx) =>
+ idx >= 0 && idx < Root.source.Tokens.Length ? Root.source.Tokens[idx].AsString (Root.source.Source) : null;
+ public Token? GetTokenByIndex (int idx) =>
+ idx >= 0 && idx < Root.source.Tokens.Length ? Root.source.Tokens[idx] : default;
}
- public class SyntaxNode {
+ public class SyntaxNode : CrowEditComponent {
+ bool _isExpanded;
+ public bool isExpanded {
+ get => _isExpanded;
+ set {
+ if (_isExpanded == value)
+ return;
+ _isExpanded = value;
+ NotifyValueChanged (_isExpanded);
+ }
+ }
+ public void ExpandToTheTop () {
+ isExpanded = true;
+ Parent?.ExpandToTheTop ();
+ }
public SyntaxNode Parent { get; private set; }
public int StartLine { get; private set; }
public virtual int LineCount => lineCount;
isFolded = false;
Parent.UnfoldToTheTop ();
}
- protected Token getTokenByIndex (int idx) => Root.source.Tokens[idx];
- List<SyntaxNode> children = new List<SyntaxNode> ();
+ protected Token getTokenByIndex (int idx) => idx < Root.source.Tokens.Length ? Root.source.Tokens[idx] : default;
+ internal List<SyntaxNode> children = new List<SyntaxNode> ();
public IEnumerable<SyntaxNode> Children => children;
+ //public int IndexOf (SyntaxNode node) => children.IndexOf (node);
public bool HasChilds => children.Count > 0;
public SyntaxNode NextSibling {
get {
}
public virtual int TokenIndexBase { get; private set; }
- public virtual int? LastTokenOffset { get; set; }
+ public virtual int? LastTokenOffset { get; internal set; }
+ public int? LastTokenIndex => TokenIndexBase + LastTokenOffset;
internal SyntaxNode () {}
public SyntaxNode (int startLine, int tokenBase, int? lastTokenIdx = null) {
StartLine = startLine;
}
internal bool isFolded;
internal int lineCount;
+
public int EndLine {
internal set {
lineCount = value - StartLine + 1;
/*if (HasChilds) {
return new TextSpan (children.First().Span.Start, children.Last().Span.End)
}*/
+ try {
Token startTok = getTokenByIndex(TokenIndexBase);
- return new TextSpan (startTok.Start, LastTokenOffset.HasValue ? getTokenByIndex (TokenIndexBase+LastTokenOffset.Value).End : startTok.End);
+ Token endTok = LastTokenOffset.HasValue ? getTokenByIndex (TokenIndexBase+LastTokenOffset.Value) : startTok;
+ return new TextSpan (startTok.Start, endTok.End);
+ }catch{
+ System.Diagnostics.Debugger.Break ();
+ }
+ return default;
}
}
child.Parent = null;
}
public T GetChild<T> () => children.OfType<T> ().FirstOrDefault ();
+ public void Replace (SyntaxNode newNode) {
+ Parent.replaceChild (this, newNode);
+ }
+ void replaceChild (SyntaxNode oldNode, SyntaxNode newNode) {
+ int idx = children.IndexOf (oldNode);
+ children[idx] = newNode;
+ newNode.Parent = this;
+ int tokIdxDiff = newNode.LastTokenOffset.Value - oldNode.LastTokenOffset.Value;
+ int lineDiff = newNode.EndLine - oldNode.EndLine;
+ if (tokIdxDiff == 0 && lineDiff == 0)
+ return;
+
+ SyntaxNode curNode = this;
+ while (curNode != null) {
+ curNode.lineCount += lineDiff;
+ curNode.LastTokenOffset += tokIdxDiff;
+ if (curNode is SyntaxRootNode)
+ break;
+ while (++idx < curNode.children.Count)
+ curNode.children[idx].offset (tokIdxDiff, lineDiff);
+ idx = curNode.Parent.children.IndexOf (curNode);
+ curNode = curNode.Parent;
+ }
+ }
+ void offset (int tokenOffset, int lineOffset) {
+ TokenIndexBase += tokenOffset;
+ StartLine += lineOffset;
+ foreach (SyntaxNode child in children) {
+ child.offset (tokenOffset, lineOffset);
+ }
+ }
public SyntaxNode FindNodeIncludingPosition (int pos) {
foreach (SyntaxNode node in children) {
if (node.Contains (pos))
return this is T tt ? tt : default;
}
+ public SyntaxNode FindNodeIncludingSpan (TextSpan span) {
+ foreach (SyntaxNode node in children) {
+ if (node.Contains (span))
+ return node.FindNodeIncludingSpan (span);
+ }
+ return this;
+ }
public bool Contains (int pos) => Span.Contains (pos);
+ public bool Contains (TextSpan span) => Span.Contains (span);
public void Dump (int level = 0) {
Console.WriteLine ($"{new string('\t', level)}{this}");
foreach (SyntaxNode node in children)
node.Dump (level + 1);
}
- public override string ToString() => $"{this.GetType().Name}: lines:({StartLine},{LineCount}) tokens:{TokenIndexBase} -> {LastTokenOffset}";
+ public override string ToString() => $"l:({StartLine,3},{LineCount,3}) tks:{TokenIndexBase},{LastTokenOffset} {this.GetType().Name}";
+ public string AsText() {
+ TextSpan span = Span;
+ return Root.source.Source.Substring (span.Start, span.Length);
+ }
+ public bool IsSimilar (SyntaxNode other) => this.GetType() == other?.GetType();
}
}
\ No newline at end of file
}
}
public string PluginsDirecory {
- get => Configuration.Global.Get<string>("PluginsDirecory");
+ get => Configuration.Global.Get<string>("PluginsDirecory", defaultPluginsDirectory);
set {
if (PluginsDirecory == value)
return;
DeleteWidget (g);
}
-
+ public ActionCommand CMDOptions_SelectPluginsDirectory => new ActionCommand ("...",
+ () => {
+ FileDialog dlg = App.LoadIMLFragment<FileDialog> (@"
+ <FileDialog Caption='Select CrowEdit Directory' CurrentDirectory='{PluginsDirecory}'
+ ShowFiles='false' ShowHidden='true' />");
+ dlg.OkClicked += (sender, e) => PluginsDirecory = (sender as FileDialog).SelectedFileFullPath;
+ dlg.DataSource = this;
+ }
+ );
+ public ActionCommand CMDOptions_ResetPluginsDirectory => new ActionCommand ("Reset",
+ () => {
+ PluginsDirecory = defaultPluginsDirectory;
+ }
+ );
+ static string defaultPluginsDirectory =>
+ Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".config", "CrowEdit", "plugins");
protected void loadPlugins () {
- if (string.IsNullOrEmpty (PluginsDirecory))
- PluginsDirecory = Path.Combine (
- Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".config", "CrowEdit", "plugins");
+ if (!Directory.Exists (PluginsDirecory))
+ return;
foreach (string pluginDir in Directory.GetDirectories (PluginsDirecory)) {
Plugin plugin = new Plugin (pluginDir);
plugin.Load ();
}
}
+ public IEnumerable<AssemblyLoadContext> AllLoadContexts =>
+ System.Runtime.Loader.AssemblyLoadContext.All;
#region Editor item templates
<ItemTemplate>
<ListItem IsVisible='{IsSelected}' IsSelected='{²IsSelected}' Selected=""{/tb.HasFocus='true'}"">
<VerticalStack Spacing='0'>
- <HorizontalStack Spacing='0'>
+ <HorizontalStack Spacing='0' Background='White'>
<Editor Name='tb' Font='consolas, 12' Margin='5'
Document='{}' TextChanged='onTextChanged'/>
<ScrollBar Value='{²../tb.ScrollY}'
CurrentEditor?.RegisterForGraphicUpdate ();
}
}
+ public bool IndentWithSpace {
+ get => Configuration.Global.Get<bool> ("IndentWithSpace", false);
+ set {
+ if (IndentWithSpace == value)
+ return;
+ Configuration.Global.Set ("IndentWithSpace", value);
+ NotifyValueChanged ("IndentWithSpace", IndentWithSpace);
+ }
+ }
+ public int TabulationSize {
+ get => Configuration.Global.Get<int> ("TabulationSize", 4);
+ set {
+ if (TabulationSize == value)
+ return;
+ Configuration.Global.Set ("TabulationSize", value);
+ NotifyValueChanged ("TabulationSize", TabulationSize);
+ }
+ }
+
//Folding
public bool FoldingEnabled {
get => Crow.Configuration.Global.Get<bool> ("FoldingEnabled", true);
using CrowEditBase;
using System.Threading;
using System.ComponentModel;
+using static CrowEditBase.CrowEditBase;
namespace Crow
{
/// <summary>
/// Background color for selected text inside this label.
/// </summary>
- [DefaultValue ("SteelBlue")]
+ [DefaultValue ("LightSteelBlue")]
public virtual Color SelectionBackground {
get { return selBackground; }
set {
if (lines[i].Length == 0)
lines.UpdateLineLengthInPixel (i, 0);// (int)Math.Ceiling (fe.MaxXAdvance);
else {
- gr.TextExtents (_text.GetLine (lines[i]), Interface.TAB_SIZE, out tmp);
+ gr.TextExtents (_text.GetLine (lines[i]), App.TabulationSize, out tmp);
lines.UpdateLineLengthInPixel (i, (int)Math.Ceiling (tmp.XAdvance));
}
}
loc.Column = curLine.Length;
}
#endif
- loc.VisualCharXPosition = gr.TextExtents (curLine.Slice (0, loc.Column), Interface.TAB_SIZE).XAdvance + cPos;
+ loc.VisualCharXPosition = gr.TextExtents (curLine.Slice (0, loc.Column), App.TabulationSize).XAdvance + cPos;
location = loc;
} else {
TextExtents te;
protected override void onDraw (Context gr)
{
- base.onDraw (gr);
+ //base.onDraw (gr);
setFontForContext (gr);
else
update (new TextChange (selection.Start, 1, ""));
} else {
- if (IFace.Shift)
+ if (e.Modifiers == Modifier.Shift)
IFace.Clipboard = SelectedText;
update (new TextChange (selection.Start, selection.Length, ""));
}
RegisterForRedraw ();
break;
case Key.Tab:
- update (new TextChange (selection.Start, selection.Length, "\t"));
+ update (new TextChange (selection.Start, selection.Length, App.IndentWithSpace ? new string(' ', App.TabulationSize) : "\t"));
break;
case Key.PageUp:
checkShift (e);
#endregion
protected void update (TextChange change) {
+
lock (linesMutex) {
ReadOnlySpan<char> src = _text.AsSpan ();
Span<char> tmp = stackalloc char[src.Length + (change.ChangedText.Length - change.Length)];
--- /dev/null
+// Copyright (c) 2021-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace CrowEditBase
+{
+ public class ObservableTask<T> : Task<T> {
+ //;
+ public ObservableTask (Func<T> func, CancellationToken cancellationToken = new CancellationToken(), TaskCreationOptions options = TaskCreationOptions.None) :
+ base (func, cancellationToken, options) {
+
+ }
+
+
+ }
+}
+
{
public class SourceEditor : Editor {
object TokenMutex = new object();
+ SyntaxNode currentNode;
+#if DEBUG_NODE
+ SyntaxNode _hoverNode;
+ SyntaxNode hoverNode {
+ get =>_hoverNode;
+ set {
+ if (_hoverNode == value)
+ return;
+ _hoverNode = value;
+ RegisterForRedraw ();
+ }
+ }
+#endif
+ public SyntaxNode CurrentNode {
+ get => currentNode;
+ set {
+ if (currentNode == value)
+ return;
+ currentNode = value;
+ NotifyValueChanged ("CurrentNode", currentNode);
+ RegisterForRedraw ();
+ }
+ }
ListBox overlay;
IList suggestions;
base.OnTextChanged(sender, e);
+ if (Document is SourceDocument srcdoc)
+ srcdoc.updateCurrentTokAndNode (lines.GetAbsolutePosition(CurrentLoc.Value));
+
if (!disableSuggestions && HasFocus)
tryGetSuggestions ();
RegisterForGraphicUpdate();
+ lock (IFace.UpdateMutex) {
+ if (Document is SourceDocument doc) {
+ doc.NotifyValueChanged ("SyntaxRootChildNodes", (object)null);
+ doc.NotifyValueChanged ("SyntaxRootChildNodes", doc.SyntaxRootChildNodes);
+ CurrentNode?.ExpandToTheTop();
+ }
+ }
//Console.WriteLine ($"{pos}: {suggestionTok.AsString (_text)} {suggestionTok}");
}
protected void tryGetSuggestions () {
- if (currentLoc.HasValue && Document is SourceDocument srcDoc)
- Suggestions = srcDoc.GetSuggestions (lines.GetAbsolutePosition (CurrentLoc.Value));
- else
+ if (currentLoc.HasValue && Document is SourceDocument srcDoc) {
+ IList suggs = srcDoc.GetSuggestions (lines.GetAbsolutePosition (CurrentLoc.Value));
+ if (suggs != null && suggs.Count == 1 && (
+ (suggs[0] is System.Reflection.MemberInfo mi && mi.Name == srcDoc.CurrentTokenString) ||
+ (suggs[0].ToString() == srcDoc.CurrentTokenString)
+ )){
+ Suggestions = null;
+ }else
+ Suggestions = suggs;
+ } else
Suggestions = null;
}
void showOverlay () {
}
void completeToken () {
if (Document is SourceDocument srcDoc) {
- TextChange? change = srcDoc.GetCompletionForCurrentToken (overlay.SelectedItem, out TextSpan? nextSelection);
- if (change.HasValue)
- update (change.Value);
- if (nextSelection.HasValue)
- Selection = nextSelection.Value;
+ if (srcDoc.TryGetCompletionForCurrentToken (overlay.SelectedItem, out TextChange change, out TextSpan? nextSelection)) {
+ update (change);
+ if (nextSelection.HasValue) {
+ Selection = nextSelection.Value;
+ }
+ }
}
hideOverlay ();
+ tryGetSuggestions ();
}
const int leftMarginGap = 5;//gap between margin start and numbering
while (fold != null && fold.StartLine == currentLoc.Value.Line)
fold = fold.Parent;
fold?.UnfoldToTheTop();
+ if (Document is SourceDocument doc)
+ doc.updateCurrentTokAndNode (lines.GetAbsolutePosition(currentLoc.Value));
}
NotifyValueChanged ("CurrentLine", CurrentLine);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
setFontForContext (gr);
updateLocation (gr, ClientRectangle.Width, ref hoverLoc);
}
+#if DEBUG_NODES
+ if (Document is SourceDocument doc) {
+ hoverNode = doc.FindNodeIncludingPosition (lines.GetAbsolutePosition (hoverLoc.Value));
+ }
+#endif
}
public override void onKeyDown(object sender, KeyEventArgs e)
{
completeToken ();
return;
}
- } else if (e.Key == Key.Space && IFace.Ctrl) {
+ } else if (e.Key == Key.Space && e.Modifiers.HasFlag (Modifier.Control)) {
tryGetSuggestions ();
return;
}
disableSuggestions = true;
- if (IFace.Shift) {
+ if ( e.Modifiers == Modifier.Shift) {
for (int l = lineStart; l <= lineEnd; l++) {
if (_text[lines[l].Start] == '\t')
update (new TextChange (lines[l].Start, 1, ""));
else if (Char.IsWhiteSpace (_text[lines[l].Start])) {
int i = 1;
- while (i < lines[l].Length && i < Interface.TAB_SIZE && Char.IsWhiteSpace (_text[i]))
+ while (i < lines[l].Length && i < App.TabulationSize && Char.IsWhiteSpace (_text[i]))
i++;
update (new TextChange (lines[l].Start, i, ""));
}
return;
}
- if (e.Key == Key.F3 && Document is SourceDocument doc) {
- doc.SyntaxRootNode?.Dump();
+ if (Document is SourceDocument doc) {
+ switch (e.Key) {
+ case Key.F3:
+ doc.SyntaxRootNode?.Dump();
+ break;
+ case Key.Enter:
+ case Key.KeypadEnter:
+ //doc.updateCurrentTokAndNode (Selection.Start);
+ Console.WriteLine ($"*** Current Token: {doc.CurrentToken} Current Node: {doc.CurrentNode}");
+ if (string.IsNullOrEmpty (LineBreak))
+ detectLineBreak ();
+ update (new TextChange (selection.Start, selection.Length, LineBreak));
+ autoAdjustScroll = true;
+ IFace.forceTextCursor = true;
+ e.Handled = true;
+ return;
+ }
}
base.onKeyDown(sender, e);
SyntaxNode getFoldContainingLine (int line) {
if (!(Document is SourceDocument doc))
return null;
- IEnumerable<SyntaxNode> folds = doc.SyntaxRootNode.FoldableNodes;
- if (folds == null)
- return null;
- return folds.LastOrDefault (n => n.StartLine <= line && n.EndLine >= line);
+ doc.EnterReadLock();
+ try {
+ IEnumerable<SyntaxNode> folds = doc.SyntaxRootNode.FoldableNodes;
+ if (folds == null)
+ return null;
+ return folds.LastOrDefault (n => n.StartLine <= line && n.EndLine >= line);
+ } finally {
+ doc.ExitReadLock ();
+ }
}
int getVisualLine (int absoluteLine) {
if (!(Document is SourceDocument doc))
return absoluteLine;
- int foldedLines = 0;
- IEnumerator<SyntaxNode> foldsEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator();
- bool notEndOfFolds = foldsEnum.MoveNext();
- while (notEndOfFolds && foldsEnum.Current.StartLine < absoluteLine) {
- if (foldsEnum.Current.isFolded) {
- foldedLines += foldsEnum.Current.LineCount - 1;
- SyntaxNode nextNode = foldsEnum.Current.NextSiblingOrParentsNextSibling;
- if (nextNode == null)
- break;
- notEndOfFolds = foldsEnum.MoveNext();
- while (notEndOfFolds && foldsEnum.Current.StartLine < nextNode.StartLine)
+ doc.EnterReadLock();
+ try {
+ int foldedLines = 0;
+ IEnumerator<SyntaxNode> foldsEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator();
+ bool notEndOfFolds = foldsEnum.MoveNext();
+ while (notEndOfFolds && foldsEnum.Current.StartLine < absoluteLine) {
+ if (foldsEnum.Current.isFolded) {
+ foldedLines += foldsEnum.Current.LineCount - 1;
+ SyntaxNode nextNode = foldsEnum.Current.NextSiblingOrParentsNextSibling;
+ if (nextNode == null)
+ break;
notEndOfFolds = foldsEnum.MoveNext();
- } else
- notEndOfFolds = foldsEnum.MoveNext();
+ while (notEndOfFolds && foldsEnum.Current.StartLine < nextNode.StartLine)
+ notEndOfFolds = foldsEnum.MoveNext();
+ } else
+ notEndOfFolds = foldsEnum.MoveNext();
+ }
+ return absoluteLine - foldedLines;
+ } finally {
+ doc.ExitReadLock ();
}
- return absoluteLine - foldedLines;
}
int countFoldedLinesUntil (int visualLine) {
if (!(Document is SourceDocument doc))
return 0;
- int foldedLines = 0;
- IEnumerator<SyntaxNode> nodeEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator ();
- if (!nodeEnum.MoveNext())
- return 0;
-
- int l = 0;
- while (l < visualLine + foldedLines) {
- if (nodeEnum.Current.StartLine == l) {
- if (nodeEnum.Current.isFolded) {
- foldedLines += nodeEnum.Current.lineCount - 1;
- SyntaxNode nextNode = nodeEnum.Current.NextSiblingOrParentsNextSibling;
- if (nextNode == null || !nodeEnum.MoveNext())
- return foldedLines;
+ doc.EnterReadLock();
+ try {
+ int foldedLines = 0;
+ IEnumerator<SyntaxNode> nodeEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator ();
+ if (!nodeEnum.MoveNext())
+ return 0;
- while (nodeEnum.Current.StartLine < nextNode.StartLine) {
- if (!nodeEnum.MoveNext())
+ int l = 0;
+ while (l < visualLine + foldedLines) {
+ if (nodeEnum.Current.StartLine == l) {
+ if (nodeEnum.Current.isFolded) {
+ foldedLines += nodeEnum.Current.lineCount - 1;
+ SyntaxNode nextNode = nodeEnum.Current.NextSiblingOrParentsNextSibling;
+ if (nextNode == null || !nodeEnum.MoveNext())
return foldedLines;
- }
- } else if (!nodeEnum.MoveNext())
- return foldedLines;
+ while (nodeEnum.Current.StartLine < nextNode.StartLine) {
+ if (!nodeEnum.MoveNext())
+ return foldedLines;
+ }
+
+ } else if (!nodeEnum.MoveNext())
+ return foldedLines;
+ }
+ l ++;
}
- l ++;
+ //Console.WriteLine ($"visualLine: {visualLine} foldedLines: {foldedLines}");
+ return foldedLines;
+ } finally {
+ doc.ExitReadLock ();
}
- //Console.WriteLine ($"visualLine: {visualLine} foldedLines: {foldedLines}");
- return foldedLines;
}
protected override int getAbsoluteLineIndexFromVisualLineMove (int startLine, int visualLineDiff) {
}
+ protected virtual void fillHighlight (Context gr, int l, CharLocation selStart, CharLocation selEnd, RectangleD selRect, Color color) {
+ if (selStart.Line == selEnd.Line) {
+ selRect.X += selStart.VisualCharXPosition;
+ selRect.Width = selEnd.VisualCharXPosition - selStart.VisualCharXPosition;
+ } else if (l == selStart.Line) {
+ selRect.X += selStart.VisualCharXPosition;
+ selRect.Width -= selStart.VisualCharXPosition - 10.0;
+ } else if (l == selEnd.Line)
+ //selRect.Width = selEnd.VisualCharXPosition - selRect.X;// + cb.X;
+ selRect.Width = selEnd.VisualCharXPosition;
+ else
+ selRect.Width += 10.0;
+
+ gr.Operator = Operator.DestOver;
+
+ gr.SetSource (color);
+ gr.Rectangle (selRect);
+ gr.Fill ();
+ Foreground.SetAsSource (IFace, gr);
+
+ gr.Operator = Operator.Over;
+ }
protected override void drawContent (Context gr) {
if (!(Document is SourceDocument doc)) {
base.drawContent (gr);
CharLocation selStart = default, selEnd = default;
bool selectionNotEmpty = false;
+ CharLocation? nodeStart = null, nodeEnd = null;
+
+ CharLocation? editNodeStart = null, editNodeEnd = null;//debug
+ CharLocation? hoverNodeStart = null, hoverNodeEnd = null;
if (currentLoc?.Column < 0) {
updateLocation (gr, cb.Width, ref currentLoc);
} else
updateLocation (gr, cb.Width, ref currentLoc);
+ if (CurrentNode != null) {
+ TextSpan nodeSpan = CurrentNode.Span;
+ nodeStart = lines.GetLocation (nodeSpan.Start);
+ updateLocation (gr, cb.Width, ref nodeStart);
+ nodeEnd = lines.GetLocation (nodeSpan.End);
+ updateLocation (gr, cb.Width, ref nodeEnd);
+ }
+#if DEBUG_NODES
+ if (doc.EditedNode != null) {
+ TextSpan nodeSpan = doc.EditedNode.Span;
+ editNodeStart = lines.GetLocation (nodeSpan.Start);
+ updateLocation (gr, cb.Width, ref editNodeStart);
+ editNodeEnd = lines.GetLocation (nodeSpan.End);
+ updateLocation (gr, cb.Width, ref editNodeEnd);
+ }
+ if (hoverNode != null) {
+ TextSpan nodeSpan = hoverNode.Span;
+ hoverNodeStart = lines.GetLocation (nodeSpan.Start);
+ updateLocation (gr, cb.Width, ref hoverNodeStart);
+ hoverNodeEnd = lines.GetLocation (nodeSpan.End);
+ updateLocation (gr, cb.Width, ref hoverNodeEnd);
+ }
+#endif
+
if (overlay != null && overlay.IsVisible) {
Point p = new Point((int)currentLoc.Value.VisualCharXPosition - ScrollX, (int)(lineHeight * (currentLoc.Value.Line + 1) - ScrollY));
if (p.Y < 0 || p.X < 0)
}
RectangleD lineRect = new RectangleD (cb.X, pixY, pixX - cb.X, lineHeight);
- if (selectionNotEmpty) {
- RectangleD selRect = lineRect;
-
- if (l >= selStart.Line && l <= selEnd.Line) {
- if (selStart.Line == selEnd.Line) {
- selRect.X += selStart.VisualCharXPosition;
- selRect.Width = selEnd.VisualCharXPosition - selStart.VisualCharXPosition;
- } else if (l == selStart.Line) {
- selRect.X += selStart.VisualCharXPosition;
- selRect.Width -= selStart.VisualCharXPosition - 10.0;
- } else if (l == selEnd.Line)
- selRect.Width = selEnd.VisualCharXPosition - selRect.X + cb.X;
- else
- selRect.Width += 10.0;
-
- buff = sourceBytes.Slice(lines[l].Start, lines[l].Length);
- int size = buff.Length * 4 + 1;
- if (bytes.Length < size)
- bytes = size > 512 ? new byte[size] : stackalloc byte[size];
-
- int encodedBytes = Crow.Text.Encoding.ToUtf8 (buff, bytes);
-
- gr.SetSource (SelectionBackground);
- gr.Rectangle (selRect);
- if (encodedBytes < 0)
- gr.Fill ();
- else {
- gr.FillPreserve ();
- gr.Save ();
- gr.Clip ();
- gr.SetSource (SelectionForeground);
- gr.MoveTo (lineRect.X, lineRect.Y + fe.Ascent);
- gr.ShowText (bytes.Slice (0, encodedBytes));
- gr.Restore ();
- }
- Foreground.SetAsSource (IFace, gr);
- }
- }
+ if (CurrentNode != null && l >= nodeStart.Value.Line && l <= nodeEnd.Value.Line)
+ fillHighlight (gr, l, nodeStart.Value, nodeEnd.Value, lineRect, new Color(0.0,0.1,0.0,0.1));;
+#if DEBUG_NODES
+ if (doc.EditedNode != null && l >= editNodeStart.Value.Line && l <= editNodeEnd.Value.Line)
+ fillHighlight (gr, l, editNodeStart.Value, editNodeEnd.Value, lineRect, new Color(0,0.5,0,0.2));;
+ if (hoverNode != null && l >= hoverNodeStart.Value.Line && l <= hoverNodeEnd.Value.Line)
+ fillHighlight (gr, l, hoverNodeStart.Value, hoverNodeEnd.Value, lineRect, new Color(0,0,0.8,0.1));;
+#endif
+ if (selectionNotEmpty && l >= selStart.Line && l <= selEnd.Line)
+ fillHighlight (gr, l, selStart, selEnd, lineRect, SelectionBackground);
+
//Draw line numbering
if (printLineNumbers){
BubbleEvents ="None";
ClipToClientRect = "true";
MouseCursor = "ibeam";
+ CacheEnabled = "true";
}
icon {
Template = "#ui.spinner.template";
}
TreeIcon {
- Width="18";
- Height="18";
+ Width="16";
+ Height="16";
}
TreeIconSmall {
Width="12";
<?xml version="1.0"?>
-<Button Command="{}" Width="Stretched">
+<Button Command="{}" Width="Stretched" BubbleEvents="All">
<Template>
<HorizontalStack Background="{./Background}" Width="Stretched" Height="Stretched" Margin="3" Spacing="2"
MouseEnter="{Background=${ControlHighlight}}"
<?xml version="1.0"?>
<ItemTemplate DataType="Crow.Command" Path="#ui.MenuButton.template"/>
<ItemTemplate DataType="Crow.CommandGroup" Data="Commands">
- <Popper PopDirection="Right" Caption="{Caption}" Width="Stretched"
+ <Popper PopDirection="Right" Caption="{Caption}" Width="Stretched" IsPopped="{²./IsOpened}"
MouseEnter="{Background=${ControlHighlight}}"
MouseLeave="{Background=Transparent}">
<Template>
<Label Text="{./Caption}" Height="Stretched"/>
<Label Text="..." Width="Fit"/>
</HorizontalStack>
- </Template>
+ </Template>
<VerticalStack Margin="0" Name="ItemsContainer" Fit="true" Background="${MenuBackground}"/>
</Popper>
</ItemTemplate>
<?xml version="1.0"?>
<Popper PopDirection="{./PopDirection}" Caption="{Caption}" IsEnabled="{CanExecute}" Width="Stretched"
- MouseEnter="{Background=${ControlHighlight}}"
+ MouseEnter="{Background=${ControlHighlight}}" IsPopped="{²./IsOpened}"
MouseLeave="{Background=Transparent}">
<Template>
<HorizontalStack Background="{./Background}" Width="Stretched" Height="Stretched" Margin="3">
<Label Text="{./Caption}" Width="Fit" Height="Stretched"/>
<Label Text="..."/>
</HorizontalStack>
- </Template>
+ </Template>
<VerticalStack Margin="0" Name="ItemsContainer" Fit="true" Background="${MenuBackground}"/>
</Popper>
\ No newline at end of file
<HorizontalStack Height="Fit">
<Shape Foreground="DimGrey" Background="Transparent"
Path="M 5.5,0 L 5.5,11 G" Size="11,11" Width="11" Height="Stretched" KeepProportions="false" Margin="0"/>
- <VerticalStack Height="Fit" Name="ItemsContainer"/>
+ <VerticalStack Height="Fit" Name="ItemsContainer" Spacing="0"/>
</HorizontalStack>
<Template>
<VerticalStack>
Unselected="{/border.Background=${TreeItemBackground}}"
MouseEnter="{/border.Foreground=${TreeItemBorderHighlightFG}}"
MouseLeave="{/border.Foreground=${TreeItemBorderFG}}">
- <Border Name="border" Margin="2" CornerRadius="${TreeItemBorderCornerRadius}"
+ <Border Name="border" Margin="1" CornerRadius="${TreeItemBorderCornerRadius}"
Foreground="${TreeItemBorderFG}">
<HorizontalStack Spacing="5">
<Image Margin="1" Width="9" Height="9" Focusable="true" MouseClick="./onClickForExpand"
<?xml version="1.0"?>
<ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}" Selected="{/tb.HasFocus='true'}">
<VerticalStack Spacing="0">
- <HorizontalStack Spacing="0">
- <SourceEditor Name="tb" Font="consolas, 12" Margin='0'
+ <HorizontalStack Spacing="0" Background="White">
+ <SourceEditor Name="tb" Font="consolas, 12" Margin='0' CurrentNode="{CurrentNode}"
Document="{}" TextChanged="onTextChanged" />
<ScrollBar Value="{²../tb.ScrollY}"
LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" />
<HorizontalStack Height="Fit" Spacing='3'>
<Widget Width="Stretched"/>
- <Label Text="MouseY:" Foreground="Grey"/>
+ <Label Text="Tok" Foreground="Grey"/>
+ <Label Text="{CurrentTokenString}" Margin="3"/>
+ <Label Text="Node" Foreground="Grey"/>
+ <Label Text="{CurrentNode}" Margin="3"/>
+ <!--<Label Text="MouseY:" Foreground="Grey"/>
<Label Text="{../../tb.MouseY}" Margin="3"/>
<Label Text="VisibleLines:" Foreground="Grey"/>
<Label Text="{../../tb.VisibleLines}" Margin="3"/>
<Label Text="{../../tb.ScrollY}" Margin="3"/>
<Label Text="ScrollLine:" Foreground="Grey"/>
<Label Text="{../../tb.ScrollLine}" Margin="3"/>
- <Label Text="HoverLine:" Foreground="Grey"/>
+ <Label Text="HoverLine:" Foreground="Grey"/>-->
<Label Text="{../../tb.HoverLine}" Margin="3"/>
<Label Text="Line:" Foreground="Grey"/>
<Label Text="{../../tb.CurrentLine}" Margin="3"/>
return null;
}
#endregion
+ static string defaultCrowAssemblyLocation =>
+ System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Assembly.GetEntryAssembly().Location), "Crow.dll");
public override void Start()
{
if (CurrentState == Status.Running)
return;
-
if (!File.Exists (CrowDbgAssemblyLocation)) {
DebugLogIsEnabled = false;
updateCrowDebuggerState($"Crow.dll for debugging file not found");
NotifyValueChanged (activeSolution);
}
}
+
public string CrowDbgAssemblyLocation {
- get => Configuration.Global.Get<string> ("CrowDbgAssemblyLocation");
+ get => Configuration.Global.Get<string> ("CrowDbgAssemblyLocation", defaultCrowAssemblyLocation);
set {
if (CrowDbgAssemblyLocation == value)
return;
using CrowEdit.Xml;
using CERoslynPlugin;
+using AttributeSyntax = CrowEdit.Xml.AttributeSyntax;
+
namespace CECrowPlugin
{
public class ImlDocument : XmlDocument {
return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
}
public override IList GetSuggestions (int pos) {
- base.GetSuggestions (pos);
+ if (tokens.Length == 0)
+ return null;
+ IList sugs = base.GetSuggestions (pos);
+ if (sugs != null)
+ return sugs;
+
#if DEBUG
- Console.WriteLine ($"Current Token: {currentToken} Current Node: {currentNode}");
+ Console.WriteLine ($"Current Token: {CurrentTokenString} Current Node: {CurrentNode}");
#endif
- /*if (currentToken.GetTokenType() == XmlTokenType.ElementOpen)
+ if (currentToken.GetTokenType() == XmlTokenType.ElementOpen)
return new List<string> (allWidgetNames);
if (currentToken.GetTokenType() == XmlTokenType.ElementName)
return allWidgetNames.Where (s => s.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
- if (currentNode is AttributeSyntax attribNode) {
- if (currentNode.Parent is ElementTagSyntax eltTag) {
- if (eltTag.NameToken.HasValue) {
+ if (currentToken.GetTokenType() == XmlTokenType.WhiteSpace && CurrentNode is ElementStartTagSyntax eltStartTag2)
+ return getAllCrowTypeMembers (eltStartTag2.Name).ToList();
+ if (CurrentNode is CrowEdit.Xml.AttributeSyntax attribNode) {
+ if (CurrentNode.Parent is ElementTagSyntax eltTag) {
+ if (!string.IsNullOrEmpty (eltTag.Name)) {
if (currentToken.GetTokenType() == XmlTokenType.AttributeName) {
- return getAllCrowTypeMembers (eltTag.NameToken.Value.AsString (Source))
+ return getAllCrowTypeMembers (eltTag.Name)
.Where (s => s.Name.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
- } else if (attribNode.NameToken.HasValue) {
+ } else if (!string.IsNullOrEmpty (attribNode.Name)) {
if (currentToken.GetTokenType() == XmlTokenType.AttributeValue) {
MemberInfo mi = getCrowTypeMember (
- eltTag.NameToken.Value.AsString (Source), attribNode.NameToken.Value.AsString (Source));
+ eltTag.Name, attribNode.Name);
if (mi is PropertyInfo pi) {
if (pi.Name == "Style")
return App.Styling.Keys
}
} else if (currentToken.GetTokenType() == XmlTokenType.AttributeValueOpen) {
MemberInfo mi = getCrowTypeMember (
- eltTag.NameToken.Value.AsString (Source), attribNode.NameToken.Value.AsString (Source));
+ eltTag.Name, attribNode.Name);
if (mi is PropertyInfo pi) {
if (pi.Name == "Style")
return App.Styling.Keys.ToList ();
} else if (currentToken.GetTokenType() != XmlTokenType.AttributeValueClose &&
currentToken.GetTokenType() != XmlTokenType.EmptyElementClosing &&
currentToken.GetTokenType() != XmlTokenType.ClosingSign &&
- currentNode is ElementStartTagSyntax eltStartTag) {
+ CurrentNode is ElementStartTagSyntax eltStartTag) {
if (currentToken.GetTokenType() == XmlTokenType.AttributeName)
- return getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source))
+ return getAllCrowTypeMembers (eltStartTag.Name)
.Where (s => s.Name.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
//else if (currentToken.Type == TokenType.ElementName)
// Suggestions = getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source)).ToList ();
} else {
- }*/
+ }
return null;
}
- public override TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection) {
- newSelection = null;
-
- string selectedSugg = suggestion is MemberInfo mi ?
- mi.Name : suggestion?.ToString ();
- if (selectedSugg == null)
- return null;
-
- if (currentToken.GetTokenType() == XmlTokenType.ElementOpen ||
- currentToken.GetTokenType() == XmlTokenType.WhiteSpace ||
- currentToken.GetTokenType() == XmlTokenType.AttributeValueOpen)
- return new TextChange (currentToken.End, 0, selectedSugg);
-
- if (currentToken.GetTokenType() == XmlTokenType.AttributeName && currentNode is AttributeSyntax attrib) {
- if (attrib.ValueToken.HasValue) {
- TextChange tc = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
- newSelection = new TextSpan(
- attrib.ValueToken.Value.Start + tc.CharDiff + 1,
- attrib.ValueToken.Value.End + tc.CharDiff - 1
- );
- return tc;
- } else {
- newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
- return new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"");
- }
- }
-
- return new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
+ return base.TryGetCompletionForCurrentToken (suggestion is MemberInfo mi ? mi.Name : suggestion, out change, out newSelection);
}
public override Color GetColorForToken(TokenType tokType)
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace CECrowPlugin
+{
+ [Flags]
+ public enum ImlTokenType {
+ Unknown,
+ Trivia = 0x0100,
+ WhiteSpace = 0x4100,
+ Tabulation = 0x4101,
+ LineBreak = 0x4102,
+ LineComment = 0x0103,
+ BlockCommentStart = 0x0104,
+ BlockComment = 0x0105,
+ BlockCommentEnd = 0x0106,
+ Name = 0x0200,
+ ElementName = 0x0201,
+ AttributeName = 0x0202,
+ PI_Target = 0x0203,
+ Punctuation = 0x0400,
+ PI_Start = 0x0401,// '<?'
+ PI_End = 0x0402,// '?>'
+ ElementOpen = 0x0403,// '<'
+ EndElementOpen = 0x0404,// '</'
+ EmptyElementClosing = 0x0405,// '/>'
+ ClosingSign = 0x0406,// '>'
+ DTDObjectOpen = 0x04A0,// '<!'
+ Operator = 0x0800,
+ EqualSign = 0x0801,
+ Keyword = 0x1000,
+ AttributeValue = 0x2000,
+ AttributeValueOpen = 0x2001,
+ AttributeValueClose = 0x2002,
+ Content,
+ BindingOpen = 0xA401,// '{'
+ BindingClose = 0xA402,// '}'
+ ConstantRefOpen = 0x2403,// '${'
+ BindingLevel = 0xA404,// '/'
+ BindingDot = 0xA405,// '.'
+ BindingDoubleDot = 0xA406,// '..'
+ BindingName = 0xA203,// 'Identifier in binding expression'
+ BindingExpression = 0xA001,// 'unparsed binding expression
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using Crow.Text;
+using System.Collections.Generic;
+using CrowEditBase;
+using CrowEdit.Xml;
+
+namespace CECrowPlugin
+{
+ public class ImlTokenizer : XmlTokenizer {
+ enum status {
+ init,
+ attribute,
+ bindingTarget,
+ bindingSource,
+
+ };
+ /*protected override void parseAttributeValue (ref SpanCharReader reader) {
+ char q = reader.Read();
+ addTok (ref reader, XmlTokenType.AttributeValueOpen);
+ status curState = status.init;
+
+ while (!reader.EndOfSpan) {
+ if (reader.TryPeak ('{')) {
+ curState = status.bindingSource;
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.BindingOpen);
+ continue;
+ }
+ if (reader.TryPeak ('}')) {
+ addTok (ref reader, ImlTokenType.BindingExpression);
+ reader.Read();
+ addTok (ref reader, ImlTokenType.BindingClose);
+ continue;
+ }
+ if (reader.Eol()) {
+ addTok (ref reader, XmlTokenType.AttributeValue);
+ reader.ReadEol();
+ addTok (ref reader, XmlTokenType.LineBreak);
+ continue;
+ }
+ if (reader.TryPeak (q)) {
+ addTok (ref reader, XmlTokenType.AttributeValue);
+ reader.Advance ();
+ addTok (ref reader, XmlTokenType.AttributeValueClose);
+ return;
+ } else
+ reader.Read ();
+ }
+ }*/
+
+ }
+}
+++ /dev/null
-// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using Crow.Text;
-using System.Collections.Generic;
-using CrowEditBase;
-using CrowEdit.Xml;
-
-namespace CECrowPlugin
-{
- public class ImlTokenizer : XmlTokenizer {
- protected override void parseAttributeValue (ref SpanCharReader reader) {
- char q = reader.Read();
- addTok (ref reader, XmlTokenType.AttributeValueOpen);
- while (!reader.EndOfSpan) {
- if (reader.Eol()) {
- addTok (ref reader, XmlTokenType.AttributeValue);
- reader.ReadEol();
- addTok (ref reader, XmlTokenType.LineBreak);
- continue;
- }
- if (reader.TryPeak (q)) {
- addTok (ref reader, XmlTokenType.AttributeValue);
- reader.Advance (1);
- addTok (ref reader, XmlTokenType.AttributeValueClose);
- return;
- } else
- reader.Read ();
- }
- }
- }
-}
+++ /dev/null
-// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace CECrowPlugin
-{
- [Flags]
- public enum StyleTokenType {
- Unknown,
- Trivia = 0x0100,
- WhiteSpace = 0x4100,
- Tabulation = 0x4101,
- LineBreak = 0x4102,
- LineCommentStart = 0x0102,
- LineComment = 0x0103,
- BlockCommentStart = 0x0104,
- BlockComment = 0x0105,
- BlockCommentEnd = 0x0106,
- Name = 0x0200,
- StyleKey = 0x0201,//may be a class name or a style name.
- MemberName = 0x0202,
- ConstantName = 0x0203,
- Punctuation = 0x0400,
- OpeningBrace = 0x0401,// '{'
- ClosingBrace = 0x0402,// '}'
- Comma = 0x0403,// ','
- EndOfExpression = 0x0404,// ';'
- EqualSign = 0x0801,
- MemberValuePart = 0x2000,
- MemberValueOpen = 0x2401,
- MemberValueClose = 0x2402,
- ConstantRefOpen = 0x2403,// '${'
- }
-}
\ No newline at end of file
+++ /dev/null
-// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using Crow.Text;
-using System.Collections.Generic;
-using CrowEditBase;
-using System.Globalization;
-using Crow.Coding;
-
-namespace CECrowPlugin {
- public class StyleTokenizer : Tokenizer {
- enum States {
- classNames, members, value, endOfStatement
- }
-
- States curState;
-
- public StyleTokenizer () {}
-
- bool readName (ref SpanCharReader reader) {
- if (reader.EndOfSpan)
- return false;
- char c = reader.Peak;
- if (char.IsLetter(c) || c == '_' ) {
- reader.Advance ();
- while (reader.TryPeak (ref c)) {
- if (!char.IsLetterOrDigit(c)) {
- UnicodeCategory uc = Char.GetUnicodeCategory (c);
- if (uc != UnicodeCategory.NonSpacingMark &&
- uc != UnicodeCategory.SpacingCombiningMark &&
- uc != UnicodeCategory.ConnectorPunctuation &&
- uc != UnicodeCategory.Format)
- return true;
- }
- reader.Advance ();
- }
- return true;
- }
- return false;
- }
-
- public override Token[] Tokenize (string source) {
- SpanCharReader reader = initParsing (source);
-
- curState = States.classNames;
-
- while(!reader.EndOfSpan) {
-
- skipWhiteSpaces (ref reader);
-
- if (reader.EndOfSpan)
- break;
-
- switch (reader.Peak) {
- case '/':
- reader.Advance ();
- if (reader.TryPeak ('/')) {
- reader.Advance ();
- addTok (ref reader, StyleTokenType.LineCommentStart);
- reader.AdvanceUntilEol ();
- addTok (ref reader, StyleTokenType.LineComment);
- } else if (reader.TryPeak ('*')) {
- reader.Advance ();
- addTok (ref reader, StyleTokenType.BlockCommentStart);
- if (reader.TryReadUntil ("*/")) {
- addTok (ref reader, StyleTokenType.BlockComment);
- reader.Advance (2);
- addTok (ref reader, StyleTokenType.BlockCommentEnd);
- }
- }
- break;
- case ',':
- reader.Advance ();
- addTok (ref reader, StyleTokenType.Comma);
- curState = States.classNames;
- break;
- case '{':
- reader.Advance ();
- addTok (ref reader, StyleTokenType.OpeningBrace);
- curState = States.members;
- break;
- case '}':
- reader.Advance ();
- addTok (ref reader, StyleTokenType.ClosingBrace);
- curState = States.classNames;
- break;
- case '=':
- reader.Advance ();
- addTok (ref reader, StyleTokenType.EqualSign);
- curState = States.value;
- break;
- case '"':
- reader.Advance ();
- addTok (ref reader, StyleTokenType.MemberValueOpen);
-
- while (!reader.EndOfSpan) {
- if (reader.TryPeak ("${")) {
- addTok (ref reader, StyleTokenType.MemberValuePart);
- reader.Advance (2);
- addTok (ref reader, StyleTokenType.ConstantRefOpen);
-
- while (!reader.EndOfSpan) {
- if (reader.TryPeak ('}')) {
- addTok (ref reader, StyleTokenType.ConstantName);
- reader.Read ();
- addTok (ref reader, StyleTokenType.ClosingBrace);
- break;
- }
- reader.Advance ();
- }
- continue;
- } else if (reader.TryPeak ('\"')) {
- addTok (ref reader, StyleTokenType.MemberValuePart);
- reader.Advance ();
- addTok (ref reader, StyleTokenType.MemberValueClose);
- break;
- }
- reader.Advance ();
- }
- curState = States.endOfStatement;
- break;
- case ';':
- reader.Advance();
- addTok (ref reader, StyleTokenType.EndOfExpression);
- curState = States.members;
- break;
- default:
- if (readName (ref reader)) {
- addTok (ref reader, StyleTokenType.Name);
- break;
- }
- reader.Advance ();
- addTok (ref reader, StyleTokenType.Unknown);
- break;
- }
-
- }
-
- return Toks.ToArray();
- }
- }
-}
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace CECrowPlugin
+{
+ [Flags]
+ public enum StyleTokenType {
+ Unknown,
+ Trivia = 0x0100,
+ WhiteSpace = 0x4100,
+ Tabulation = 0x4101,
+ LineBreak = 0x4102,
+ LineCommentStart = 0x0102,
+ LineComment = 0x0103,
+ BlockCommentStart = 0x0104,
+ BlockComment = 0x0105,
+ BlockCommentEnd = 0x0106,
+ Name = 0x0200,
+ StyleKey = 0x0201,//may be a class name or a style name.
+ MemberName = 0x0202,
+ ConstantName = 0x0203,
+ Punctuation = 0x0400,
+ OpeningBrace = 0x0401,// '{'
+ ClosingBrace = 0x0402,// '}'
+ Comma = 0x0403,// ','
+ EndOfExpression = 0x0404,// ';'
+ EqualSign = 0x0801,
+ MemberValuePart = 0x2000,
+ MemberValueOpen = 0x2401,
+ MemberValueClose = 0x2402,
+ ConstantRefOpen = 0x2403,// '${'
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using Crow.Text;
+using System.Collections.Generic;
+using CrowEditBase;
+using System.Globalization;
+using Crow.Coding;
+
+namespace CECrowPlugin {
+ public class StyleTokenizer : Tokenizer {
+ enum States {
+ classNames, members, value, endOfStatement
+ }
+
+ States curState;
+
+ public StyleTokenizer () {}
+
+ bool readName (ref SpanCharReader reader) {
+ if (reader.EndOfSpan)
+ return false;
+ char c = reader.Peak;
+ if (char.IsLetter(c) || c == '_' ) {
+ reader.Advance ();
+ while (reader.TryPeak (ref c)) {
+ if (!char.IsLetterOrDigit(c)) {
+ UnicodeCategory uc = Char.GetUnicodeCategory (c);
+ if (uc != UnicodeCategory.NonSpacingMark &&
+ uc != UnicodeCategory.SpacingCombiningMark &&
+ uc != UnicodeCategory.ConnectorPunctuation &&
+ uc != UnicodeCategory.Format)
+ return true;
+ }
+ reader.Advance ();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public override Token[] Tokenize (string source) {
+ SpanCharReader reader = initParsing (source);
+
+ curState = States.classNames;
+
+ while(!reader.EndOfSpan) {
+
+ skipWhiteSpaces (ref reader);
+
+ if (reader.EndOfSpan)
+ break;
+
+ switch (reader.Peak) {
+ case '/':
+ reader.Advance ();
+ if (reader.TryPeak ('/')) {
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.LineCommentStart);
+ reader.AdvanceUntilEol ();
+ addTok (ref reader, StyleTokenType.LineComment);
+ } else if (reader.TryPeak ('*')) {
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.BlockCommentStart);
+ if (reader.TryReadUntil ("*/")) {
+ addTok (ref reader, StyleTokenType.BlockComment);
+ reader.Advance (2);
+ addTok (ref reader, StyleTokenType.BlockCommentEnd);
+ }
+ }
+ break;
+ case ',':
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.Comma);
+ curState = States.classNames;
+ break;
+ case '{':
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.OpeningBrace);
+ curState = States.members;
+ break;
+ case '}':
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.ClosingBrace);
+ curState = States.classNames;
+ break;
+ case '=':
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.EqualSign);
+ curState = States.value;
+ break;
+ case '"':
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.MemberValueOpen);
+
+ while (!reader.EndOfSpan) {
+ if (reader.TryPeak ("${")) {
+ addTok (ref reader, StyleTokenType.MemberValuePart);
+ reader.Advance (2);
+ addTok (ref reader, StyleTokenType.ConstantRefOpen);
+
+ while (!reader.EndOfSpan) {
+ if (reader.TryPeak ('}')) {
+ addTok (ref reader, StyleTokenType.ConstantName);
+ reader.Read ();
+ addTok (ref reader, StyleTokenType.ClosingBrace);
+ break;
+ }
+ reader.Advance ();
+ }
+ continue;
+ } else if (reader.TryPeak ('\"')) {
+ addTok (ref reader, StyleTokenType.MemberValuePart);
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.MemberValueClose);
+ break;
+ }
+ reader.Advance ();
+ }
+ curState = States.endOfStatement;
+ break;
+ case ';':
+ reader.Advance();
+ addTok (ref reader, StyleTokenType.EndOfExpression);
+ curState = States.members;
+ break;
+ default:
+ if (readName (ref reader)) {
+ addTok (ref reader, StyleTokenType.Name);
+ break;
+ }
+ reader.Advance ();
+ addTok (ref reader, StyleTokenType.Unknown);
+ break;
+ }
+
+ }
+
+ return Toks.ToArray();
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2021-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CrowEditBase;
+
+namespace CECrowPlugin
+{
+ public class StyleSyntaxAnalyser : SyntaxAnalyser {
+ public override SyntaxNode Root => CurrentNode;
+ public StyleSyntaxAnalyser (StyleDocument source) : base (source) {
+ this.source = source;
+ }
+
+ SyntaxNode CurrentNode;
+ Token previousTok;
+ IEnumerator<Token> iter;
+ int currentLine;
+ public override void Process () {
+ StyleDocument doc = source as StyleDocument;
+ Exceptions = new List<SyntaxException> ();
+ CurrentNode = new StyleRootSyntax (doc);
+ previousTok = default;
+ iter = doc.Tokens.AsEnumerable().GetEnumerator ();
+ currentLine = 0;
+
+ bool notEndOfSource = iter.MoveNext ();
+ while (notEndOfSource) {
+ if (iter.Current.Type == TokenType.LineBreak)
+ currentLine++;
+ else if (!iter.Current.Type.HasFlag (TokenType.Trivia)) {
+ }
+
+ previousTok = iter.Current;
+ notEndOfSource = iter.MoveNext ();
+ }
+ while (currentNode.Parent != null) {
+ if (!currentNode.LastTokenOffset.HasValue)
+ storeCurrentNode (-1);
+ else
+ currentNode = currentNode.Parent;
+ }
+ setCurrentNodeEndLine (currentLine);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using CrowEditBase;
+
+namespace CECrowPlugin
+{
+
+ public class StyleRootSyntax : SyntaxRootNode {
+ public StyleRootSyntax (StyleDocument source)
+ : base (source) {
+ }
+ }
+
+ public class AttributeSyntax : SyntaxNode {
+ public Token? NameToken { get; internal set; }
+ public Token? EqualToken { get; internal set; }
+ public Token? ValueOpenToken { get; internal set; }
+ public Token? ValueCloseToken { get; internal set; }
+ public Token? ValueToken { get; internal set; }
+ public AttributeSyntax (int startLine, int startTok) : base (startLine, startTok) {}
+ public override bool IsComplete => base.IsComplete & NameToken.HasValue & EqualToken.HasValue &
+ ValueToken.HasValue & ValueOpenToken.HasValue & ValueCloseToken.HasValue;
+ }
+}
\ No newline at end of file
+++ /dev/null
-// Copyright (c) 2021-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using CrowEditBase;
-
-namespace CECrowPlugin
-{
- public class StyleSyntaxAnalyser : SyntaxAnalyser {
- public override SyntaxNode Root => CurrentNode;
- public StyleSyntaxAnalyser (StyleDocument source) : base (source) {
- this.source = source;
- }
-
- SyntaxNode CurrentNode;
- Token previousTok;
- IEnumerator<Token> iter;
- int currentLine;
- public override void Process () {
- StyleDocument doc = source as StyleDocument;
- Exceptions = new List<SyntaxException> ();
- CurrentNode = new StyleRootSyntax (doc);
- previousTok = default;
- iter = doc.Tokens.AsEnumerable().GetEnumerator ();
- currentLine = 0;
-
- bool notEndOfSource = iter.MoveNext ();
- while (notEndOfSource) {
- if (iter.Current.Type == TokenType.LineBreak)
- currentLine++;
- else if (!iter.Current.Type.HasFlag (TokenType.Trivia)) {
- }
-
- previousTok = iter.Current;
- notEndOfSource = iter.MoveNext ();
- }
- while (currentNode.Parent != null) {
- if (!currentNode.LastTokenOffset.HasValue)
- storeCurrentNode (-1);
- else
- currentNode = currentNode.Parent;
- }
- setCurrentNodeEndLine (currentLine);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using CrowEditBase;
-
-namespace CECrowPlugin
-{
-
- public class StyleRootSyntax : SyntaxRootNode {
- public StyleRootSyntax (StyleDocument source)
- : base (source) {
- }
- }
-
- public class AttributeSyntax : SyntaxNode {
- public Token? NameToken { get; internal set; }
- public Token? EqualToken { get; internal set; }
- public Token? ValueOpenToken { get; internal set; }
- public Token? ValueCloseToken { get; internal set; }
- public Token? ValueToken { get; internal set; }
- public AttributeSyntax (int startLine, int startTok) : base (startLine, startTok) {}
- public override bool IsComplete => base.IsComplete & NameToken.HasValue & EqualToken.HasValue &
- ValueToken.HasValue & ValueOpenToken.HasValue & ValueCloseToken.HasValue;
- }
-}
\ No newline at end of file
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new StyleSyntaxAnalyser (this);
public override IList GetSuggestions (int pos) {
- currentToken = FindTokenIncludingPosition (pos);
- currentNode = FindNodeIncludingPosition (pos);
+ /*currentToken = FindTokenIncludingPosition (pos);
+ currentNode = FindNodeIncludingPosition (pos);*/
return null;
}
- public override TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection) {
+ public override bool TryGetCompletionForCurrentToken(object suggestion, out TextChange change, out TextSpan? newSelection)
+ {
+ change = default;
newSelection = null;
- return null;
+ return false;
}
public override Color GetColorForToken(TokenType tokType)
{
<?xml version="1.0"?>
-<DockWindow Caption="Crow Preview Configuration" Width="80%" Height="400" Resizable="false">
+<DockWindow Caption="Crow Preview Configuration" Width="60%" Height="400">
<VerticalStack RootDataLevel="true" Margin="5">
<HorizontalStack Height="Fit" Margin="5">
<Label Text="Crow Service" Width="Stretched"/>
</HorizontalStack>
<HorizontalStack Height="Fit">
<Label Fit="true" Text="Crow assembly path:"/>
- <Image Width="30" Height="20" Path="#Crow.Icons.IconAlerte.svg" Visible="{ServiceIsInError}"/>
- </HorizontalStack>
- <HorizontalStack Height="Fit">
<TextBox Height="Fit" Text="{²CrowDbgAssemblyLocation}" Margin="2"/>
+ <Image Width="30" Height="20" Path="#Crow.Icons.IconAlerte.svg" Visible="{ServiceIsInError}"/>
<Button Command="{CMDOptions_SelectCrowAssemblyLocation}" MinimumSize="0,0"/>
</HorizontalStack>
<Label Background="Red" Foreground="White" Margin="5" Width="Stretched" Text="{ServiceErrorMessage}"
<ListBox Style="ScrollingListBox" Data="{CrowAssemblies}"/>
<HorizontalStack Height="Fit" Width="Fit" HorizontalAlignment="Right">
<Button Command="{CMDOptions_AddCrowAssembly}" Fit="true"/>
-
</HorizontalStack>
<Spinner Caption="Zoom Factor" Value="{²ZoomFactor}" Minimum="0.2" Maximum="4.0" SmallIncrement="0.1" LargeIncrement="0.2"/>
<Spinner Caption="Refresh Rate (ms)" Value="{²RefreshRate}" Maximum="1000"/>
public IEnumerable<string> Configurations => solutionFile.SolutionConfigurations.Select (sc => sc.ConfigurationName).Distinct ().ToList ();
public IEnumerable<string> Platforms => solutionFile.SolutionConfigurations.Select (sc => sc.PlatformName).Distinct ().ToList ();
public string ActiveConfiguration {
- get => projectCollection.GetGlobalProperty ("Configuration")?.ToString();
- /*set {
+ get => UserConfig.Get<string> ("ActiveConfiguration");
+ set {
if (ActiveConfiguration == value)
return;
- projectCollection.SetGlobalProperty ("Configuration", value);
+ UserConfig.Set ("ActiveConfiguration", value);
NotifyValueChanged (value);
- }*/
+ }
}
public string ActivePlatform {
- get => projectCollection.GetGlobalProperty ("Platform")?.ToString();
- /*set {
- if (ActivePlatform == value)
+ get => UserConfig.Get<string> ("ActivePlatform");
+ set {
+ if (ActiveConfiguration == value)
return;
- projectCollection.SetGlobalProperty ("Platform", value);
+ UserConfig.Set ("ActivePlatform", value);
NotifyValueChanged (value);
- }*/
+ }
}
public override bool ContainsFile (string fullPath) =>
FlattenProjetcs.Any (f => f.ContainsFile (fullPath));
}
public override void Load () {
- Dictionary<string,string> globalProperties = new Dictionary<string, string>();
- globalProperties.Add ("Configuration", "Debug");
+ //Dictionary<string,string> globalProperties = new Dictionary<string, string>();
+ //globalProperties.Add ("Configuration", "Debug");
projectCollection = new ProjectCollection (
- globalProperties,
+ null,//globalProperties,
new ILogger [] { roslynService.Logger },
ToolsetDefinitionLocations.Default
);
solutionFile = SolutionFile.Parse (FullPath);
UserConfig = new Configuration (FullPath + ".user");
+
//IDE.ProgressNotify (10);
//projectCollection has to be recreated to change global properties
- //ActiveConfiguration = solutionFile.GetDefaultConfigurationName ();
- //ActivePlatform = solutionFile.GetDefaultPlatformName ();
+ if (string.IsNullOrEmpty (ActiveConfiguration))
+ ActiveConfiguration = solutionFile.GetDefaultConfigurationName ();
+ if (string.IsNullOrEmpty (ActivePlatform))
+ ActivePlatform = solutionFile.GetDefaultPlatformName ();
projectCollection.SetGlobalProperty ("RestoreConfigFile", Path.Combine (
Path.Combine (
Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".nuget"), "NuGet"),
"NuGet.Config"));
- projectCollection.SetGlobalProperty ("SolutionDir", Path.GetDirectoryName (FullPath) + Path.DirectorySeparatorChar);
projectCollection.SetGlobalProperty ("DefaultItemExcludes", "obj/**/*;bin/**/*");
projectCollection.SetGlobalProperty ("TargetFramework", "netcoreapp3.1");
+ projectCollection.SetGlobalProperty ("SolutionDir", Path.GetDirectoryName (FullPath) + Path.DirectorySeparatorChar);
+ //projectCollection.SetGlobalProperty ("Configuration", "Debug");
+
//IDE.ProgressNotify (10);
//ide.projectCollection.HostServices
}
IsLoaded = true;
-
- if (StartupProject is MSBuildProject msbProj)
- msbProj?.DesignBuild();
+ //Console.WriteLine (projectCollection.Get ("Configuration"));
+ /*if (StartupProject is MSBuildProject msbProj)
+ msbProj?.DesignBuild();*/
}
void build (params string[] targets) {
this.source = source;
}
- Token previousTok;
- Token curTok => source.Tokens[tokIdx];
+ /*public virtual SyntaxNode Process (SyntaxNode startingNode) {
+
+ }*/
public override void Process () {
XmlDocument xmlDoc = source as XmlDocument;
Exceptions = new List<SyntaxException> ();
currentNode = new IMLRootSyntax (xmlDoc);
- previousTok = default;
currentLine = 0;
- Token[] toks = source.Tokens;
+ Span<Token> toks = source.Tokens;
tokIdx = 0;
while (tokIdx < toks.Length) {
+ Token curTok = toks[tokIdx];
if (curTok.Type == TokenType.LineBreak)
currentLine++;
else if (!curTok.Type.HasFlag (TokenType.Trivia)) {
if (currentNode is ElementStartTagSyntax tag) {
if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
- attribute.name = tokIdx;
+ attribute.name = 0;
currentNode = currentNode.AddChild (attribute);
} else if (curTok.GetTokenType() == XmlTokenType.ElementName)
- tag.name = tokIdx;
+ tag.name = tokIdx - tag.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
storeCurrentNode ();
currentNode.RemoveChild (tag);
public abstract class ElementTagSyntax : SyntaxNode {
internal int? name, close;
public override bool IsComplete => base.IsComplete & name.HasValue & close.HasValue;
+ public string Name => Root.GetTokenStringByIndex (TokenIndexBase + name.Value);
protected ElementTagSyntax (int startLine, int tokenBase)
: base (startLine, tokenBase) {
}
public class EmptyElementSyntax : SyntaxNode {
public readonly ElementStartTagSyntax StartTag;
- public EmptyElementSyntax (ElementStartTagSyntax startNode) : base (startNode.StartLine, startNode.TokenIndexBase, startNode.LastTokenOffset) {
+ public EmptyElementSyntax (ElementStartTagSyntax startNode) : base (startNode.StartLine, startNode.TokenIndexBase, startNode.LastTokenIndex) {
StartTag = startNode;
AddChild (StartTag);
}
public int? ValueOpenToken { get; internal set; }
public int? ValueCloseToken { get; internal set; }
public int? ValueToken { get; internal set; }*/
+ public string Name => name.HasValue ? Root.GetTokenStringByIndex (TokenIndexBase + name.Value) : null;
+ public string Value => valueTok.HasValue ? Root.GetTokenStringByIndex (TokenIndexBase + valueTok.Value) : null;
+ public Token? ValueToken => valueTok.HasValue ? Root.GetTokenByIndex (TokenIndexBase + valueTok.Value) : null;
public AttributeSyntax (int startLine, int tokenBase)
: base (startLine, tokenBase) {}
public override bool IsComplete => base.IsComplete & name.HasValue & equal.HasValue & valueTok.HasValue & valueOpen.HasValue & valueClose.HasValue;
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new XmlSyntaxAnalyser (this);
public override IList GetSuggestions (int pos) {
- currentToken = FindTokenIncludingPosition (pos);
- currentNode = FindNodeIncludingPosition (pos);
+ /*currentToken = FindTokenIncludingPosition (pos);
+ currentNode = FindNodeIncludingPosition (pos);*/
return null;
}
- public override TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection) {
+ public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
newSelection = null;
- return null;
+ change = default;
+
+ string selectedSugg = suggestion?.ToString ();
+
+ if (selectedSugg == null)
+ return false;
+
+ if (currentToken.GetTokenType() == XmlTokenType.ElementOpen ||
+ currentToken.GetTokenType() == XmlTokenType.WhiteSpace ||
+ currentToken.GetTokenType() == XmlTokenType.AttributeValueOpen) {
+ change = new TextChange (currentToken.End, 0, selectedSugg);
+ return true;
+ }
+ if (currentToken.GetTokenType() == XmlTokenType.AttributeName && CurrentNode is CrowEdit.Xml.AttributeSyntax attrib) {
+ if (attrib.ValueToken.HasValue) {
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ newSelection = new TextSpan(
+ attrib.ValueToken.Value.Start + change.CharDiff + 1,
+ attrib.ValueToken.Value.End + change.CharDiff - 1
+ );
+ } else {
+ newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"");
+ }
+ return true;
+ }
+
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ return true;
}
public override Color GetColorForToken(TokenType tokType)
}
return false;
}
-
+ protected virtual void parseAttributeValue (ref SpanCharReader reader) {
+ char q = reader.Read();
+ addTok (ref reader, XmlTokenType.AttributeValueOpen);
+ while (!reader.EndOfSpan) {
+ if (reader.Eol()) {
+ addTok (ref reader, XmlTokenType.AttributeValue);
+ reader.ReadEol();
+ addTok (ref reader, XmlTokenType.LineBreak);
+ continue;
+ }
+ if (reader.TryPeak ('<')) {
+ addTok (ref reader, XmlTokenType.AttributeValue);
+ return;
+ }
+ if (reader.TryPeak (q)) {
+ addTok (ref reader, XmlTokenType.AttributeValue);
+ reader.Advance (1);
+ addTok (ref reader, XmlTokenType.AttributeValueClose);
+ return;
+ }
+ reader.Read ();
+ }
+ }
public override Token[] Tokenize (string source) {
SpanCharReader reader = initParsing (source);
break;
case '\'':
case '"':
- char q = reader.Read();
- addTok (ref reader, XmlTokenType.AttributeValueOpen);
- while (!reader.EndOfSpan) {
- if (reader.Eol()) {
- addTok (ref reader, XmlTokenType.AttributeValue);
- reader.ReadEol();
- addTok (ref reader, XmlTokenType.LineBreak);
- continue;
- }
- if (reader.TryPeak (q)) {
- addTok (ref reader, XmlTokenType.AttributeValue);
- reader.Advance (1);
- addTok (ref reader, XmlTokenType.AttributeValueClose);
- break;
- } else
- reader.Read ();
- }
+ parseAttributeValue (ref reader);
break;
case '=':
reader.Advance();
break;
case '/':
reader.Advance();
- if (reader.TryRead ('>')) {
+ if (reader.TryPeak ('>')) {
+ reader.Advance();
addTok (ref reader, XmlTokenType.EmptyElementClosing);
if (--curObjectLevel > 0)
curState = States.Content;
else if (reader.TryAdvance())
addTok (ref reader, XmlTokenType.Unknown);
} else {
- reader.TryReadUntil ('<');
- addTok (ref reader, XmlTokenType.Content);
+ while (!reader.EndOfSpan) {
+ if (reader.Eol()) {
+ addTok (ref reader, XmlTokenType.Content);
+ reader.ReadEol();
+ addTok (ref reader, XmlTokenType.LineBreak);
+ continue;
+ }
+ if (reader.TryPeak ("<")) {
+ addTok (ref reader, XmlTokenType.Content);
+ break;
+ } else
+ reader.Read ();
+ }
}
break;
}
protected override Document openOrCreateFile (string filePath, string editorPath = null) {
Document doc = null;
CurrentFilePath = filePath;
+ try {
+ string ext = Path.GetExtension (CurrentFilePath);
+ if (TryGetDefaultTypeForExtension (ext, out Type clientType)) {
+ if (typeof(Document).IsAssignableFrom (clientType)) {
+ if (editorPath == null)
+ TryGetDefaultEditorForDocumentType (clientType, out editorPath);
+ doc = (Document)Activator.CreateInstance (clientType, new object[] {CurrentFilePath, editorPath});
+ }else if (typeof(Service).IsAssignableFrom (clientType))
+ doc = GetService (clientType)?.OpenDocument (CurrentFilePath);
+ else if (typeof(Project).IsAssignableFrom (clientType)) {
+ Project prj = (Project)Activator.CreateInstance (clientType, new object[] {CurrentFilePath});
+ Projects.Add (prj);
+ CurrentProject = prj;
+ return null;
+ }
+ }else
+ doc = new TextDocument (CurrentFilePath);
- string ext = Path.GetExtension (CurrentFilePath);
- if (TryGetDefaultTypeForExtension (ext, out Type clientType)) {
- if (typeof(Document).IsAssignableFrom (clientType)) {
- if (editorPath == null)
- TryGetDefaultEditorForDocumentType (clientType, out editorPath);
- doc = (Document)Activator.CreateInstance (clientType, new object[] {CurrentFilePath, editorPath});
- }else if (typeof(Service).IsAssignableFrom (clientType))
- doc = GetService (clientType)?.OpenDocument (CurrentFilePath);
- else if (typeof(Project).IsAssignableFrom (clientType)) {
- Project prj = (Project)Activator.CreateInstance (clientType, new object[] {CurrentFilePath});
- Projects.Add (prj);
- CurrentProject = prj;
- return null;
- }
- }else
- doc = new TextDocument (CurrentFilePath);
-
- doc.CloseEvent += onQueryCloseDocument;
- OpenedDocuments.Add (doc);
- CurrentDocument = doc;
+ doc.CloseEvent += onQueryCloseDocument;
+ OpenedDocuments.Add (doc);
+ CurrentDocument = doc;
+ } catch (Exception ex) {
+ System.Diagnostics.Debug.WriteLine ($"[openOrCreateFile]{ex}");
+ }
return doc;
}
/*public TreeNode[] GetCurrentDirNodes =>
<VerticalStack>
<CheckBox Caption="Print line number" IsChecked="{²PrintLineNumbers}"/>
<CheckBox Caption="Reopen last file" IsChecked="{²ReopenLastFile}"/>
+ <CheckBox Caption="Indent With Space" IsChecked="{²IndentWithSpace}"/>
+ <Spinner Caption="Tabulation Size" Value="{²TabulationSize}"/>
</VerticalStack>
</Window>
\ No newline at end of file
<?xml version="1.0"?>
-<DockWindow Caption="Available Plugins" Width="200" >
+<DockWindow Caption="Available Plugins" Width="70%" Height="80%" FreezeDockState="true">
<VerticalStack Margin="5">
- <Label Fit="true" Text="Plugins directory path:" HorizontalAlignment="Left"/>
- <TextBox Height="Fit" Text="{²PluginsDirecory}" Margin="2"/>
- <ListBox Data="{Plugins}" >
+ <Label Fit="true" Text="Plugins directory path:"/>
+ <HorizontalStack Height="Fit">
+ <TextBox Height="Fit" Text="{²PluginsDirecory}" Margin="2"/>
+ <Button Command="{CMDOptions_SelectPluginsDirectory}" MinimumSize="0,0"/>
+ <Button Command="{CMDOptions_ResetPluginsDirectory}" MinimumSize="0,0"/>
+ </HorizontalStack>
+ <ListBox Data="{Plugins}" Height="50%">
<ItemTemplate>
<HorizontalStack Height="Fit">
<Label Text="{Name}" Width="Stretched"/>
</ListBox>
</HorizontalStack>
</ItemTemplate>
- </ListBox>
+ </ListBox>
+ <Splitter/>
+ <TreeView IsRoot="true" Name="lbCtxs" Data="{AllLoadContexts}" UseLoadingThread = 'false' >
+ <ItemTemplate DataType="System.Reflection">
+ <ListItem CornerRadius="2" Margin="0" Height="Fit" Width="Stretched"
+ Selected="{Background=${ControlHighlight}}"
+ Unselected="{Background=Transparent}">
+ <HorizontalStack>
+ <!--<Image Margin="1" Width="14" Height="14" Path="#Crow.Icons.file.svg"/>-->
+ <Label Text="{}" Width="Stretched"/>
+ </HorizontalStack>
+ </ListItem>
+ </ItemTemplate>
+ <ItemTemplate DataType="System.Runtime.Loader.AssemblyLoadContext" Data="Assemblies">
+ <ListItem
+ Selected="{/exp.Background=${ControlHighlight}}"
+ Unselected="{/exp.Background=Transparent}">
+ <Expandable Name="exp" Caption="{}" MouseDoubleClick="/onClickForExpand" BubbleEvents="All">
+ <Template>
+ <VerticalStack>
+ <Border CornerRadius="2" Margin="0" Height="Fit" MouseDoubleClick="./onClickForExpand"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <HorizontalStack Background="{./Background}" Spacing="1">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand"
+ Path="{./Image}"
+ Visible="{./IsExpandable}"
+ SvgSub="{./IsExpanded}"
+ MouseEnter="{Background=LightGrey}"
+ MouseLeave="{Background=Transparent}"/>
+ <Image Margin="1" Width="16" Height="16"
+ Path="#Crow.Icons.folder.svg" SvgSub="{./IsExpanded}"/>
+ <Label Text="{}"/>
+ </HorizontalStack>
+ </Border>
+ <Container Name="Content" Visible="false"/>
+ </VerticalStack>
+ </Template>
+ <HorizontalStack Height="Fit">
+ <Widget Width="12" Height="10"/>
+ <VerticalStack Height="Fit" Name="ItemsContainer"/>
+ </HorizontalStack>
+ </Expandable>
+ </ListItem>
+ </ItemTemplate>
+ </TreeView>
+ <!--<ListBox RootDataLevel="true" DataSource="{../lbCtxs.SelectedItem}" Data="{Assemblies}" UseLoadingThread = 'false' Height="200"/>-->
</VerticalStack>
</DockWindow>
Unselected="{/border.Background=${TreeItemBackground}}"
MouseEnter="{/border.Foreground=${TreeItemBorderHighlightFG}}"
MouseLeave="{/border.Foreground=${TreeItemBorderFG}}">
- <Border Name="border" Margin="2" CornerRadius="${TreeItemBorderCornerRadius}"
+ <Border Name="border" Margin="1" CornerRadius="${TreeItemBorderCornerRadius}"
Foreground="${TreeItemBorderFG}">
<HorizontalStack Spacing="5">
<Image Style="TreeIcon" Path="{Icon}" SvgSub="{IconSub}"/>
<?xml version="1.0"?>
<DockWindow Caption="Syntax" Width="40%">
<VerticalStack RootDataLevel="true" Spacing="0" DataSource="{CurrentDocument}">
+ <Button Command="{CMDRefreshSyntaxTree}"/>
<Label Text="{}"/>
- <TreeView DataSource="{SyntaxRootNode}" Data="{Children}">
+ <Label Text="{SyntaxRootNode}"/>
+ <Label Text="{CurrentNode}"/>
+ <TreeView Data="{SyntaxRootChildNodes}" SelectedItem="{²CurrentNode}">
<ItemTemplate Data="Children">
- <Expandable Caption="{}" BubbleEvents="MouseWheel">
+ <ListItem IsSelected="{IsSelected}"
+ Selected="{/exp.Background=${ControlHighlight}}"
+ Unselected="{/exp.Background=${TreeItemBackground}}">
+ <Expandable Name="exp" Caption="{}" MouseDoubleClick="/onClickForExpand" BubbleEvents="All" IsExpanded="{²isExpanded}"
+ Tooltip="{AsText}">
+ <Template>
+ <VerticalStack>
+ <Border CornerRadius="2" Margin="0" Height="Fit" MouseDoubleClick="./onClickForExpand"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <HorizontalStack Background="{./Background}" Spacing="1">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand"
+ Path="{./Image}"
+ Visible="{HasChilds}"
+ SvgSub="{isExpanded}"
+ MouseEnter="{Background=LightGrey}"
+ MouseLeave="{Background=Transparent}"/>
+ <Label Style="TreeLabel" Text="{./Caption}"/>
+ <Label Style="TreeLabel" Text="ok:"/>
+ <Label Style="TreeLabel" Text="{IsComplete}"/>
+ <Label Style="TreeLabel" Text="span:"/>
+ <Label Style="TreeLabel" Text="{Span}"/>
+ </HorizontalStack>
+ </Border>
+ <Container Name="Content" Visible="false"/>
+ </VerticalStack>
+ </Template>
+ <HorizontalStack Height="Fit">
+ <Widget Width="12" Height="10"/>
+ <VerticalStack Height="Fit" Name="ItemsContainer"/>
+ </HorizontalStack>
+ </Expandable>
+ </ListItem>
+ </ItemTemplate>
+ <!--<ItemTemplate Data="Children">
+ <Expandable Caption="{}" BubbleEvents="MouseWheel" IsExpanded="{²isExpanded}">
<HorizontalStack Height="Fit">
<Shape Foreground="DimGrey" Background="Transparent"
Path="M 5.5,0 L 5.5,11 G" Size="11,11" Width="11" Height="Stretched" KeepProportions="false" Margin="0"/>
MouseEnter="{/border.Foreground=${TreeItemBorderHighlightFG}}"
MouseLeave="{/border.Foreground=${TreeItemBorderFG}}">
<Border Name="border" Margin="2" CornerRadius="${TreeItemBorderCornerRadius}"
- Foreground="${TreeItemBorderFG}">
+ Background="${TreeItemBackground}" Foreground="${TreeItemBorderFG}">
<HorizontalStack Spacing="5">
<Image Margin="1" Width="9" Height="9" Focusable="true" MouseClick="./onClickForExpand"
Path="{./Image}"
Visible="{HasChilds}"
- SvgSub="{./IsExpanded}"
+ SvgSub="{isExpanded}"
MouseEnter="{Background=LightGrey}"
MouseLeave="{Background=Transparent}"/>
- <Label Style="TreeLabel" Text="l:"/>
- <Label Style="TreeLabel" Text="{StartLine}"/>
+ <Label Style="TreeLabel" Text="{./Caption}"/>
<Label Style="TreeLabel" Text="ok:"/>
<Label Style="TreeLabel" Text="{IsComplete}"/>
- <Label Style="TreeLabel" Text="#l:"/>
- <Label Style="TreeLabel" Text="{lineCount2}"/>
- <Label Style="TreeLabel" Text="{./Caption}"/>
<Label Style="TreeLabel" Text="span:"/>
<Label Style="TreeLabel" Text="{Span}"/>
</HorizontalStack>
</VerticalStack>
</Template>
</Expandable>
- </ItemTemplate>
+ </ItemTemplate>-->
</TreeView>
</VerticalStack>
</DockWindow>