protected Token[] tokens;
protected SyntaxNode RootNode;
protected Token currentToken => currentTokenIndex < 0 ? default : tokens[currentTokenIndex];
+ protected Token? previousToken {
+ get {
+ if (currentTokenIndex < 1)
+ return null;
+ return tokens[currentTokenIndex-1];
+ }
+ }
SyntaxNode currentNode;
public SyntaxNode CurrentNode {
get => currentNode;
}
public string CurrentTokenString => RootNode?.Root.GetTokenStringByIndex (currentTokenIndex);
public Token CurrentToken => currentToken;
+ public bool IsParsed => tokens.Length > 0 && RootNode != null;
//public SyntaxNode EditedNode { get; protected set; }
protected int currentTokenIndex;
return default;
int idx = Array.BinarySearch (tokens, 0, tokens.Length, new Token () {Start = pos});
- return idx == 0 ? tokens[0] : idx < 0 ? tokens[~idx - 1] : tokens[idx - 1];
+ return idx == 0 ? tokens[0] : idx < 0 ? tokens[~idx - 1] : tokens[idx];
}
public int FindTokenIndexIncludingPosition (int pos) {
if (pos == 0 || tokens == null || tokens.Length == 0)
base.apply(change);
Tokenizer tokenizer = CreateTokenizer ();
- tokens = tokenizer.Tokenize (Source);
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
if (syntaxAnalyser == null) {
return;
}
+ SyntaxNode changedNode = RootNode.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
+
+
+ tokens = tokenizer.Tokenize (Source);
+
+
+
syntaxAnalyser.Process ();
NotifyValueChanged("Exceptions", syntaxAnalyser.Exceptions);
if (tokType.HasFlag (TokenType.Punctuation))
return Colors.DarkGrey;
if (tokType.HasFlag (TokenType.Trivia))
- return Colors.DimGrey;
+ return Colors.Silver;
if (tokType == TokenType.Keyword)
return Colors.DarkSlateBlue;
return Colors.Red;
/// <param name="newSelection">new position or selection, null if normal position after text changes</param>
/// <returns>true if successed</returns>
public abstract bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection);
+ protected bool previousTokHasFlag(TokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
void parse () {
Tokenizer tokenizer = CreateTokenizer ();
tokens = tokenizer?.Tokenize (Source);
-// Copyright (c) 2021-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+// Copyright (c) 2021-2025 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 CrowEditBase
{
- public class SyntaxException : Exception {
- public readonly Token Token;
- public SyntaxException(string message, Token token = default, Exception innerException = null)
- : base (message, innerException) {
- Token = token;
- }
- }
public abstract class SyntaxAnalyser {
+ //protected abstract void Parse(SyntaxNode node);
protected SourceDocument source;
public abstract SyntaxNode Root { get; }
- public List<SyntaxException> Exceptions { get; protected set; }
+ public IEnumerable<SyntaxException> Exceptions => Root?.GetAllExceptions();
public SyntaxAnalyser (SourceDocument source) {
this.source = source;
}
public abstract void Process ();
- protected Token curTok;
- protected SyntaxNode currentNode;
+
+ #region Token handling
+ protected Token curTok => tokIdx < 0 ? default : tokens[tokIdx];
+ protected Token[] tokens;
+ protected bool EOF => tokIdx == tokens.Length;
+ protected bool tryRead (out Token tok) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx++];
+ return true;
+ }
+ protected bool tryPeek (out Token tok) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx];
+ return true;
+ }
+ protected bool tryPeek (Enum expectedType)
+ => EOF ? false : Enum.Equals(tokens [tokIdx].Type, expectedType);
+
+ protected bool tryRead (out Token tok, Enum expectedType) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx++];
+ return Enum.Equals(tok.Type, expectedType);
+ }
+ protected bool tryPeek (out Token tok, Enum expectedType) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx];
+ return Enum.Equals(tok.Type, expectedType);
+ }
+ protected bool tryPeekFlag (out Token tok, Enum expectedFlag) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx];
+ return tok.Type.HasFlag(expectedFlag);
+ }
+
+ #endregion
+
+ #region parsing context
protected int currentLine, tokIdx;
+ protected SyntaxNode currentNode;
+ #endregion
/// <summary>
/// set current node endToken and line count and set current to current.parent.
/// </summary>
/// <param name="endToken">The final token of this node</param>
/// <param name="endLine">the endline number of this node</param>
- protected void storeCurrentNode (int endTokenOffsetFromCurrentTokIdx = 0) {
- currentNode.LastTokenOffset = tokIdx - currentNode.TokenIndexBase + endTokenOffsetFromCurrentTokIdx;
+ protected void setEndLineForCurrentNode (int endTokenOffsetFromCurrentTokIdx = 0) {
+ currentNode.TokenCount = tokIdx - currentNode.TokenIndexBase + endTokenOffsetFromCurrentTokIdx;
currentNode.EndLine = currentLine;
currentNode = currentNode.Parent;
}
+ protected void setEndOfNode (int endTokenOffsetFromCurrentTokIdx = 0, int endLineOffsetFromCurrentLine = 0) {
+ currentNode.TokenCount = tokIdx - currentNode.TokenIndexBase + endTokenOffsetFromCurrentTokIdx;
+ currentNode.EndLine = currentLine + endLineOffsetFromCurrentLine;
+ }
protected void setCurrentNodeEndLine (int endLine)
=> currentNode.EndLine = endLine;
+ protected bool skipTrivia(bool skipLineBreaks = true) {
+ while (tryPeekFlag(out Token tok, TokenType.Trivia)) {
+ if (tok.Type == TokenType.LineBreak) {
+ if (!skipLineBreaks)
+ return true;
+ currentLine++;
+ }
+ tokIdx++;
+ }
+ return !EOF;
+ }
+ protected void addException(string message) {
+ currentNode.AddException(new SyntaxException(message, curTok));
+ }
//bool EOF => tokIdx == tokens.Length;
--- /dev/null
+// Copyright (c) 2021-2025 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 CrowEditBase
+{
+ public class SyntaxException : Exception {
+ public readonly Token Token;
+ public SyntaxException(string message, Token token = default, Exception innerException = null)
+ : base (message, innerException) {
+ Token = token;
+ }
+ public override string ToString() => $"{Message}, {Token}";
+ }
+}
\ No newline at end of file
namespace CrowEditBase
{
public abstract class SyntaxRootNode : SyntaxNode {
- internal readonly SourceDocument source;
+ protected readonly SourceDocument source;
public SyntaxRootNode (SourceDocument source) {
this.source = source;
}
public override int TokenIndexBase => 0;
- public override int? LastTokenOffset { get => Math.Max (0, source.Tokens.Length - 1); internal set {} }
+ public override int? TokenCount { 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;
+ idx >= 0 && idx < source.Tokens.Length ? source.Tokens[idx].AsString (source.Source) : null;
+ public Token GetTokenByIndex (int idx) =>
+ idx >= 0 && idx < source.Tokens.Length ? source.Tokens[idx] : default;
+ public ReadOnlySpan<char> GetText(TextSpan span) =>
+ source.GetText(span);
}
public class SyntaxNode : CrowEditComponent {
+ internal SyntaxNode () {}
+ public SyntaxNode (int startLine, int tokenBase, int? lastTokenIdx = null) {
+ StartLine = startLine;
+ TokenIndexBase = tokenBase;
+ if (lastTokenIdx.HasValue)
+ TokenCount = lastTokenIdx - tokenBase;
+ }
bool _isExpanded;
public bool isExpanded {
get => _isExpanded;
public SyntaxNode Parent { get; private set; }
public int StartLine { get; private set; }
public virtual int LineCount => lineCount;
- public virtual bool IsComplete => LastTokenOffset.HasValue;
+ public virtual bool IsComplete => TokenCount.HasValue;
public virtual bool IsFoldable => IsComplete && Parent.StartLine != StartLine && lineCount > 1;
public virtual SyntaxRootNode Root => Parent.Root;
public virtual void UnfoldToTheTop () {
isFolded = false;
Parent.UnfoldToTheTop ();
}
- protected Token getTokenByIndex (int idx) => idx < Root.source.Tokens.Length ? Root.source.Tokens[idx] : default;
+ protected Token getTokenByIndex (int idx) => Root.GetTokenByIndex(idx);
internal List<SyntaxNode> children = new List<SyntaxNode> ();
+ List<SyntaxException> exceptions = new List<SyntaxException>();
+ public void AddException(SyntaxException e) => exceptions.Add(e);
+ public void ResetExceptions(SyntaxException e) => exceptions.Clear();
+ public IEnumerable<SyntaxException> Exceptions => exceptions;
+ public IEnumerable<SyntaxException> GetAllExceptions() {
+ foreach (SyntaxException e in exceptions)
+ yield return e;
+ foreach (SyntaxNode n in Children) {
+ foreach (SyntaxException ce in n.GetAllExceptions())
+ yield return ce;
+ }
+ }
+
public IEnumerable<SyntaxNode> Children => children;
//public int IndexOf (SyntaxNode node) => children.IndexOf (node);
public bool HasChilds => children.Count > 0;
}
public virtual int TokenIndexBase { get; private 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;
- TokenIndexBase = tokenBase;
- if (lastTokenIdx.HasValue)
- LastTokenOffset = lastTokenIdx - tokenBase;
- }
+ public virtual int? TokenCount { get; internal set; }
+ public int? LastTokenIndex => TokenIndexBase + TokenCount;
internal bool isFolded;
internal int lineCount;
return new TextSpan (children.First().Span.Start, children.Last().Span.End)
}*/
try {
- Token startTok = getTokenByIndex(TokenIndexBase);
- Token endTok = LastTokenOffset.HasValue ? getTokenByIndex (TokenIndexBase+LastTokenOffset.Value) : startTok;
- return new TextSpan (startTok.Start, endTok.End);
+ Token startTok = getTokenByIndex(TokenIndexBase);
+ Token endTok = TokenCount.HasValue ? getTokenByIndex (TokenIndexBase+TokenCount.Value) : startTok;
+ return new TextSpan (startTok.Start, endTok.End);
}catch{
System.Diagnostics.Debugger.Break ();
}
children.Remove (child);
child.Parent = null;
}
- public T GetChild<T> () => children.OfType<T> ().FirstOrDefault ();
+ public IEnumerable<T> GetChilds<T> () => children.OfType<T>();
+
public void Replace (SyntaxNode newNode) {
Parent.replaceChild (this, newNode);
}
int idx = children.IndexOf (oldNode);
children[idx] = newNode;
newNode.Parent = this;
- int tokIdxDiff = newNode.LastTokenOffset.Value - oldNode.LastTokenOffset.Value;
+ int tokIdxDiff = newNode.TokenCount.Value - oldNode.TokenCount.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;
+ curNode.TokenCount += tokIdxDiff;
if (curNode is SyntaxRootNode)
break;
while (++idx < curNode.children.Count)
foreach (SyntaxNode node in children)
node.Dump (level + 1);
}
- public override string ToString() => $"l:({StartLine,3},{LineCount,3}) tks:{TokenIndexBase},{LastTokenOffset} {this.GetType().Name}";
+ public override string ToString() => $"l:({StartLine,3},{LineCount,3}) tks:{TokenIndexBase},{TokenCount} {this.GetType().Name}";
public string AsText() {
- TextSpan span = Span;
- return Root.source.Source.Substring (span.Start, span.Length);
+ return Span.Length < 0 ? "" : Root.GetText(Span).ToString();
}
public bool IsSimilar (SyntaxNode other) => this.GetType() == other?.GetType();
}
--- /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 Crow.Text;
+using Crow;
+
+namespace CrowEditBase
+{
+ public struct TokenReader
+ {
+ int curPos;
+ Token[] buffer;
+
+ public TokenReader (Token[] span) {
+ buffer = span;
+ curPos = 0;
+ }
+
+ public int CurrentPosition => curPos;
+ /// <summary>
+ /// Current reader position is further the end of the buffer.
+ /// </summary>
+ public bool EndOfSpan => curPos >= buffer.Length;
+
+ public void Seek (int position) => curPos = position;
+
+ public Token Peek => buffer[curPos];
+ public Token Read () => buffer[curPos++];
+ public bool TryRead (out Token c) {
+ if (EndOfSpan) {
+ c = default;
+ return false;
+ }
+ c = Read();
+ return true;
+ }
+ public bool TryRead (Token c) => EndOfSpan ? false : EqualityComparer<Token>.Default.Equals(Read(), c);
+
+ public ReadOnlySpan<Token> Read (int length) => buffer.AsSpan().Slice (curPos += length, length);
+ public void Advance (int increment = 1) => curPos += increment;
+ public bool TryAdvance (int increment = 1) {
+ curPos += increment;
+ return curPos < buffer.Length;
+ }
+ /// <summary>
+ /// Retrieve a span of that buffer from provided starting position to the current reader position.
+ /// </summary>
+ /// <param name="fromPosition"></param>
+ /// <returns></returns>
+ public ReadOnlySpan<Token> Get (int fromPosition) => buffer.AsSpan().Slice (fromPosition, curPos - fromPosition);
+ public bool TryPeek (Token c) => !EndOfSpan && EqualityComparer<Token>.Default.Equals(Peek, c);
+ /// <summary>
+ /// Try peak one char, return false if end of span, true otherwise.
+ /// </summary>
+ /// <param name="c"></param>
+ /// <returns></returns>
+ public bool TryPeek (out Token c) {
+ c = default;
+ if (EndOfSpan)
+ return false;
+ c = buffer[curPos];
+ return true;
+ }
+ }
+}
\ No newline at end of file
Toks.Add (new Token((TokenType)tokType, startOfTok, reader.CurrentPosition));
startOfTok = reader.CurrentPosition;
}
- protected virtual void skipWhiteSpaces (ref SpanCharReader reader) {
+ protected virtual void skipWhiteSpaces (ref SpanCharReader reader, bool skipLineBreaksToo = true) {
while(!reader.EndOfSpan) {
switch (reader.Peek) {
case '\x85':
case '\x2028':
case '\xA':
+ if (!skipLineBreaksToo)
+ return;
reader.Read();
addTok (ref reader, TokenType.LineBreak);
break;
case '\xD':
+ if (!skipLineBreaksToo)
+ return;
reader.Read();
if (reader.IsNextCharIn ('\xA', '\x85'))
reader.Read();
Widget g = FindByName (path);
if (g != null)
return g as Window;
- g = Load (path);
+ if (TryGetConfigFromFloatingWinConfigs(path, out string floatingConfig))
+ g = DockWindow.CreateFromFloatingConfigString(this, floatingConfig);
+ else
+ g = Load (path);
g.Name = path;
g.DataSource = dataSource;
return g as Window;
}
public void CloseWindow (string path){
Widget g = FindByName (path);
+ if (g is DockWindow dockwin) {
+ if (dockwin.IsFloating)
+ saveWinConfigs();
+ }
if (g != null)
DeleteWidget (g);
+
+ }
+ void saveFloatingWinConfigs() {
+ StringBuilder floatings = new StringBuilder (512);
+ DockWindow[] floatingWins = GraphicTree.OfType<DockWindow> ().ToArray ();
+ if (floatingWins.Length > 0) {
+ for (int i = 0; i < floatingWins.Length - 1; i++) {
+ floatings.Append (floatingWins[i].FloatingConfigString);
+ floatings.Append ('|');
+ }
+ floatings.Append (floatingWins[floatingWins.Length - 1].FloatingConfigString);
+ }
+ Configuration.Global.Set ("FloatingWinConfigs", floatings.ToString ());
+ }
+ protected bool TryGetConfigFromFloatingWinConfigs(string winPath, out string conf) {
+ if (Configuration.Global.TryGet<string>("FloatingWinConfigs", out conf) && !string.IsNullOrEmpty(conf)) {
+ string[] floatings = conf.Split ('|');
+ for (int i = 0; i < floatings.Length; i++) {
+ if (floatings[i].Split(';')[0] == winPath) {
+ conf = floatings[i];
+ return true;
+ }
+ }
+ }
+ return false;
}
+ protected void saveWinConfigs() {
+ Configuration.Global.Set ("WinConfigs", mainDock.ExportConfig ());
+ saveFloatingWinConfigs();
+
+ Configuration.Global.Save ();
+ }
+ protected DockStack mainDock;
+ protected void reloadWinConfigs() {
+
+ if (Configuration.Global.TryGet<string>("WinConfigs", out string conf) && !string.IsNullOrEmpty(conf))
+ mainDock.ImportConfig (conf, this);
+ if (Configuration.Global.TryGet<string>("FloatingWinConfigs", out conf) && !string.IsNullOrEmpty(conf)) {
+ string[] floatings = conf.Split ('|');
+ for (int i = 0; i < floatings.Length; i++)
+ DockWindow.CreateFromFloatingConfigString (this, floatings[i], this);
+ }
+ }
+ protected void reloadLogsConfigs() {
+
+ if (Configuration.Global.TryGet<string>("OpenedLogs", out string conf) && !string.IsNullOrEmpty(conf)) {
+ string[] logs = conf.Split ('|');
+ for (int i = 0; i < logs.Length; i++)
+ App.GetLog(logs[i]).IsOpened = true;
+ if (Configuration.Global.TryGet<string>("CurrentLog", out string curLog) && !string.IsNullOrEmpty(curLog))
+ App.GetLog(curLog).IsSelected = true;
+ }
+ }
+ protected void saveLogsConfig() {
+ lock (OpenedLogs) {
+ string openLogs = OpenedLogs.Count > 0 ?
+ OpenedLogs.Select(li=>li.Name).Aggregate((a,b) => a + "|" + b) : null;
+ Configuration.Global.Set("OpenedLogs", openLogs);
+ Configuration.Global.Set("CurrentLog", CurrentLog?.Name);
+ }
+ }
public ActionCommand CMDOptions_SelectPluginsDirectory => new ActionCommand ("...",
() => {
FileDialog dlg = App.LoadIMLFragment<FileDialog> (@"
<Label Text='Line:' Foreground='Grey'/>
<Label Text='{../../tb.CurrentLine}' Margin='3'/>
<Label Text='col:' Foreground='Grey'/>
- <Label Text='{../../tb.CurrentColumn}' Margin='3'/>
+ <Label Text='{../../tb.TabulatedColumn}' Margin='3'/>
</HorizontalStack>
</VerticalStack>
</ListItem>
protected Project project;
public Command CMDDebugStart, CMDDebugPause, CMDDebugStop, CMDDebugStepIn, CMDDebugStepOver, CMDDebugStepOut;
- public virtual CommandGroup Commands => new CommandGroup (
+ public virtual CommandGroup DebugCommands => new CommandGroup (
CMDDebugStart, CMDDebugPause, CMDDebugStop, CMDDebugStepIn, CMDDebugStepOver, CMDDebugStepOut);
protected virtual void initCommands () {
CMDDebugStart = new ActionCommand ("Start", Start, "#icons.debug-play.svg");
#region Label
- int targetColumn = -1;//handle line changes with long->short->long line length sequence.
+ double targetColumn = -1;//handle line changes with long->short->long line length sequence.
protected CharLocation? hoverLoc = null;
protected CharLocation? currentLoc = null;
currentLoc = value;
NotifyValueChanged ("CurrentLine", CurrentLine);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ NotifyValueChanged ("TabulatedColumn", TabulatedColumn);
CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
}
CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
}
}
+ public int TabulatedColumn {
+ get => currentLoc.HasValue ? currentLoc.Value.TabulatedColumn < 0 ? 0 : currentLoc.Value.TabulatedColumn : 0;
+ }
+
/// <summary>
/// Set current cursor position in label.
/// </summary>
//protected object linesMutex = new object ();
protected Size cachedTextSize = default (Size);
-
-
protected FontExtents fe;
protected TextExtents te;
-
+ protected int tabSize;
/// <summary>
/// Background color for selected text inside this label.
RegisterForRedraw ();
}
}
-
+ [DefaultValue(4)]
+ public int TabSize {
+ get => tabSize;
+ set {
+ if (tabSize == value)
+ return;
+ tabSize = value;
+ NotifyValueChanged("TabSize",tabSize);
+ }
+ }
protected double lineHeight => fe.Ascent + fe.Descent;
protected virtual int getAbsoluteLineIndexFromVisualLineMove (int startLine, int visualLineDiff)
/// </summary>
/// <returns><c>true</c> if move succeed</returns>
public bool MoveLeft(){
- //targetColumn = -1;
+ targetColumn = -1;
CharLocation loc = CurrentLoc.Value;
if (loc.Column == 0) {
if (loc.Line == 0)
return false;
int newLine = getAbsoluteLineIndexFromVisualLineMove (loc.Line, -1);
- CurrentLoc = new CharLocation (newLine, document.GetLine (newLine).Length);
+ loc = new CharLocation (newLine, document.GetLine (newLine).Length);
}else
- CurrentLoc = new CharLocation (loc.Line, loc.Column - 1);
+ loc = new CharLocation (loc.Line, loc.Column - 1);
+ updateLocation(ref loc);
+ CurrentLoc = loc;
return true;
}
public bool MoveRight () {
if (loc.Column == document.GetLine (loc.Line).Length) {
if (loc.Line == document.LinesCount - 1)
return false;
- CurrentLoc = new CharLocation (
+ loc = new CharLocation (
getAbsoluteLineIndexFromVisualLineMove (loc.Line, 1), 0);
} else
- CurrentLoc = new CharLocation (loc.Line, loc.Column + 1);
+ loc = new CharLocation (loc.Line, loc.Column + 1);
+ updateLocation(ref loc);
+ CurrentLoc = loc;
return true;
}
public bool LineMove (int lineDiff) {
+ if (!CurrentLoc.HasValue)
+ return false;
+
CharLocation loc = CurrentLoc.Value;
int newLine = getAbsoluteLineIndexFromVisualLineMove (loc.Line, lineDiff);
-
if (newLine == loc.Line)
return false;
- if (loc.Column > document.GetLine (newLine).Length) {
+ using (IContext gr = IFace.Backend.CreateContext (IFace.MainSurface)) {
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+ CharLocation newLoc;
+ double targetX;
+ if (targetColumn > 0) {
+ targetX = targetColumn;
+ } else {
+ if (!loc.HasVisualX)
+ updateLocation(gr, ref loc);
+ targetX = loc.VisualCharXPosition;
+ }
+
+ newLoc = new CharLocation(newLine, -1, targetX);
+ updateLocation(ref newLoc);
+
+ if (newLoc.VisualCharXPosition < targetX) {
+ if (targetColumn < 0)
+ targetColumn = loc.VisualCharXPosition;
+ } else {
+ targetColumn = -1;
+ }
+
+ CurrentLoc = newLoc;
+ }
+
+ /*if (loc.Column > document.GetLine (newLine).Length) {
if (targetColumn < 0)
targetColumn = loc.Column;
CurrentLoc = new CharLocation (newLine, document.GetLine (newLine).Length);
else if (targetColumn > document.GetLine (newLine).Length)
CurrentLoc = new CharLocation (newLine, document.GetLine (newLine).Length);
else
- CurrentLoc = new CharLocation (newLine, targetColumn);
+ CurrentLoc = new CharLocation (newLine, targetColumn);*/
return true;
}
try {
//if (HasFocus) {
if (currentLoc?.Column < 0) {
- updateLocation (gr, cb.Width, ref currentLoc);
- NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ updateLocation (gr, ref currentLoc);
} else
- updateLocation (gr, cb.Width, ref currentLoc);
+ updateLocation (gr, ref currentLoc);
if (selectionStart.HasValue) {
- updateLocation (gr, cb.Width, ref selectionStart);
+ updateLocation (gr, ref selectionStart);
if (CurrentLoc.Value != selectionStart.Value)
selectionNotEmpty = true;
}
NotifyValueChanged("ScrollY", ScrollY);
NotifyValueChanged("VisibleLines", visibleLines);
NotifyValueChanged("HoverLine", hoverLine);
- hoverLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X + ScrollX);
- using (IContext gr = IFace.Backend.CreateContext (IFace.MainSurface)) {
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
- updateLocation (gr, ClientRectangle.Width, ref hoverLoc);
- }
+ CharLocation newLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X + ScrollX);
+ updateLocation (ref newLoc);
+ hoverLoc = newLoc;
}
protected virtual bool cancelLinePrint (double lineHeght, double y, int clientHeight) => false;
RectangleD? textCursor = null;
rect = default;
return false;
}
- if (!CurrentLoc.Value.HasVisualX) {
+ CharLocation loc = currentLoc.Value;
+
+ if (!loc.HasVisualX) {
ctx.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
ctx.SetFontSize (Font.Size);
if (currentLoc?.Column < 0) {
- updateLocation (ctx, ClientRectangle.Width, ref currentLoc);
- NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ updateLocation (ctx, ref loc);
+ //update is locked, should not notify while updating graphics
+ //NotifyValueChanged ("CurrentColumn", CurrentColumn);
} else
- updateLocation (ctx, ClientRectangle.Width, ref currentLoc);
+ updateLocation (ctx, ref loc);
textCursor = null;
}
+ currentLoc = loc;
- textCursor = computeTextCursor (new RectangleD (CurrentLoc.Value.VisualCharXPosition, lineHeight * visualCurrentLine, 1.0, lineHeight));
+ textCursor = computeTextCursor (new RectangleD (loc.VisualCharXPosition, lineHeight * visualCurrentLine, 1.0, lineHeight));
if (textCursor == null) {
rect = default;
return false;
}
- //}
Rectangle c = ContextCoordinates (textCursor.Value + Slot.Position + ClientRectangle.Position);
Foreground.SetAsSource (IFace, ctx, c);
rect = c;
return true;
}
-
+ protected void updateLocation(ref CharLocation loc) {
+ if (loc.HasVisualX)
+ return;
+ using (IContext gr = IFace.Backend.CreateContext (IFace.MainSurface)) {
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+ updateLocation(gr, ref loc);
+ }
+ }
+ [Obsolete("use override without clientWidth parameter")]
protected void updateLocation (IContext gr, int clientWidth, ref CharLocation? location) {
if (location == null)
return;
CharLocation loc = location.Value;
- //Console.WriteLine ($"updateLocation: {loc} text:{_text.Length}");
+ updateLocation(gr, ref loc);
+ location = loc;
+ }
+ protected void updateLocation (IContext gr, ref CharLocation? location) {
+ if (location == null)
+ return;
+ CharLocation loc = location.Value;
+ updateLocation(gr, ref loc);
+ location = loc;
+ }
+ protected void updateLocation (IContext gr, ref CharLocation loc) {
if (loc.HasVisualX)
return;
TextLine ls = document.GetLine (loc.Line);
ReadOnlySpan<char> curLine = document.GetText (ls);
- double cPos = 0;
if (loc.Column >= 0) {
//int encodedBytes = Crow.Text.Encoding2.ToUtf8 (curLine.Slice (0, loc.Column), bytes);
loc.Column = curLine.Length;
}
#endif
- loc.VisualCharXPosition = gr.TextExtents (curLine.Slice (0, loc.Column), App.TabulationSize).XAdvance + cPos;
- location = loc;
+ ReadOnlySpan<char> buff = curLine.Slice (0, loc.Column);
+ loc.TabulatedColumn = buff.Count('\t') * (tabSize-1) + buff.Length;
+ loc.VisualCharXPosition = gr.TextExtents (buff).XAdvance;
} else {
TextExtents te;
Span<byte> bytes = stackalloc byte[5];//utf8 single char buffer + '\0'
+ int totChar = 0;
+ double cPos = 0;
for (int i = 0; i < ls.Length; i++) {
- int encodedBytes = curLine.Slice (i, 1).ToUtf8 (bytes);
+ int encodedBytes = curLine.Slice (i, 1).ToUtf8 (bytes, ref totChar, tabSize);
bytes[encodedBytes] = 0;
gr.TextExtents (bytes, out te);
if (loc.VisualCharXPosition <= cPos + halfWidth) {
loc.Column = i;
loc.VisualCharXPosition = cPos;
- location = loc;
+ loc.TabulatedColumn = totChar;
return;
}
}
loc.Column = ls.Length;
loc.VisualCharXPosition = cPos;
- location = loc;
+ loc.TabulatedColumn = totChar;
}
}
+ /*protected void updateLocation (IContext gr, int clientWidth, ref CharLocation? location) {
+ if (location == null)
+ return;
+ CharLocation loc = location.Value;
+ //Console.WriteLine ($"updateLocation: {loc} text:{_text.Length}");
+ if (loc.HasVisualX)
+ return;
+ if (loc.Column == 0) {
+ loc.VisualCharXPosition = 0;
+ } else {
+
+ TextLine ls = document.GetLine (loc.Line);
+ ReadOnlySpan<char> curLine = document.GetText (ls);
+ double cPos = 0;
+
+ if (loc.Column >= 0) {
+ //int encodedBytes = Crow.Text.Encoding2.ToUtf8 (curLine.Slice (0, loc.Column), bytes);
+ #if DEBUG
+ if (loc.Column > curLine.Length) {
+ System.Diagnostics.Debug.WriteLine ($"loc.Column: {loc.Column} curLine.Length:{curLine.Length}");
+ loc.Column = curLine.Length;
+ }
+ #endif
+ Span<byte> bytes = stackalloc byte[loc.Column*4+10];
+ int encodedBytes = curLine.Slice (0,loc.Column).ToUtf8 (bytes, 4);
+ bytes[encodedBytes++] = 0;
+ gr.TextExtents (bytes, out TextExtents te);
+ loc.VisualCharXPosition = te.XAdvance;
+ } else {
+ TextExtents te;
+ Span<byte> bytes = stackalloc byte[5];//utf8 single char buffer + '\0'
+
+ for (int i = 0; i < ls.Length; i++) {
+ int encodedBytes = curLine.Slice (i, 1).ToUtf8 (bytes);
+ bytes[encodedBytes] = 0;
+
+ gr.TextExtents (bytes, out te);
+ double halfWidth = te.XAdvance / 2;
+
+ if (loc.VisualCharXPosition <= cPos + halfWidth) {
+ loc.Column = i;
+ loc.VisualCharXPosition = cPos;
+ location = loc;
+ return;
+ }
+
+ cPos += te.XAdvance;
+ }
+ loc.Column = ls.Length;
+ loc.VisualCharXPosition = cPos;
+ }
+ }
+ location = loc;
+ }*/
protected void checkShift (KeyEventArgs e) {
if (e.Modifiers.HasFlag (Modifier.Shift)) {
}
protected virtual void update (TextChange change) {
-
if (!disableTextChangedEvent)
OnTextChanged (this, new TextChangeEventArgs (change));
selectionStart = null;
- CurrentLoc = document.GetLocation (change.Start + change.ChangedText.Length);
+ CharLocation newLoc = document.GetLocation (change.Start + change.ChangedText.Length);
+ updateLocation(ref newLoc);//ensure tabulated column is uptodate on each changes
+ CurrentLoc = newLoc;
textMeasureIsUpToDate = false;
IFace.forceTextCursor();
{
public class SourceEditor : Editor {
object TokenMutex = new object();
- /*protected override void backgroundThreadFunc () {
- while (true) {
- if (Document != null && Document.TryGetState (this, out List<TextChange> changes)) {
- disableTextChangedEvent = true;
- disableSuggestions = true;
- foreach (TextChange tc in changes)
- update (tc);
- disableTextChangedEvent = false;
- disableSuggestions = false;
- }
- System.Threading.Thread.Sleep (200);
- }
- }*/
-
SyntaxNode currentNode;
#if DEBUG_NODE
SyntaxNode _hoverNode;
}
}
+ #region suggestions and autocomplete
ListBox overlay;
IList suggestions;
volatile bool disableSuggestions;
bool suggestionsActive => overlay != null && overlay.IsVisible;
protected void tryGetSuggestions () {
- if (currentLoc.HasValue && Document is SourceDocument srcDoc) {
+ if (currentLoc.HasValue && Document is SourceDocument srcDoc && srcDoc.IsParsed) {
IList suggs = srcDoc.GetSuggestions (CurrentLoc.Value);
if (suggs != null && suggs.Count == 1 && (
(suggs[0] is System.Reflection.MemberInfo mi && mi.Name == srcDoc.CurrentTokenString) ||
hideOverlay ();
tryGetSuggestions ();
}
-
+ #endregion
+
+ #region Margin
const int leftMarginGap = 5;//gap between margin start and numbering
const int leftMarginRightGap = 3;//gap between items in margin and text
const int foldSize = 9;//folding rectangles size
const int foldMargin = 9;
-
int leftMargin;
bool mouseIsInMargin, mouseIsInFoldRect;
leftMargin += leftMarginRightGap;
//updateVisibleColumns ();
}
+ #endregion
protected override CharLocation? CurrentLoc {
get => currentLoc;
}
NotifyValueChanged ("CurrentLine", CurrentLine);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ NotifyValueChanged ("TabulatedColumn", TabulatedColumn);
CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
}
}
+
public override int measureRawSize(LayoutingType lt)
{
DbgLogger.StartEvent(DbgEvtType.GOMeasure, this, lt);
gr.Operator = Operator.Over;
}
+ protected void drawLineNumber(IContext gr, int lineIndex, double x, double y) {
+ string strLN = (lineIndex+1).ToString ();
+ gr.MoveTo (x - gr.TextExtents (strLN).Width, y);
+ gr.ShowText (strLN);
+ gr.Fill ();
+
+ }
protected override void drawContent (IContext gr) {
if (!(Document is SourceDocument doc)) {
base.drawContent (gr);
doc.EnterReadLock ();
try {
- if (doc.Tokens == null || doc.Tokens.Length == 0) {
- base.drawContent (gr);
- return;
- }
-
double lineHeight = fe.Ascent + fe.Descent;
updateMargin ();
bool printLineNumbers = App.PrintLineNumbers;
Color marginBG = App.MarginBackground;
Color marginFG = Colors.Ivory;
+ Rectangle cb = ClientRectangle;
+ RectangleD marginRect = new RectangleD (cb.X + ScrollX, cb.Y, leftMargin - leftMarginRightGap, cb.Height);
+
+ gr.SetSource (marginBG);
+ gr.Rectangle (marginRect);
+ gr.Fill();
+
+
+ if (!doc.IsParsed) {
+ base.drawContent (gr);
+ return;
+ }
+
double lineNumWidth = gr.TextExtents (Document.LinesCount.ToString()).Width;
- Rectangle cb = ClientRectangle;
- RectangleD marginRect = new RectangleD (cb.X + ScrollX, cb.Y, leftMargin - leftMarginRightGap, lineHeight);
+ marginRect.Height = lineHeight;
cb.Left += leftMargin;
CharLocation selStart = default, selEnd = default;
bool selectionNotEmpty = false;
CharLocation? nodeStart = null, nodeEnd = null;
-
+#if DEBUG_NODES
CharLocation? editNodeStart = null, editNodeEnd = null;//debug
CharLocation? hoverNodeStart = null, hoverNodeEnd = null;
-
+#endif
if (currentLoc?.Column < 0) {
- updateLocation (gr, cb.Width, ref currentLoc);
- NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ updateLocation (gr, ref currentLoc);
} else
- updateLocation (gr, cb.Width, ref currentLoc);
+ updateLocation (gr, ref currentLoc);
if (CurrentNode != null) {
TextSpan nodeSpan = CurrentNode.Span;
nodeStart = Document.GetLocation (nodeSpan.Start);
- updateLocation (gr, cb.Width, ref nodeStart);
+ updateLocation (gr, ref nodeStart);
nodeEnd = Document.GetLocation (nodeSpan.End);
- updateLocation (gr, cb.Width, ref nodeEnd);
+ updateLocation (gr, ref nodeEnd);
}
#if DEBUG_NODES
if (doc.EditedNode != null) {
if (p.Y < 0 || p.X < 0)
hideOverlay ();
else {
- p += ScreenCoordinates (Slot).TopLeft;
+ p += ScreenCoordinates (Slot).TopLeft + cb.TopLeft;
overlay.Left = p.X;
overlay.Top = p.Y;
}
}
if (selectionStart.HasValue) {
- updateLocation (gr, cb.Width, ref selectionStart);
+ updateLocation (gr, ref selectionStart);
if (CurrentLoc.Value != selectionStart.Value)
selectionNotEmpty = true;
}
}
- double spacePixelWidth = gr.TextExtents (" ").XAdvance;
+ //double spacePixelWidth = gr.TextExtents (" ").XAdvance;
int x = 0;
double pixX = cb.Left,
pixY = cb.Top;
IEnumerator<SyntaxNode> nodeEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator ();
bool notEndOfNodes = nodeEnum.MoveNext();
+ gr.LineWidth = 1;
int l = 0;
while (l < Document.LinesCount) {
//if (!cancelLinePrint (lineHeight, lineHeight * y, cb.Height)) {
}
//buff = sourceBytes.Slice (lines[l].Start, lines[l].Length);
+ int encodedChar = 0;
while (tok.Start < Document.GetLine (l).End) {
buff = sourceBytes.Slice (tok.Start, tok.Length);
if (bytes.Length < size)
bytes = new byte[size];
- int encodedBytes = buff.ToUtf8 (bytes);
+ int encodedBytes = buff.ToUtf8 (bytes, ref encodedChar, tabSize);
if (encodedBytes > 0) {
bytes[encodedBytes++] = 0;
gr.TextExtents (bytes.Slice (0, encodedBytes), out extents);
- gr.MoveTo (pixX, pixY + fe.Ascent);
- gr.ShowText (bytes.Slice (0, encodedBytes));
+ if (extents.Width > 0) {
+ gr.MoveTo (pixX, pixY + fe.Ascent);
+ gr.ShowText (bytes.Slice (0, encodedBytes));
+ }
+
+ if (doc.CurrentToken.Equals(tok)) {
+ /*CharLocation? tokloc = Document.GetLocation (tok.Start);
+ updateLocation (gr, cb.Width, ref tokloc);*/
+ Rectangle r = new RectangleD(pixX, pixY, extents.Width, lineHeight);
+ r.Inflate(1);
+ gr.Rectangle(r);
+ gr.SetSource(doc.GetColorForToken (tok.Type).AdjustAlpha(0.6));
+ gr.Stroke();
+ }
+
pixX += extents.XAdvance;
x += buff.Length;
}
RectangleD lineRect = new RectangleD (cb.X, pixY, pixX - cb.X, lineHeight);
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.08));;
+ fillHighlight (gr, l, nodeStart.Value, nodeEnd.Value, lineRect, new Color(0.0,0.1,0.0,0.04));;
#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));;
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);
-
-
+ fillHighlight (gr, l, selStart, selEnd, lineRect, SelectionBackground);
+
//Draw line numbering
if (printLineNumbers){
marginRect.Y = lineRect.Y;
-
- string strLN = (l+1).ToString ();
- gr.SetSource (marginBG);
- gr.Rectangle (marginRect);
- gr.Fill();
gr.SetSource (marginFG);
- gr.MoveTo (marginRect.X + leftMarginGap + lineNumWidth - gr.TextExtents (strLN).Width, marginRect.Y + fe.Ascent);
- gr.ShowText (strLN);
- gr.Fill ();
+
+ drawLineNumber (gr, l, marginRect.X + leftMarginGap + lineNumWidth, marginRect.Y + fe.Ascent);
+ if (tokPtr + 1 == doc.Tokens.Length && l < doc.LinesCount-1)
+ drawLineNumber (gr, l+1, marginRect.X + leftMarginGap + lineNumWidth, marginRect.Y + lineHeight + fe.Ascent);
}
+
//draw fold
if (foldable) {
Rectangle rFld = new Rectangle (cb.X - leftMarginGap - foldMargin,
gr.Stroke ();
}
- if (++tokPtr >= doc.Tokens.Length)
+ if (++tokPtr >= doc.Tokens.Length) {
break;
+ }
+
tok = doc.Tokens[tokPtr];
x = 0;
pixX = cb.Left;
pixY += lineHeight;
+ /*if (pixY > cb.Height)
+ break;*/
if (foldable && curNode.isFolded) {
TextSpan ns = curNode.Span;
pixX += spacePixelWidth * tok2.Length;*/
}
//gr.Translate (ScrollX, ScrollY);
+ } catch (Exception e) {
+ Console.WriteLine(e.Message);
+ Console.WriteLine(e.StackTrace);
} finally {
doc.ExitReadLock ();
}
{
editorRWLock.EnterWriteLock ();
registeredClients.Add (client, null);
- notifyClient (client, new TextChange (0, 0, Source));
+ //notifyClient (client, new TextChange (0, 0, source));
editorRWLock.ExitWriteLock ();
}
public override void UnregisterClient(object client)
}
protected Stack<TextChange> undoStack = new Stack<TextChange> ();
protected Stack<TextChange> redoStack = new Stack<TextChange> ();
-
-
-
protected override void saveFileDialog_OkClicked (object sender, EventArgs e)
{
FileDialog fd = sender as FileDialog;
writeToDisk ();
}
-
protected override void undo () {
editorRWLock.EnterWriteLock ();
try {
Background = "${DockWindowBackground}";
Margin="0";
RootDataLevel = "true";
+ HorizontalAlignment = "Center";
+ VerticalAlignment = "Center";
}
DockWindow2 {
Template = "#ui.DockWindow2.template";
Margin="0";
RootDataLevel = "true";
}
+DockWindowToolbar {
+ Template = "#ui.DockWindowToolbar.template";
+ Background = "${DockWindowBackground}";
+ Margin="0";
+ RootDataLevel = "true";
+ HorizontalAlignment = "Center";
+ VerticalAlignment = "Center";
+ Resizable = "false";
+ Height="Fit";
+ Width="Fit";
+}
DockWinTitleBarMenu {
ItemTemplate = "#ui.DockWinTitleBarMenu.itemp";
}
--- /dev/null
+<?xml version="1.0"?>
+<Border Background="{./Background}" Margin="5" CornerRadius="0">
+ <HorizontalStack>
+ <Widget Width="12" Height="Stretched" Background="Onyx" Name="MoveHandle" Focusable="true" CornerRadius="5"/>
+ <Container Name="Content" Width="Stretched"/>
+ </HorizontalStack>
+</Border>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<Label Background="{./Background}"/>
\ No newline at end of file
LargeIncrement="{../tb.PageWidth}" SmallIncrement="1"
CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" />
<Splitter/>
- <ListBox Data='{Exceptions}' Height='200' Width='Stretched'/>
+ <ListBox Data='{Exceptions}' Height='10%' Width='Stretched'/>
<HorizontalStack Height="Fit" Spacing='3'>
<Widget Width="Stretched"/>
<Label Text="TokType" Foreground="Grey"/>
<Label Text="{CurrentTokenString}" Margin="3"/>
<Label Text="Node" Foreground="Grey"/>
<Label Text="{CurrentNode}" Margin="3"/>
- <!--<Label Text="MouseY:" Foreground="Grey"/>
+ <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"/>
<Label Text="Col:" Foreground="Grey"/>
- <Label Text="{../../tb.CurrentColumn}" Margin="3"/>
+ <Label Text="{../../tb.TabulatedColumn}" Margin="3"/>
</HorizontalStack>
</VerticalStack>
</ListItem>
IEnumerable<MemberInfo> getAllCrowTypeMembers (string crowTypeName) {
Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName);
- return crowType.GetMembers (BindingFlags.Public | BindingFlags.Instance).
+ return crowType?.GetMembers (BindingFlags.Public | BindingFlags.Instance).
Where (m=>((m is PropertyInfo pi && pi.CanWrite) || (m is EventInfo)) &&
m.GetCustomAttribute<XmlIgnoreAttribute>() == null);
}
Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName);
return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
}
+
+ protected bool previousTokHasFlag(ImlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
+
+ protected bool tryCast<TOUT> (object objectToCast, out TOUT result) {
+ result = default;
+ if (typeof(TOUT).IsAssignableFrom(objectToCast.GetType())) {
+ result = (TOUT)objectToCast;
+ return true;
+ }
+
+ return false;
+ }
public override IList GetSuggestions (CharLocation loc) {
- if (tokens.Length == 0)
- return null;
IList sugs = base.GetSuggestions (loc);
if (sugs != null)
return sugs;
- if (currentToken.GetTokenType() == XmlTokenType.ElementOpen)
+ //Token tok = currentToken.Length == 0 || currentToken.Type.HasFlag(TokenType.Trivia) ? previousToken : currentToken;
+ Token tok = currentToken;
+
+ if (tok.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 (currentToken.GetTokenType() == XmlTokenType.WhiteSpace && CurrentNode is ElementStartTagSyntax eltStartTag2)
- return getAllCrowTypeMembers (eltStartTag2.Name).ToList();
+ if (tok.GetTokenType() == XmlTokenType.ElementName)
+ return allWidgetNames.Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ if ((tok.Type.HasFlag(TokenType.WhiteSpace) || previousTokHasFlag(TokenType.WhiteSpace)) &&
+ tryCast(CurrentNode, out ElementTagSyntax ets)) {
+ if (ets.name.HasValue)
+ return getAllCrowTypeMembers (ets.Name).ToList();
+ return null;
+ }
+
if (CurrentNode is CrowEdit.Xml.AttributeSyntax attribNode) {
if (CurrentNode.Parent is ElementTagSyntax eltTag) {
if (!string.IsNullOrEmpty (eltTag.Name)) {
- if (currentToken.GetTokenType() == XmlTokenType.AttributeName) {
+ if (tok.GetTokenType() == XmlTokenType.AttributeName) {
return getAllCrowTypeMembers (eltTag.Name)
- .Where (s => s.Name.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ .Where (s => s.Name.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
} else if (!string.IsNullOrEmpty (attribNode.Name)) {
- if (currentToken.GetTokenType() == XmlTokenType.AttributeValue) {
+ if (tok.GetTokenType() == XmlTokenType.AttributeValue) {
MemberInfo mi = getCrowTypeMember (
eltTag.Name, attribNode.Name);
if (mi is PropertyInfo pi) {
if (pi.Name == "Style")
return App.Styling.Keys
- .Where (s => s.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ .Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
if (pi.PropertyType.IsEnum)
return Enum.GetNames (pi.PropertyType)
- .Where (s => s.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ .Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
if (pi.PropertyType == typeof(bool))
return (new string[] {"true", "false"}).
- Where (s => s.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
if (pi.PropertyType == typeof (Measure))
return (new string[] {"Stretched", "Fit"}).
- Where (s => s.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
if (pi.PropertyType == typeof (Fill))
return EnumsNET.Enums.GetValues<Colors> ()
- .Where (s => s.ToString().StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ .Where (s => s.ToString().StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
}
- } else if (currentToken.GetTokenType() == XmlTokenType.AttributeValueOpen) {
+ } else if (tok.GetTokenType() == XmlTokenType.AttributeValueOpen) {
MemberInfo mi = getCrowTypeMember (
eltTag.Name, attribNode.Name);
if (mi is PropertyInfo pi) {
}
}
}
- } else if (currentToken.GetTokenType() != XmlTokenType.AttributeValueClose &&
- currentToken.GetTokenType() != XmlTokenType.EmptyElementClosing &&
- currentToken.GetTokenType() != XmlTokenType.ClosingSign &&
+ } /*else if (tok.GetTokenType() != XmlTokenType.AttributeValueClose &&
+ tok.GetTokenType() != XmlTokenType.EmptyElementClosing &&
+ tok.GetTokenType() != XmlTokenType.ClosingSign &&
CurrentNode is ElementStartTagSyntax eltStartTag) {
- if (currentToken.GetTokenType() == XmlTokenType.AttributeName)
+ if (tok.GetTokenType() == XmlTokenType.AttributeName)
return getAllCrowTypeMembers (eltStartTag.Name)
- .Where (s => s.Name.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
- //else if (currentToken.Type == TokenType.ElementName)
+ .Where (s => s.Name.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+ //else if (tok.Type == TokenType.ElementName)
// Suggestions = getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source)).ToList ();
} else {
- }
+ }*/
return null;
}
public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
public override void Process () {
StyleDocument doc = source as StyleDocument;
- Exceptions = new List<SyntaxException> ();
currentNode = new StyleRootSyntax (doc);
currentLine = 0;
Span<Token> toks = source.Tokens;
tokIdx++;
}
while (currentNode.Parent != null) {
- if (!currentNode.LastTokenOffset.HasValue)
- storeCurrentNode (-1);
+ if (!currentNode.TokenCount.HasValue)
+ setEndLineForCurrentNode (-1);
else
currentNode = currentNode.Parent;
}
public override Color GetColorForToken(TokenType tokType)
{
EbnfTokenType xmlTokType = (EbnfTokenType)tokType;
+ if (xmlTokType == EbnfTokenType.OpenBracket || xmlTokType == EbnfTokenType.ClosingBracket)
+ return Colors.RebeccaPurple;
+ if (xmlTokType == EbnfTokenType.StringDelimiter)
+ return Colors.DarkGoldenRod;
+ if (xmlTokType == EbnfTokenType.StringLiteral)
+ return Colors.DarkGoldenRod;
+
if (xmlTokType.HasFlag (EbnfTokenType.Punctuation))
return Colors.DarkGrey;
- if (xmlTokType.HasFlag (EbnfTokenType.Trivia))
- return Colors.DimGrey;
- return Colors.Black;
+ if (xmlTokType == EbnfTokenType.SymbolName)
+ return Colors.Blue;
+ if (xmlTokType == EbnfTokenType.Name)
+ return Colors.Green;
+ return base.GetColorForToken(tokType);
}
}
namespace CrowEdit.Ebnf
{
+
public class EbnfSyntaxAnalyser : SyntaxAnalyser {
public override SyntaxNode Root => currentNode;
public EbnfSyntaxAnalyser (EbnfDocument source) : base (source) {
this.source = source;
}
+
+
+ // ::= NCName '::=' Expression
+ // Link ::= '[' URL ']'
+ // Choice ::= SequenceOrDifference ( '|' SequenceOrDifference )*
+ // SequenceOrDifference ::= Item ( '-' Item | Item* )?
+ // Item ::= Primary ( '?' | '*' | '+' )?
+ //NCName | StringLiteral | CharCode | CharClass | '(' Choice ')'
+ // StringLiteral ::= '"' [^"]* '"' | "'" [^']* "'"
+
public override void Process()
{
EbnfDocument doc = source as EbnfDocument;
- Exceptions = new List<SyntaxException>();
currentNode = new EbnfRootSyntax (doc);
currentLine = 0;
- source2 = doc.Source;
-
- Span<Token> toks = source.Tokens;
tokIdx = 0;
+ tokens = doc.Tokens;
+
+ /*while(tokIdx < tokens.Length) {
+ skipTrivia();
+
+ if (currentNode is EbnfRootSyntax root) {
+ if (curTok.GetTokenType() == EbnfTokenType.SymbolName)
+ currentNode = root.AddChild(
+ new ProductionSyntax(0, currentLine, tokIdx));
+ else
+ addException("Unexpected token");
+
+ } else if (currentNode is ProductionSyntax prod) {
+ if (curTok.GetTokenType() == EbnfTokenType.SymbolAffectation) {
+ prod.equal = tokIdx;
+ tokIdx++;
+ if (!skipTrivia())
+ break;
+ currentNode = currentNode.AddChild(
+ new ExpressionSyntax(currentLine, tokIdx));
+ } else {
+ addException("'::=' expected.");
+ currentNode = Root;
+ }
+ } else if (currentNode is ExpressionSyntax exp) {
+ if (curTok.GetTokenType() == EbnfTokenType.OpenBracket) {
+ //either CharClass or link
+ int openBraketIdx = tokIdx;
+ tokIdx++;
+ if (tryPeek(EbnfTokenType.CharMatchNegation)) {
+ currentNode = currentNode.AddChild(
+ new CharClassSyntax(currentLine, openBraketIdx) );
+ } else {
+ while(tryPeek(out Token tok) && !tok.Type.HasFlag(TokenType.Trivia)) {
+ EbnfTokenType tokType = tok.GetTokenType();
+ if (tokType == EbnfTokenType.ClosingBracket) {
- while (tokIdx < toks.Length) {
- curTok = toks[tokIdx];
- switch (curTok.GetTokenType())
- {
- case EbnfTokenType.LineBreak:
- currentLine++;
- break;
- case EbnfTokenType.SymbolName:
- currentNode = currentNode.AddChild(new ProductionSyntax(0, currentLine, tokIdx));
- break;
-
+ }
+ }
+ }
+ } else {
+
+ }
}
+
tokIdx++;
- }
-
+ }*/
+
setCurrentNodeEndLine (currentLine);
}
- Token[] tokens;
+
Stack<object> resolveStack;//expression resolutions
string source2;
- bool EOF => tokIdx == tokens.Length;
+
bool EndOfExpression =>
EOF || tokIdx > tokens.Length - 2 || tokens[tokIdx + 1].GetTokenType() == EbnfTokenType.SymbolAffectation;
- bool tryRead (out Token tok) {
- if (EOF) {
- tok = default;
- return false;
- }
- tok = tokens [tokIdx++];
- return true;
- }
- bool tryPeek (out Token tok) {
- if (EOF) {
- tok = default;
- return false;
- }
- tok = tokens [tokIdx];
- return true;
- }
- bool tryRead (out Token tok, EbnfTokenType expectedType) {
- if (EOF) {
- tok = default;
- return false;
- }
- tok = tokens [tokIdx++];
- return tok.GetTokenType() == expectedType;
- }
- bool tryPeek (out Token tok, EbnfTokenType expectedType) {
- if (EOF) {
- tok = default;
- return false;
- }
- tok = tokens [tokIdx];
- return tok.GetTokenType() == expectedType;
- }
bool resolvStackPeekIsOpenBracket =>
- resolveStack.TryPeek (out object elt) && elt is Token tok && tok.GetTokenType() == EbnfTokenType.OpenBracket;
+ resolveStack.TryPeek (out object elt) && elt is Token tok && tok.GetTokenType() == EbnfTokenType.OpenRoundBracket;
bool resolvStackPeekIsSequenceOperator =>
resolveStack.TryPeek (out object elt) && elt is Expression;
if (resolveStack.TryPeek (out object obj)) {
if (obj is Token tok) {
- if (tok.GetTokenType() == EbnfTokenType.OpenBracket)
+ if (tok.GetTokenType() == EbnfTokenType.OpenRoundBracket)
return rightOp;
resolveStack.Pop ();
resolveStack.Push (resolve (leftOp));
else
resolveStack.Push (leftOp);
- } else if (tok.GetTokenType() == EbnfTokenType.OpenBracket)
+ } else if (tok.GetTokenType() == EbnfTokenType.OpenRoundBracket)
resolveStack.Push (leftOp);
} else //so theres an expression on the stack, the operator is sequenceOp (whitespace) with precedence = 3
resolveStack.Push (resolve (leftOp));
if (!tryRead (out tok, EbnfTokenType.SymbolAffectation))
throw new EbnfParserException ($"expecing '::='");
resolveStack = new Stack<object> (16);
- } else if (Peek.GetTokenType() == EbnfTokenType.OpenBracket) {
+ } else if (Peek.GetTokenType() == EbnfTokenType.OpenRoundBracket) {
tok = Read ();
resolveStack.Push (tok);
- } else if (Peek.GetTokenType() == EbnfTokenType.ClosingBracket) {
+ } else if (Peek.GetTokenType() == EbnfTokenType.ClosingRoundBracket) {
tok = Read ();
Expression rightOp = resolve ();
while (!resolvStackPeekIsOpenBracket)
rightOp = resolve (rightOp);
- if (resolveStack.TryPop (out object obj) && obj is Token tk && tk.GetTokenType() == EbnfTokenType.OpenBracket)
+ if (resolveStack.TryPop (out object obj) && obj is Token tk && tk.GetTokenType() == EbnfTokenType.OpenRoundBracket)
checkCardinalityAndPushNewExpression (rightOp);
else
throw new EbnfParserException ($"expecing open bracket.");
} else if (Peek.GetTokenType().HasFlag (EbnfTokenType.Punctuation)) {
tok = Read ();
Expression te = default;
- if (tok.GetTokenType() == EbnfTokenType.CharMatchOpen) {
+ if (tok.GetTokenType() == EbnfTokenType.OpenBracket) {
bool negative = false;
if (tryPeek (out tok, EbnfTokenType.CharMatchNegation)) {
Read ();
List<CharRangeElement> elts = new List<CharRangeElement> ();
CharRangeElement.SingleChar leftOp = null;
while (tryRead (out tok)) {
- if (tok.GetTokenType() == EbnfTokenType.CharMatchClose) {
+ if (tok.GetTokenType() == EbnfTokenType.ClosingBracket) {
if (leftOp != null)
elts.Add (leftOp);
if (elts.Count == 0)
throw new EbnfParserException ($"malformed character range match");
}
}
- if (tok.GetTokenType() == EbnfTokenType.StringMatchOpen) {
+ if (tok.GetTokenType() == EbnfTokenType.StringDelimiter) {
if (tryRead (out tok, EbnfTokenType.StringMatch)) {
te = new StringMatch (tok.AsString (source2));
- if (!tryRead (out tok, EbnfTokenType.StringMatchClose))
+ if (!tryRead (out tok, EbnfTokenType.StringLiteral))
throw new EbnfParserException ($"malformed string match");
} else
throw new EbnfParserException ($"malformed string match");
resolveStack.Push (resolve (exp));
else
resolveStack.Push (exp);
- } else if (tok.GetTokenType() == EbnfTokenType.OpenBracket)
+ } else if (tok.GetTokenType() == EbnfTokenType.OpenRoundBracket)
resolveStack.Push (exp);
} else if (3 <= operatorPrecedance (newOp)) { //so theres an expression on the stack, the operator is sequenceOp (whitespace) with precedence = 3
resolveStack.Push (resolve (exp));
--- /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 CrowEdit.Ebnf
+{
+
+ public class EbnfRootSyntax : SyntaxRootNode {
+ public EbnfRootSyntax (EbnfDocument source)
+ : base (source) {
+ }
+ }
+ public class EbnfSyntaxNode : SyntaxNode {
+ public EbnfSyntaxNode(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+
+ public class ProductionSyntax : SyntaxNode {
+ public int? ncname, equal;
+ public ExpressionSyntax expression;
+ public ProductionSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ public ProductionSyntax(int name, int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ ncname = name;
+ }
+ public override bool IsComplete => base.IsComplete;
+ }
+ public class ExpressionSyntax : SyntaxNode {
+ public ExpressionSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) { }
+ }
+ public class LinkSyntax : ExpressionSyntax {
+ public int? openBracket, closingBracket;
+ public LinkSyntax(int openBracket, int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ this.openBracket = openBracket;
+ }
+ }
+ public class ChoiceSyntax : ExpressionSyntax {
+ public ChoiceSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+ // (Item ( '-' Item | Item* ))?
+ public class SequenceOrDifferenceSyntax : SyntaxNode {
+ public SequenceOrDifferenceSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) { }
+ }
+ // Item ::= Primary ( '?' | '*' | '+' )? */
+ public class ItemSyntax : SyntaxNode {
+ public ItemSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) { }
+ }
+ /* NCName | StringLiteral | CharCode | CharClass | '(' Choice ')' */
+ public class PrimarySyntax : SyntaxNode {
+ public PrimarySyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+ // StringLiteral ::= '"' [^"]* '"' | "'" [^']* "'"
+ public class StringLiteralSyntax : SyntaxNode {
+ public StringLiteralSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+
+ }
+ }
+ // CharCode ::= '#x' [0-9a-fA-F]+
+ public class CharCodeSyntax : SyntaxNode {
+ public CharCodeSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+ // CharClass ::= '[' '^'? ( Char | CharCode | CharRange | CharCodeRange )+ ']'
+ public class CharClassSyntax : SyntaxNode {
+ public int? closingBracket;
+ public CharClassSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {}
+ }
+ // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
+ public class CharSyntax : SyntaxNode {
+ public CharSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+
+
+}
\ No newline at end of file
SymbolName = 0x0201,
Punctuation = 0x0400,
- OpenBracket = 0x0401,
- ClosingBracket = 0x0402,
- CharMatchOpen = 0x0403,// '['
- CharMatchClose = 0x0404,// ']'
- StringMatchOpen = 0x0405,
- StringMatchClose = 0x0406,
+ OpenRoundBracket = 0x0401,
+ ClosingRoundBracket = 0x0402,
+ OpenBracket = 0x0403,// '['
+ ClosingBracket = 0x0404,// ']'
+ StringDelimiter = 0x0405,
+ StringLiteral = 0x0406,
CharMatchNegation = 0x0407,// '^'
CharMatchRangeOperator = 0x0C01,// '-'
//CharMatch = 0x0C01,// '-'
case '"':
case '\'':
char q = reader.Read();
- addTok (ref reader, EbnfTokenType.StringMatchOpen);
- if (reader.TryReadUntil (q)) {
- addTok (ref reader, EbnfTokenType.StringMatch);
- reader.Advance ();
- addTok (ref reader, EbnfTokenType.StringMatchClose);
- } else
- addTok (ref reader, EbnfTokenType.StringMatch);
+ addTok (ref reader, EbnfTokenType.StringDelimiter);
+ while (!reader.EndOfSpan) {
+ if (reader.Eol()) {
+ addTok (ref reader, EbnfTokenType.StringLiteral);
+ break;
+ } else if (reader.Peek == q) {
+ addTok (ref reader, EbnfTokenType.StringLiteral);
+ reader.Advance ();
+ addTok (ref reader, EbnfTokenType.StringDelimiter);
+ break;
+ }
+ reader.Advance();
+ }
break;
case ':':
reader.Advance();
break;
case '(':
reader.Advance();
- addTok (ref reader, EbnfTokenType.OpenBracket);
+ addTok (ref reader, EbnfTokenType.OpenRoundBracket);
break;
case ')':
reader.Advance();
- addTok (ref reader, EbnfTokenType.ClosingBracket);
+ addTok (ref reader, EbnfTokenType.ClosingRoundBracket);
break;
case '|':
reader.Advance();
break;
case '[':
reader.Advance();
- addTok (ref reader, EbnfTokenType.CharMatchOpen);
+ addTok (ref reader, EbnfTokenType.OpenBracket);
if (reader.TryPeek ('^')) {
reader.Advance();
addTok (ref reader, EbnfTokenType.CharMatchNegation);
}
- while(!reader.EndOfSpan) {
+ while(!reader.Eol()) {
char c = reader.Read ();
if (c == ']') {
- addTok (ref reader, EbnfTokenType.CharMatchClose);
+ addTok (ref reader, EbnfTokenType.ClosingBracket);
break;
} else if (c == '-')
addTok (ref reader, EbnfTokenType.CharMatchRangeOperator);
namespace CrowEdit.Ebnf
{
- public class ExpressionSyntax : SyntaxNode {
- public ExpressionSyntax(int startLine, int tokenBase)
- : base (startLine, tokenBase) {
- }
- }
- public class ProductionSyntax : SyntaxNode {
- public int? ncname, equal;
- public ExpressionSyntax expression;
- public ProductionSyntax(int startLine, int tokenBase)
- : base (startLine, tokenBase) {
- }
- public ProductionSyntax(int name, int startLine, int tokenBase)
- : base (startLine, tokenBase) {
- ncname = name;
- }
-
- }
public class SymbolDecl {
public readonly string Name;
public Expression Expression;
+++ /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 CrowEdit.Ebnf
-{
-
- public class EbnfRootSyntax : SyntaxRootNode {
- public EbnfRootSyntax (EbnfDocument source)
- : base (source) {
- }
- }
- public class ConstantDefinitionSyntax : SyntaxNode {
- internal int? name, equal, valueOpen, valueClose;
- public override bool IsComplete => base.IsComplete & name.HasValue & equal.HasValue &
- valueOpen.HasValue & valueClose.HasValue;
- public ConstantDefinitionSyntax (int startLine, int tokenBase)
- : base (startLine, tokenBase) {
- }
- }
- 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
<?xml version="1.0"?>
-<DockWindow Caption="Netcore Debugger" Width="Fit" Height="Fit" Resizable="false" >
- <HorizontalStack Fit="true" DataSource="{DbgSession}" Margin="0" Spacing="5">
- <Button Style="IcoBut" Command="{CMDDebugStart}"/>
- <Button Style="IcoBut" Command="{CMDDebugPause}"/>
- <Button Style="IcoBut" Command="{CMDDebugStop}"/>
- <Button Style="IcoBut" Command="{CMDDebugStepIn}"/>
- <Button Style="IcoBut" Command="{CMDDebugStepOut}"/>
- <Button Style="IcoBut" Command="{CMDDebugStepOver}"/>
+<DockWindow Caption="Netcore Debugger">
+ <HorizontalStack Height="Fit" DataSource="{DbgSession}" Margin="0" Spacing="5">
+ <ListBox Data="{DebugCommands}" Fit="true">
+ <Template>
+ <HorizontalStack Name="ItemsContainer" Spacing="5" />
+ </Template>
+ <ItemTemplate>
+ <Button Command="{}" MinimumSize="1,1" Width="40" Height="40" Background="vgradient|0:DimGrey|1:Black" CornerRadius="0" >
+ <Template>
+ <Border Style="ButtonBorder" Width="Stretched" Height="Stretched" Margin="10" Background="{./Background}" CornerRadius="{../CornerRadius}">
+ <Image Path="{./Icon}" Tooltip="{./Caption}" Scaled="true" KeepProportions="true" Margin="0"/>
+ </Border>
+ </Template>
+ </Button>
+ </ItemTemplate>
+ </ListBox >
<Label Text="{CurrentState}" Margin="2"/>
</HorizontalStack>
</DockWindow>
}
public class CSSyntaxAnalyser : SyntaxAnalyser {
public override SyntaxNode Root => currentNode;
+ /*protected override void Parse(SyntaxNode node)
+ {
+ throw new NotImplementedException();
+ }*/
+
public CSSyntaxAnalyser (CSDocument source) : base (source) {
this.source = source;
}
public override void Process () {
- Exceptions = new List<SyntaxException> ();
currentNode = new CSRootSyntax (source);
}
}
+++ /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 CrowEdit.Xml
-{
- public class XmlSyntaxAnalyser : SyntaxAnalyser {
- public override SyntaxNode Root => currentNode;
- public XmlSyntaxAnalyser (XmlDocument source) : base (source) {
- this.source = source;
- }
-
- /*public virtual SyntaxNode Process (SyntaxNode startingNode) {
-
- }*/
- public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
- attrib.valueTok = tokIdx - attrib.TokenIndexBase;
- }
- public override void Process () {
- XmlDocument xmlDoc = source as XmlDocument;
- Exceptions = new List<SyntaxException> ();
- currentNode = new XMLRootSyntax (xmlDoc);
- currentLine = 0;
- Span<Token> toks = source.Tokens;
- tokIdx = 0;
-
- while (tokIdx < toks.Length) {
- 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 = 0;
- currentNode = currentNode.AddChild (attribute);
- } else if (curTok.GetTokenType() == XmlTokenType.ElementName)
- tag.name = tokIdx - tag.TokenIndexBase;
- else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
- tag.close = tokIdx - tag.TokenIndexBase;
- storeCurrentNode ();
- currentNode.RemoveChild (tag);
- currentNode = currentNode.AddChild (new ElementSyntax (tag));
- } else if (curTok.GetTokenType() == XmlTokenType.EmptyElementClosing) {
- storeCurrentNode ();
- currentNode.RemoveChild (tag);
- currentNode = currentNode.AddChild (new EmptyElementSyntax (tag));
- setCurrentNodeEndLine (currentLine);
- currentNode = currentNode.Parent;
- } else {
- Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
- storeCurrentNode (-1);
- continue;
- }
- } else if (currentNode is ElementSyntax elt) {
- if (curTok.GetTokenType() == XmlTokenType.ElementOpen)
- currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
- else if (curTok.GetTokenType() == XmlTokenType.EndElementOpen) {
- elt.EndTag = new ElementEndTagSyntax (currentLine, tokIdx);
- currentNode = elt.AddChild (elt.EndTag);
- }
- } else if (currentNode is AttributeSyntax attrib) {
- if (curTok.GetTokenType() == XmlTokenType.EqualSign)
- if (attrib.equal.HasValue)
- Exceptions.Add (new SyntaxException ("Extra equal sign in attribute syntax", curTok));
- else
- attrib.equal = tokIdx - attrib.TokenIndexBase;
- else if (curTok.GetTokenType() == XmlTokenType.AttributeValueOpen)
- attrib.valueOpen = tokIdx - attrib.TokenIndexBase;
- else if (curTok.GetTokenType() == XmlTokenType.AttributeValue)
- ProcessAttributeValueSyntax (attrib);
- else if (curTok.GetTokenType() == XmlTokenType.AttributeValueClose) {
- attrib.valueClose = tokIdx - attrib.TokenIndexBase;
- storeCurrentNode ();
- } else {
- Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
- storeCurrentNode (-1);
- continue;
- }
- } else if (currentNode is ElementEndTagSyntax eltEndTag) {
- if (curTok.GetTokenType() == XmlTokenType.ElementName)
- eltEndTag.name = tokIdx - eltEndTag.TokenIndexBase;
- else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
- eltEndTag.close = tokIdx - eltEndTag.TokenIndexBase;
- //go up 2 times
- storeCurrentNode (); storeCurrentNode ();
- } else {
- Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
- storeCurrentNode (-1);
- storeCurrentNode (-1);
- continue;
- }
- } else if (currentNode is XMLRootSyntax) {
- switch (curTok.GetTokenType()) {
- case XmlTokenType.ElementOpen:
- currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
- break;
- case XmlTokenType.PI_Start:
- currentNode = currentNode.AddChild (new ProcessingInstructionSyntax (currentLine, tokIdx));
- break;
- default:
- Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
- break;
- }
- } else if (currentNode is ProcessingInstructionSyntax pi) {
- if (curTok.GetTokenType() == XmlTokenType.PI_Target)
- pi.name = tokIdx - pi.TokenIndexBase;
- else if (curTok.GetTokenType() == XmlTokenType.PI_End) {
- pi.PIClose = tokIdx - pi.TokenIndexBase;
- storeCurrentNode ();
- } else if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
- AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
- attribute.name = 0;
- currentNode = currentNode.AddChild (attribute);
- } else {
- Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
- storeCurrentNode (-1);
- continue;
- }
- }
- }
- tokIdx++;
- }
- 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.Linq;
-using Crow.Text;
-using CrowEditBase;
-
-namespace CrowEdit.Xml
-{
-
- public class XMLRootSyntax : SyntaxRootNode {
- public XMLRootSyntax (XmlDocument source)
- : base (source) {
- }
- }
- public class ProcessingInstructionSyntax : SyntaxNode {
- public int? PIClose, name;
- public override bool IsComplete => base.IsComplete & name.HasValue & PIClose.HasValue;
- public ProcessingInstructionSyntax (int startLine, int tokenBase)
- : base (startLine, tokenBase) {
- }
- }
-
- public abstract class ElementTagSyntax : SyntaxNode {
- public 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 ElementStartTagSyntax : ElementTagSyntax {
- public ElementStartTagSyntax (int startLine, int tokenBase)
- : base (startLine, tokenBase) {
- }
- }
- public class ElementEndTagSyntax : ElementTagSyntax {
- public ElementEndTagSyntax (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.LastTokenIndex) {
- StartTag = startNode;
- AddChild (StartTag);
- }
- }
-
- public class ElementSyntax : SyntaxNode {
- public readonly ElementStartTagSyntax StartTag;
- public ElementEndTagSyntax EndTag { get; set; }
-
- public override bool IsComplete => base.IsComplete & StartTag.IsComplete & (EndTag != null && EndTag.IsComplete);
-
- public ElementSyntax (ElementStartTagSyntax startTag)
- : base (startTag.StartLine, startTag.TokenIndexBase) {
- StartTag = startTag;
- AddChild (StartTag);
- }
- }
-
- public class AttributeSyntax : SyntaxNode {
- public int? name, equal, valueOpen, valueClose, valueTok;
- 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;
- }
-}
\ No newline at end of file
using System.Collections;
using CrowEditBase;
using Drawing2D;
+using System.Collections.Generic;
namespace CrowEdit.Xml
{
}
protected override Tokenizer CreateTokenizer() => new XmlTokenizer ();
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new XmlSyntaxAnalyser (this);
-
+ public override string GetTokenTypeString (TokenType tokenType) => ((XmlTokenType)tokenType).ToString();
public override IList GetSuggestions (CharLocation loc) {
/*currentToken = FindTokenIncludingPosition (pos);
currentNode = FindNodeIncludingPosition (pos);*/
+ if (currentToken.GetTokenType() == XmlTokenType.EndElementOpen &&
+ CurrentNode is ElementEndTagSyntax eltEndTag && !eltEndTag.IsComplete) {
+ ElementSyntax es = eltEndTag.Parent as ElementSyntax;
+ if (es?.StartTag.name != null)
+ return new List<string> (new string[] {tokens[es.StartTag.name.Value].AsString(Source)});
+ }
return null;
}
public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
if (selectedSugg == null)
return false;
- if (currentToken.GetTokenType() == XmlTokenType.ElementOpen ||
+ Token tok = CurrentToken;
+ XmlTokenType tokType = tok.GetTokenType();
+
+ if (tokType.HasFlag(XmlTokenType.WhiteSpace)) {
+ if (typeof(ElementTagSyntax).IsAssignableFrom(CurrentNode?.GetType())) {
+ ElementTagSyntax ets = CurrentNode as ElementTagSyntax;
+ if (ets.name.HasValue) {
+ change = new TextChange (currentToken.End, 0, selectedSugg + "=\"\"");
+ newSelection = TextSpan.FromStartAndLength(change.End2 - 1);
+ } else
+ change = new TextChange (currentToken.End, 0, selectedSugg + " ");
+ } else {
+ change = new TextChange (currentToken.End, 0, selectedSugg);
+ }
+ } else if (tokType == XmlTokenType.EndElementOpen) {
+ change = new TextChange (currentToken.End, 0, selectedSugg + ">");
+ } else if (tokType == XmlTokenType.ElementName) {
+ if (CurrentNode is ElementEndTagSyntax)
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + ">");
+ else {
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + ">");
+ newSelection = TextSpan.FromStartAndLength (change.End2 - 1);
+ }
+ } else if (CurrentNode is AttributeSyntax attrib) {
+ if (tokType == XmlTokenType.AttributeName) {
+ 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 {
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"");
+ newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
+ }
+ } else {
+ int offset = 1;
+ if (!attrib.valueClose.HasValue) {
+ selectedSugg += tokens[attrib.valueClose.Value].AsString(Source);
+ offset = 0;
+ }
+ if (tokType == XmlTokenType.AttributeValueOpen)
+ change = new TextChange (currentToken.End, 0, selectedSugg);
+ else if (tokType == XmlTokenType.AttributeValue)
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+ newSelection = TextSpan.FromStartAndLength (change.End2 + offset);
+ }
+ } else if (tokType == XmlTokenType.ElementOpen) {
+ change = new TextChange (currentToken.End, 0, selectedSugg + " ");
+ } else
+ change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
+
+ return true;
+/***********************************************/
+
+ /*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 (currentToken.GetTokenType() == XmlTokenType.AttributeName && CurrentNode is AttributeSyntax attrib) {
if (attrib.ValueToken.HasValue) {
change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
newSelection = new TextSpan(
attrib.ValueToken.Value.End + change.CharDiff - 1
);
} else {
- newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"");
+ newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2);
}
return true;
}
change = new TextChange (currentToken.Start, currentToken.Length, selectedSugg);
- return true;
+ return true;*/
}
public override Color GetColorForToken(TokenType tokType)
return Colors.Red;
}
+ protected bool previousTokHasFlag(XmlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
}
}
\ 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 CrowEdit.Xml
+{
+ public class XmlSyntaxAnalyser : SyntaxAnalyser {
+ public override SyntaxNode Root => currentNode;
+ /*protected override void Parse(SyntaxNode node)
+ {
+ throw new NotImplementedException();
+ }*/
+ public XmlSyntaxAnalyser (XmlDocument source) : base (source) {
+ this.source = source;
+ }
+
+ /*public virtual SyntaxNode Process (SyntaxNode startingNode) {
+
+ }*/
+ public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
+ attrib.valueTok = tokIdx - attrib.TokenIndexBase;
+ }
+ public override void Process () {
+ XmlDocument xmlDoc = source as XmlDocument;
+ currentNode = new XMLRootSyntax (xmlDoc);
+ currentLine = 0;
+ tokIdx = 0;
+ tokens = source.Tokens;
+
+ while (tokIdx < tokens.Length) {
+ 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 = 0;
+ currentNode = currentNode.AddChild (attribute);
+ } else if (curTok.GetTokenType() == XmlTokenType.ElementName)
+ tag.name = tokIdx - tag.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
+ tag.close = tokIdx - tag.TokenIndexBase;
+ setEndLineForCurrentNode ();
+ currentNode.RemoveChild (tag);
+ currentNode = currentNode.AddChild (new ElementSyntax (tag));
+ } else if (curTok.GetTokenType() == XmlTokenType.EmptyElementClosing) {
+ setEndLineForCurrentNode ();
+ currentNode.RemoveChild (tag);
+ currentNode = currentNode.AddChild (new EmptyElementSyntax (tag));
+ setCurrentNodeEndLine (currentLine);
+ currentNode = currentNode.Parent;
+ } else {
+ addException ("Unexpected Token");
+ setEndLineForCurrentNode (-1);
+ continue;
+ }
+ } else if (currentNode is ElementSyntax elt) {
+ if (curTok.GetTokenType() == XmlTokenType.ElementOpen)
+ currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
+ else if (curTok.GetTokenType() == XmlTokenType.EndElementOpen) {
+ elt.EndTag = new ElementEndTagSyntax (currentLine, tokIdx);
+ currentNode = elt.AddChild (elt.EndTag);
+ }
+ } else if (currentNode is AttributeSyntax attrib) {
+ if (curTok.GetTokenType() == XmlTokenType.EqualSign)
+ if (attrib.equal.HasValue)
+ addException ("Extra equal sign in attribute syntax");
+ else
+ attrib.equal = tokIdx - attrib.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.AttributeValueOpen)
+ attrib.valueOpen = tokIdx - attrib.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.AttributeValue)
+ ProcessAttributeValueSyntax (attrib);
+ else if (curTok.GetTokenType() == XmlTokenType.AttributeValueClose) {
+ attrib.valueClose = tokIdx - attrib.TokenIndexBase;
+ setEndLineForCurrentNode ();
+ } else {
+ addException ("Unexpected Token");
+ setEndLineForCurrentNode (-1);
+ continue;
+ }
+ } else if (currentNode is ElementEndTagSyntax eltEndTag) {
+ if (curTok.GetTokenType() == XmlTokenType.ElementName)
+ eltEndTag.name = tokIdx - eltEndTag.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
+ eltEndTag.close = tokIdx - eltEndTag.TokenIndexBase;
+ //go up 2 times
+ setEndLineForCurrentNode (); setEndLineForCurrentNode ();
+ } else {
+ addException ("Unexpected Token");
+ setEndLineForCurrentNode (-1);
+ setEndLineForCurrentNode (-1);
+ continue;
+ }
+ } else if (currentNode is XMLRootSyntax) {
+ switch (curTok.GetTokenType()) {
+ case XmlTokenType.ElementOpen:
+ currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
+ break;
+ case XmlTokenType.PI_Start:
+ currentNode = currentNode.AddChild (new ProcessingInstructionSyntax (currentLine, tokIdx));
+ break;
+ default:
+ addException ("Unexpected Token");
+ break;
+ }
+ } else if (currentNode is ProcessingInstructionSyntax pi) {
+ if (curTok.GetTokenType() == XmlTokenType.PI_Target)
+ pi.name = tokIdx - pi.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.PI_End) {
+ pi.PIClose = tokIdx - pi.TokenIndexBase;
+ setEndLineForCurrentNode ();
+ } else if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
+ AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
+ attribute.name = 0;
+ currentNode = currentNode.AddChild (attribute);
+ } else {
+ addException ("Unexpected Token");
+ setEndLineForCurrentNode (-1);
+ continue;
+ }
+ }
+ }
+ tokIdx++;
+ }
+ while (currentNode.Parent != null) {
+ if (!currentNode.TokenCount.HasValue)
+ setEndLineForCurrentNode (-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.Linq;
+using Crow.Text;
+using CrowEditBase;
+
+namespace CrowEdit.Xml
+{
+
+ public class XMLRootSyntax : SyntaxRootNode {
+ public XMLRootSyntax (XmlDocument source)
+ : base (source) {
+ }
+ }
+ public class ProcessingInstructionSyntax : SyntaxNode {
+ public int? PIClose, name;
+ public override bool IsComplete => base.IsComplete & name.HasValue & PIClose.HasValue;
+ public ProcessingInstructionSyntax (int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+
+ public abstract class ElementTagSyntax : SyntaxNode {
+ public 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 ElementStartTagSyntax : ElementTagSyntax {
+ public ElementStartTagSyntax (int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+ public class ElementEndTagSyntax : ElementTagSyntax {
+ public ElementEndTagSyntax (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.LastTokenIndex) {
+ StartTag = startNode;
+ AddChild (StartTag);
+ }
+ public override bool IsComplete => base.IsComplete && StartTag != null;
+ }
+
+ public class ElementSyntax : SyntaxNode {
+ public readonly ElementStartTagSyntax StartTag;
+ public ElementEndTagSyntax EndTag { get; set; }
+
+ public override bool IsComplete => base.IsComplete & StartTag.IsComplete & (EndTag != null && EndTag.IsComplete);
+
+ public ElementSyntax (ElementStartTagSyntax startTag)
+ : base (startTag.StartLine, startTag.TokenIndexBase) {
+ StartTag = startTag;
+ AddChild (StartTag);
+ }
+ }
+
+ public class AttributeSyntax : SyntaxNode {
+ public int? name, equal, valueOpen, valueClose, valueTok;
+ 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;
+ }
+}
\ No newline at end of file
saveLogsConfig ();
saveWinConfigs ();
}
- DockStack mainDock;
+
public Command CMDSave, CMDSaveAs, CMDQuit, CMDHelp, CMDAbout, CMDOptions;
void initCommands (){
CrowEdit e = w.IFace as CrowEdit;
e.LoadWindow (path, e);
}
- void saveWinConfigs() {
- Configuration.Global.Set ("WinConfigs", mainDock.ExportConfig ());
-
- StringBuilder floatings = new StringBuilder (512);
- DockWindow[] floatingWins = GraphicTree.OfType<DockWindow> ().ToArray ();
- if (floatingWins.Length > 0) {
- for (int i = 0; i < floatingWins.Length - 1; i++) {
- floatings.Append (floatingWins[i].FloatingConfigString);
- floatings.Append ('|');
- }
- floatings.Append (floatingWins[floatingWins.Length - 1].FloatingConfigString);
- }
- Configuration.Global.Set ("FloatingWinConfigs", floatings.ToString ());
-
- Configuration.Global.Save ();
- }
- void reloadWinConfigs() {
-
- if (Configuration.Global.TryGet<string>("WinConfigs", out string conf) && !string.IsNullOrEmpty(conf))
- mainDock.ImportConfig (conf, this);
- if (Configuration.Global.TryGet<string>("FloatingWinConfigs", out conf) && !string.IsNullOrEmpty(conf)) {
- string[] floatings = conf.Split ('|');
- for (int i = 0; i < floatings.Length; i++)
- DockWindow.CreateFromFloatingConfigString (this, floatings[i], this);
- }
- }
- void reloadLogsConfigs() {
-
- if (Configuration.Global.TryGet<string>("OpenedLogs", out string conf) && !string.IsNullOrEmpty(conf)) {
- string[] logs = conf.Split ('|');
- for (int i = 0; i < logs.Length; i++)
- App.GetLog(logs[i]).IsOpened = true;
- if (Configuration.Global.TryGet<string>("CurrentLog", out string curLog) && !string.IsNullOrEmpty(curLog))
- App.GetLog(curLog).IsSelected = true;
- }
- }
- void saveLogsConfig() {
- lock (OpenedLogs) {
- string openLogs = OpenedLogs.Count > 0 ?
- OpenedLogs.Select(li=>li.Name).Aggregate((a,b) => a + "|" + b) : null;
- Configuration.Global.Set("OpenedLogs", openLogs);
- Configuration.Global.Set("CurrentLog", CurrentLog?.Name);
- }
- }
+
protected override Document openOrCreateFile (string filePath, string editorPath = null) {
Document doc = null;
<?xml version="1.0"?>
-<DockWindow Caption="Editor" Width="60%">
+<DockWindow Caption="Editor" Width="50%" Height="80%">
<TabView ItemTemplate="{EditorItemTemplates}"
Data="{OpenedDocuments}" SelectedItem="{²CurrentDocument}" DataTest="EditorPath">
<Template>
<?xml version="1.0"?>
-<DockWindow Caption="Explorer" Width="60%">
+<DockWindow Caption="Explorer" Width="30%" Height="80%">
<VerticalStack Spacing="0">
<HorizontalStack Height="Fit" Spacing="0" Margin="2" >
<Image Margin="2" Width="16" Height="16" Path="#Crow.Icons.level-up.svg" MouseClick="goUpDirClick"
<?xml version="1.0"?>
-<DockWindow Style="DockWindow" Caption="Logs" Width="80%" >
+<DockWindow Style="DockWindow" Caption="Logs" Width="80%" Height="20%" >
<VerticalStack>
<TabView Data="{OpenedLogs}" SelectedItem="{²CurrentLog}">
<?xml version="1.0"?>
-<DockWindow Caption="Project" Width="60%" >
+<DockWindow Caption="Project" Width="30%" Height="60%" >
<!--<ListBox RootDataLevel="true" Data="{Projects}" SelectedItem="{²CurrentProject}">
<ItemTemplate>
<HorizontalStack Height="Fit">
</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"/>
- <VerticalStack Height="Fit" Name="ItemsContainer"/>
- </HorizontalStack>
- <Template>
- <VerticalStack>
- <ListItem BubbleEvents="All"
- MouseDoubleClick="./onClickForExpand"
- Selected="{/border.Background=${ControlHighlight}}"
- Unselected="{/border.Background=${TreeItemBackground}}"
- MouseEnter="{/border.Foreground=${TreeItemBorderHighlightFG}}"
- MouseLeave="{/border.Foreground=${TreeItemBorderFG}}">
- <Border Name="border" Margin="2" CornerRadius="${TreeItemBorderCornerRadius}"
- Background="${TreeItemBackground}" Foreground="${TreeItemBorderFG}">
- <HorizontalStack Spacing="5">
- <Image Margin="1" Width="9" Height="9" Focusable="true" MouseClick="./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>
- </ListItem>
- <Container Name="Content" Visible="false"/>
- </VerticalStack>
- </Template>
- </Expandable>
- </ItemTemplate>-->
</TreeView>
</VerticalStack>
</DockWindow>