</EmbeddedResource>
</ItemGroup>
<ItemGroup>
- <!--<ProjectReference Include="/mnt/devel/crow/Crow/Crow.csproj" />-->
- <PackageReference Include="Crow" Version="0.9.7-beta" />
+ <ProjectReference Include="/mnt/devel/crow/Crow/Crow.csproj" />
+ <!--<PackageReference Include="Crow" Version="0.9.7-beta" />-->
</ItemGroup>
</Project>
}
protected Token[] tokens;
protected SyntaxNode RootNode;
+ protected LineCollection lines;
protected Token currentToken;
protected SyntaxNode currentNode;
public Token[] Tokens => tokens;
+ public SyntaxNode SyntaxRootNode => RootNode;
+ public LineCollection Lines => lines;
public Token FindTokenIncludingPosition (int pos) {
if (pos == 0 || tokens == null || tokens.Length == 0)
return default;
return idx == 0 ? tokens[0] : idx < 0 ? tokens[~idx - 1] : tokens[idx - 1];
}
- public SyntaxNode FindNodeIncludingPosition (int pos) {
+ public int FindTokenIndexIncludingPosition (int pos) {
+ if (pos == 0 || tokens == null || tokens.Length == 0)
+ return default;
+ int idx = Array.BinarySearch (tokens, 0, tokens.Length, new Token () {Start = pos});
+
+ return idx == 0 ? 0 : idx < 0 ? ~idx - 1 : idx - 1;
+ }
+ /// <summary>
+ /// if outermost is true, return oldest ancestor exept root node, useful for folding.
+ /// </summary>
+ public SyntaxNode FindNodeIncludingPosition (int pos, bool outerMost = false) {
if (RootNode == null)
return null;
if (!RootNode.Contains (pos))
return null;
- return RootNode.FindNodeIncludingPosition (pos);
+ SyntaxNode sn = RootNode.FindNodeIncludingPosition (pos);
+ if (outerMost) {
+ while (sn.Parent != RootNode && sn.StartToken.Start == sn.Parent.StartToken.Start)
+ sn = sn.Parent;
+ }
+ return sn;
}
public T FindNodeIncludingPosition<T> (int pos) {
if (RootNode == null)
tokens = tokenizer.Tokenize (Source);
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
- Stopwatch sw = Stopwatch.StartNew ();
+ //Stopwatch sw = Stopwatch.StartNew ();
syntaxAnalyser.Process ();
- sw.Stop();
+ //sw.Stop();
RootNode = syntaxAnalyser.Root;
- Console.WriteLine ($"Syntax Analysis done in {sw.ElapsedMilliseconds}(ms) {sw.ElapsedTicks}(ticks)");
+ /*Console.WriteLine ($"Syntax Analysis done in {sw.ElapsedMilliseconds}(ms) {sw.ElapsedTicks}(ticks)");
foreach (SyntaxException ex in syntaxAnalyser.Exceptions)
- Console.WriteLine ($"{ex}");
+ Console.WriteLine ($"{ex}");*/
/*foreach (Token t in Tokens)
Console.WriteLine ($"{t,-40} {Source.AsSpan(t.Start, t.Length).ToString()}");
this.source = source;
}
public abstract void Process ();
+ protected SyntaxNode currentNode;
+
+ /// <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 (Token endToken, int endLine) {
+ currentNode.EndToken = endToken;
+ currentNode.EndLine = endLine;
+ currentNode = currentNode.Parent;
+ }
+ protected void setCurrentNodeEndLine (int endLine)
+ => currentNode.EndLine = endLine;
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
+using Crow.Text;
namespace CrowEditBase
{
+ public abstract class SyntaxRootNode : SyntaxNode {
+ protected readonly SourceDocument source;
+ public SyntaxRootNode (SourceDocument source)
+ : base (0, source.Tokens.FirstOrDefault (), source.Tokens.LastOrDefault ()) {
+ this.source = source;
+ }
+ public override SyntaxRootNode Root => this;
+ public override bool IsFoldable => false;
+ public override SyntaxNode NextSiblingOrParentsNextSibling => null;
+ }
public class SyntaxNode {
public SyntaxNode Parent { get; private set; }
+ public int StartLine { get; private set; }
+ public virtual int LineCount => lineCount;
+ public virtual bool IsComplete => EndToken.HasValue;
+ public virtual bool IsFoldable => Parent.StartLine != StartLine && lineCount > 1;
+ public virtual SyntaxRootNode Root => Parent.Root;
+
+
List<SyntaxNode> children = new List<SyntaxNode> ();
+ public IEnumerable<SyntaxNode> Children => children;
+ public bool HasChilds => children.Count > 0;
+ public SyntaxNode NextSibling {
+ get {
+ if (Parent != null) {
+ int idx = Parent.children.IndexOf (this);
+ if (idx < Parent.children.Count - 1)
+ return Parent.children[idx + 1];
+ }
+ return null;
+ }
+ }
+ public SyntaxNode PreviousSibling {
+ get {
+ if (Parent != null) {
+ int idx = Parent.children.IndexOf (this);
+ if (idx > 0)
+ return Parent.children[idx - 1];
+ }
+ return null;
+ }
+ }
+ /*public virtual int lineCount2 {
+ get {
+ SyntaxNode ns = NextSibling;
+ if (ns == null)
+ return Parent.StartLine + Parent.lineCount2 - StartLine;
+ return ns.StartLine - StartLine;
+ }
+ }*/
+ /*public virtual int FoldedLineCount {
+ get {
+
+ }
+ }*/
+ public virtual SyntaxNode NextSiblingOrParentsNextSibling
+ => NextSibling ?? Parent.NextSiblingOrParentsNextSibling;
+ public IEnumerable<SyntaxNode> FoldableNodes {
+ get {
+ if (IsFoldable)
+ yield return this;
+ foreach (SyntaxNode n in Children) {
+ foreach (SyntaxNode folds in n.FoldableNodes)
+ yield return folds;
+ }
+ }
+ }
+ public virtual int FoldedLineCount {
+ get {
+ if (isFolded)
+ return lineCount;
+ int tmp = 0;
+ if (HasChilds) {
+ foreach (SyntaxNode n in children.Where (c => c.IsFoldable))
+ tmp += n.FoldedLineCount;
+ }
+ return tmp;
+ }
+ }
public readonly Token StartToken;
public Token? EndToken { get; set; }
- public SyntaxNode (Token tokStart, Token? tokEnd = null) {
+ public SyntaxNode (int startLine, Token tokStart, Token? tokEnd = null) {
+ StartLine = startLine;
StartToken = tokStart;
EndToken = tokEnd;
}
+ internal bool isFolded;
+ internal int lineCount;
+ public int EndLine {
+ internal set {
+ lineCount = value - StartLine + 1;
+ }
+ get => StartLine + lineCount - 1;
+ }
+ public TextSpan Span {
+ get {
+ /*if (HasChilds) {
+ return new TextSpan (children.First().Span.Start, children.Last().Span.End)
+ }*/
+ return new TextSpan (StartToken.Start, EndToken.HasValue ? EndToken.Value.End : StartToken.End);
- public virtual bool IsComplete => EndToken.HasValue;
-
+ }
+ }
public SyntaxNode AddChild (SyntaxNode child) {
children.Add (child);
child.Parent = this;
return this is T tt ? tt : default;
}
- public virtual SyntaxNode Root => Parent.Root;
public bool Contains (int pos) =>
EndToken.HasValue ?
StartToken.Start <= pos && EndToken.Value.End >= pos : false;
-
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}: {StartToken} -> {EndToken}";
+ public override string ToString() => $"{this.GetType().Name}: lines:({StartLine},{LineCount}) tokens:{StartToken} -> {EndToken}";
}
}
\ No newline at end of file
Type = type;
Start = start;
Length = length;
- }
+ }
public int CompareTo([AllowNull] Token other)
=> Start - other.Start;
public bool Equals([AllowNull] Token other)
=> Type == other.Type && Start == other.Start && Length == other.Length;
- public override bool Equals(object obj)
+ public override bool Equals(object obj)
=> obj is Token other ? Equals (other) : false;
public override int GetHashCode() => HashCode.Combine (Type, Start, Length);
public override string ToString() => $"{Type}:{Start},{Length};";
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
+using System.Collections.Generic;
+using Crow.Text;
namespace CrowEditBase
{
}
}
public abstract class Tokenizer {
+ protected List<Token> Toks;
+ protected int startOfTok;
public Tokenizer () {}
public abstract Token[] Tokenize (string source);
+ /// <summary>
+ /// First method to call in tokenizers to init parsing variables
+ /// </summary>
+ /// <returns></returns>
+ protected virtual SpanCharReader initParsing (string source) {
+ startOfTok = 0;
+ Toks = new List<Token>(100);
+ return new SpanCharReader(source);
+ }
+ /// <summary>
+ /// Add token delimited from 'startOfTok' to current reader position.
+ /// </summary>
+ /// <param name="reader"></param>
+ /// <param name="tokType"></param>
+ protected void addTok (ref SpanCharReader reader, Enum tokType) {
+ if (reader.CurrentPosition == startOfTok)
+ return;
+ Toks.Add (new Token((TokenType)tokType, startOfTok, reader.CurrentPosition));
+ startOfTok = reader.CurrentPosition;
+ }
+ protected virtual void skipWhiteSpaces (ref SpanCharReader reader) {
+ while(!reader.EndOfSpan) {
+ switch (reader.Peak) {
+ case '\x85':
+ case '\x2028':
+ case '\xA':
+ reader.Read();
+ addTok (ref reader, TokenType.LineBreak);
+ break;
+ case '\xD':
+ reader.Read();
+ if (reader.IsNextCharIn ('\xA', '\x85'))
+ reader.Read();
+ addTok (ref reader, TokenType.LineBreak);
+ break;
+ case '\x20':
+ case '\x9':
+ char c = reader.Read();
+ while (reader.TryPeak (c))
+ reader.Read();
+ addTok (ref reader, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
}
}
NotifyValueChanged ("CurrentColumn", CurrentColumn);
CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
- }
- }
+ }
+ }
public virtual int CurrentLine {
get => currentLoc.HasValue ? currentLoc.Value.Line : 0;
set {
CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
}
- }
+ }
public virtual int CurrentColumn {
get => currentLoc.HasValue ? currentLoc.Value.Column < 0 ? 0 : currentLoc.Value.Column : 0;
set {
if (loc.Line == 0)
return false;
CurrentLoc = new CharLocation (loc.Line - 1, lines[loc.Line - 1].Length);
- }else
+ }else
CurrentLoc = new CharLocation (loc.Line, loc.Column - 1);
return true;
}
CurrentLoc = new CharLocation (newLine, targetColumn);
return true;
- }
+ }
protected int visibleLines => (int)((double)ClientRectangle.Height / (fe.Ascent + fe.Descent));
public void GotoWordStart(){
int pos = lines.GetAbsolutePosition (CurrentLoc.Value);
if (lines.Count == 0 || lines[0].LineBreakLength == 0) {
LineBreak = Environment.NewLine;
return;
- }
+ }
LineBreak = _text.GetLineBreak (lines[0]).ToString ();
for (int i = 1; i < lines.Count; i++) {
if (!lb.SequenceEqual (LineBreak)) {
mixedLineBreak = true;
break;
- }
+ }
}
- }
+ }
protected void getLines () {
if (lines == null)
}
return new TextSpan (lines.GetAbsolutePosition (selStart), lines.GetAbsolutePosition (selEnd));
}
- }
+ }
public string SelectedText {
get {
TextSpan selection = Selection;
return selection.IsEmpty ? "" : _text.AsSpan (selection.Start, selection.Length).ToString ();
}
- }
+ }
public bool SelectionIsEmpty => selectionStart.HasValue ? Selection.IsEmpty : true;
+ protected virtual int lineCount => lines.Count;
+
protected virtual void measureTextBounds (Context gr) {
fe = gr.FontExtents;
te = new TextExtents ();
- cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent + fe.Descent) * Math.Max (1, lines.Count));
+ cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent + fe.Descent) * Math.Max (1, lineCount));
TextExtents tmp = default;
int longestLine = 0;
gr.Translate (ScrollX, ScrollY);
}
+ protected int getLineIndex (Point mouseLocalPos) =>
+ (int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ (fe.Ascent + fe.Descent))), lines.Count - 1);
+ protected int getVisualLineIndex (Point mouseLocalPos) =>
+ (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent + fe.Descent))), visibleLines - 1);
+
protected virtual void updateHoverLocation (Point mouseLocalPos) {
- int hoverLine = (int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ (fe.Ascent + fe.Descent))), lines.Count - 1);
- int scrollLine = (int)Math.Ceiling((double)ScrollY / (fe.Ascent + fe.Descent));
- /*if (hoverLine > scrollLine + visibleLines)
- ScrollY = (int)((double)(hoverLine - visibleLines) * (fe.Ascent + fe.Descent));*/
+ int hoverLine = getLineIndex (mouseLocalPos);
NotifyValueChanged("MouseY", mouseLocalPos.Y + ScrollY);
NotifyValueChanged("ScrollY", ScrollY);
NotifyValueChanged("VisibleLines", visibleLines);
NotifyValueChanged("HoverLine", hoverLine);
- NotifyValueChanged("ScrollLine", hoverLine);
hoverLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X + ScrollX);
using (Context gr = new Context (IFace.surf)) {
setFontForContext (gr);
}
protected virtual bool cancelLinePrint (double lineHeght, double y, int clientHeight) => false;
RectangleD? textCursor = null;
+ protected virtual int visualCurrentLine => CurrentLoc.Value.Line;
+
public virtual bool DrawCursor (Context ctx, out Rectangle rect) {
if (CurrentLoc == null) {
rect = default;
}
- int lineHeight = (int)(fe.Ascent + fe.Descent);
- textCursor = computeTextCursor (new RectangleD (CurrentLoc.Value.VisualCharXPosition, CurrentLoc.Value.Line * lineHeight, 1.0, lineHeight));
+ double lineHeight = fe.Ascent + fe.Descent;
+ textCursor = computeTextCursor (new RectangleD (CurrentLoc.Value.VisualCharXPosition, lineHeight * visualCurrentLine, 1.0, lineHeight));
if (textCursor == null) {
rect = default;
//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}");
+ System.Diagnostics.Debug.WriteLine ($"loc.Column: {loc.Column} curLine.Length:{curLine.Length}");
loc.Column = curLine.Length;
}
#endif
if (!textMeasureIsUpToDate) {
lock (linesMutex)
measureTextBounds (gr);
- }
+ }
if (ClipToClientRect) {
gr.Save ();
base.onUnfocused (sender, e);
RegisterForRedraw ();
}*/
- public override void onMouseEnter (object sender, MouseMoveEventArgs e) {
- base.onMouseEnter (sender, e);
+ public override void onMouseEnter (object sender, MouseMoveEventArgs e) {
+ base.onMouseEnter (sender, e);
+ if (!Focusable)
+ return;
HasFocus = true;
- if (Focusable)
- IFace.MouseCursor = MouseCursor.ibeam;
}
- public override void onMouseMove (object sender, MouseMoveEventArgs e)
+ public override void onMouseMove (object sender, MouseMoveEventArgs e)
{
base.onMouseMove (sender, e);
mouseMove (e);
base.onMouseWheel(sender, e);
mouseMove (e);
}
- void mouseMove (MouseEventArgs e) {
- updateHoverLocation (ScreenPointToLocal (IFace.MousePosition));
+ protected virtual void mouseMove (MouseEventArgs e) {
+ updateHoverLocation (ScreenPointToLocal (e.Position));
if (HasFocus && IFace.IsDown (MouseButton.Left)) {
CurrentLoc = hoverLoc;
}
public override void onMouseDown (object sender, MouseButtonEventArgs e)
{
- if (e.Button == Glfw.MouseButton.Left) {
+ if (!e.Handled && e.Button == Glfw.MouseButton.Left) {
targetColumn = -1;
if (HasFocus) {
if (!IFace.Shift)
using System.Collections;
using CrowEditBase;
using static CrowEditBase.CrowEditBase;
+using System.Collections.Generic;
+using System.Linq;
namespace Crow
{
}
hideOverlay ();
}
+
+ 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;
+
+ void updateMargin () {
+ leftMargin = leftMarginGap;
+ if (App.PrintLineNumbers)
+ leftMargin += (int)Math.Ceiling((double)lines.Count.ToString().Length * fe.MaxXAdvance) + 6;
+ if (App.FoldingEnabled)
+ leftMargin += foldMargin;
+ leftMargin += leftMarginRightGap;
+ //updateVisibleColumns ();
+ }
+ public override int measureRawSize(LayoutingType lt)
+ {
+ DbgLogger.StartEvent(DbgEvtType.GOMeasure, this, lt);
+ try {
+ if ((bool)lines?.IsEmpty)
+ getLines ();
+
+ updateMargin ();
+
+ if (!textMeasureIsUpToDate) {
+ using (Context gr = new Context (IFace.surf)) {
+ setFontForContext (gr);
+ measureTextBounds (gr);
+ }
+ }
+ return Margin * 2 + (lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width + leftMargin);
+ } finally {
+ DbgLogger.EndEvent(DbgEvtType.GOMeasure);
+ }
+ }
public override void onMouseDown (object sender, MouseButtonEventArgs e) {
hideOverlay ();
+ if (mouseIsInMargin) {
+ if (e.Button == MouseButton.Left && mouseIsInFoldRect) {
+ SyntaxNode curNode = getFoldFromLine (hoverLoc.Value.Line);
+ if (curNode != null) {
+ curNode.isFolded = !curNode.isFolded;
+ textMeasureIsUpToDate = false;
+ RegisterForRedraw();
+ }
+ }
+
+ e.Handled = true;
+ } else if (!e.Handled && HasFocus && e.Button == MouseButton.Left)
+ visualLine = hoverVisualLine;
+
base.onMouseDown (sender, e);
}
+ SyntaxNode getFoldFromLine (int line) {
+ if (!(Document is SourceDocument doc))
+ return null;
+ IEnumerable<SyntaxNode> folds = doc.SyntaxRootNode.FoldableNodes;
+ if (folds == null)
+ return null;
+ return folds.FirstOrDefault (n => n.StartLine == line);
+ }
+ protected override void mouseMove (MouseEventArgs e) {
+ Point mLoc = ScreenPointToLocal (e.Position);
+ if (mLoc.X < leftMargin - leftMarginRightGap) {
+ mouseIsInMargin = true;
+ IFace.MouseCursor = MouseCursor.arrow;
+ } else {
+ if (mouseIsInFoldRect)
+ RegisterForRedraw();
+ mouseIsInMargin = mouseIsInFoldRect = false;
+ IFace.MouseCursor = MouseCursor.ibeam;
+ }
+
+ updateHoverLocation (mLoc);
+
+ if (mouseIsInMargin) {
+ double lineHeight = fe.Ascent + fe.Descent;
+ Rectangle rFold = new Rectangle (leftMargin - foldMargin - leftMarginRightGap,
+ (int)(lineHeight * hoverVisualLine + lineHeight / 2.0 - foldSize / 2.0) - ScrollY, foldSize, foldSize);
+ mouseIsInFoldRect = rFold.ContainsOrIsEqual (mLoc);
+ RegisterForRedraw();
+ return;
+ }
+
+
+ if (HasFocus && IFace.IsDown (MouseButton.Left)) {
+ CurrentLoc = hoverLoc;
+ autoAdjustScroll = true;
+ IFace.forceTextCursor = true;
+ RegisterForRedraw ();
+ }
+ }
+ int hoverVisualLine, visualLine;
+ protected override void updateHoverLocation (Point mouseLocalPos) {
+ hoverVisualLine = getLineIndex (mouseLocalPos);
+ int hoverLine = hoverVisualLine + countFoldedLinesUntil (hoverVisualLine);
+ NotifyValueChanged("MouseY", mouseLocalPos.Y + ScrollY);
+ NotifyValueChanged("ScrollY", ScrollY);
+ NotifyValueChanged("VisibleLines", visibleLines);
+ NotifyValueChanged("HoverLine", hoverLine);
+ if (mouseIsInMargin) {
+ if (hoverLoc.HasValue)
+ hoverLoc = new CharLocation (hoverLine, hoverLoc.Value.Column, hoverLoc.Value.VisualCharXPosition);
+ else
+ hoverLoc = new CharLocation (hoverLine, 0, 0);
+ return;
+ }
+ hoverLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X + ScrollX - leftMargin);
+ using (Context gr = new Context (IFace.surf)) {
+ setFontForContext (gr);
+ updateLocation (gr, ClientRectangle.Width, ref hoverLoc);
+ }
+ }
+
public override void onKeyDown(object sender, KeyEventArgs e)
{
TextSpan selection = Selection;
return;
}
+ if (e.Key == Key.F3 && Document is SourceDocument doc) {
+ doc.SyntaxRootNode?.Dump();
+ }
+
base.onKeyDown(sender, e);
}
- const int leftMarginGap = 3;//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;
- void updateMargin () {
- leftMargin = leftMarginGap;
- if (App.PrintLineNumbers)
- leftMargin += (int)Math.Ceiling((double)lines.Count.ToString().Length * fe.MaxXAdvance) + 6;
- if (App.FoldingEnabled)
- leftMargin += foldMargin;
- if (leftMargin > 0)
- leftMargin += leftMarginRightGap;
- //updateVisibleColumns ();
- }
- public override int measureRawSize(LayoutingType lt)
- {
- DbgLogger.StartEvent(DbgEvtType.GOMeasure, this, lt);
- try {
- if ((bool)lines?.IsEmpty)
- getLines ();
- updateMargin ();
- if (!textMeasureIsUpToDate) {
- using (Context gr = new Context (IFace.surf)) {
- setFontForContext (gr);
- measureTextBounds (gr);
- }
- }
- return Margin * 2 + (lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width + leftMargin);
- } finally {
- DbgLogger.EndEvent(DbgEvtType.GOMeasure);
- }
- }
- protected override void updateHoverLocation (Point mouseLocalPos) {
- int hoverLine = (int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ (fe.Ascent + fe.Descent))), lines.Count - 1);
- int scrollLine = (int)Math.Ceiling((double)ScrollY / (fe.Ascent + fe.Descent));
- /*if (hoverLine > scrollLine + visibleLines)
- ScrollY = (int)((double)(hoverLine - visibleLines) * (fe.Ascent + fe.Descent));*/
- NotifyValueChanged("MouseY", mouseLocalPos.Y + ScrollY);
- NotifyValueChanged("ScrollY", ScrollY);
- NotifyValueChanged("VisibleLines", visibleLines);
- NotifyValueChanged("HoverLine", hoverLine);
- NotifyValueChanged("ScrollLine", hoverLine);
- hoverLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X + ScrollX - leftMargin);
- using (Context gr = new Context (IFace.surf)) {
- setFontForContext (gr);
- updateLocation (gr, ClientRectangle.Width, ref hoverLoc);
+ protected override int lineCount
+ {
+ get {
+ if (!(Document is SourceDocument doc))
+ return base.lineCount;
+ return lines.Count - countFoldedLinesUntil (lines.Count);
}
}
+ protected override int visualCurrentLine => visualLine;
protected override void updateMaxScrolls (LayoutingType layout) {
updateMargin();
Rectangle cb = ClientRectangle;
}
}
+ 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;
+
+ while (nodeEnum.Current.StartLine < nextNode.StartLine) {
+ if (!nodeEnum.MoveNext())
+ return foldedLines;
+ }
+
+ } else if (!nodeEnum.MoveNext())
+ return foldedLines;
+ }
+ l ++;
+ }
+ //Console.WriteLine ($"visualLine: {visualLine} foldedLines: {foldedLines}");
+ return foldedLines;
+ }
+
protected override void drawContent (Context gr) {
if (!(Document is SourceDocument doc)) {
base.drawContent (gr);
return;
}
- //lock(TokenMutex) {
+
doc.EnterReadLock ();
try {
if (doc.Tokens == null || doc.Tokens.Length == 0) {
return;
}
+ setFontForContext (gr);
+
+ if (!textMeasureIsUpToDate) {
+ lock (linesMutex)
+ measureTextBounds (gr);
+ }
+
double lineHeight = fe.Ascent + fe.Descent;
updateMargin ();
Rectangle cb = ClientRectangle;
RectangleD marginRect = new RectangleD (cb.X + ScrollX, cb.Y, leftMargin - leftMarginRightGap, lineHeight);
- /*gr.SetSource (App.MarginBackground);
- gr.Rectangle (marginRect);
- gr.Fill ();*/
cb.Left += leftMargin;
CharLocation selStart = default, selEnd = default;
bool selectionNotEmpty = false;
- //if (HasFocus) {
- if (currentLoc?.Column < 0) {
- updateLocation (gr, cb.Width, ref currentLoc);
- NotifyValueChanged ("CurrentColumn", CurrentColumn);
- } else
- updateLocation (gr, cb.Width, ref currentLoc);
-
- 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)
- hideOverlay ();
- else {
- p += ScreenCoordinates (Slot).TopLeft;
- overlay.Left = p.X;
- overlay.Top = p.Y;
- }
+ if (currentLoc?.Column < 0) {
+ updateLocation (gr, cb.Width, ref currentLoc);
+ NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ } else
+ updateLocation (gr, cb.Width, ref currentLoc);
+
+ 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)
+ hideOverlay ();
+ else {
+ p += ScreenCoordinates (Slot).TopLeft;
+ overlay.Left = p.X;
+ overlay.Top = p.Y;
}
- if (selectionStart.HasValue) {
- updateLocation (gr, cb.Width, ref selectionStart);
- if (CurrentLoc.Value != selectionStart.Value)
- selectionNotEmpty = true;
+ }
+ if (selectionStart.HasValue) {
+ updateLocation (gr, cb.Width, ref selectionStart);
+ if (CurrentLoc.Value != selectionStart.Value)
+ selectionNotEmpty = true;
+ }
+ if (selectionNotEmpty) {
+ if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
+ selStart = CurrentLoc.Value;
+ selEnd = selectionStart.Value;
+ } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
+ selStart = selectionStart.Value;
+ selEnd = CurrentLoc.Value;
+ } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
+ selStart = CurrentLoc.Value;
+ selEnd = selectionStart.Value;
+ } else {
+ selStart = selectionStart.Value;
+ selEnd = CurrentLoc.Value;
}
- if (selectionNotEmpty) {
- if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
- selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
- selStart = selectionStart.Value;
- selEnd = CurrentLoc.Value;
- } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
- selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else {
- selStart = selectionStart.Value;
- selEnd = CurrentLoc.Value;
- }
- } else
- IFace.forceTextCursor = true;
- //}
+ } else
+ IFace.forceTextCursor = true;
+
double spacePixelWidth = gr.TextExtents (" ").XAdvance;
- int x = 0, y = 0;
- double pixX = cb.Left;
+ int x = 0;
+ double pixX = cb.Left,
+ pixY = cb.Top;
Foreground.SetAsSource (IFace, gr);
gr.Translate (-ScrollX, -ScrollY);
TextExtents extents;
int tokPtr = 0;
Token tok = doc.Tokens[tokPtr];
- bool multilineToken = false;
ReadOnlySpan<char> buff = sourceBytes;
+ SyntaxNode curNode = null;
- for (int i = 0; i < lines.Count; i++) {
+ IEnumerator<SyntaxNode> nodeEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator ();
+ bool notEndOfNodes = nodeEnum.MoveNext();
+
+ int l = 0;
+ while (l < lines.Count) {
//if (!cancelLinePrint (lineHeight, lineHeight * y, cb.Height)) {
- double pixY = lineHeight * y + cb.Top;
- if (multilineToken) {
- if (tok.End < lines[i].End)//last incomplete line of multiline token
- buff = sourceBytes.Slice (lines[i].Start, tok.End - lines[i].Start);
- else//print full line
- buff = sourceBytes.Slice (lines[i].Start, lines[i].Length);
+ bool foldable = false;
+ if (notEndOfNodes && nodeEnum.Current.StartLine == l) {
+ curNode = nodeEnum.Current;
+ notEndOfNodes = nodeEnum.MoveNext();
+ if (curNode.isFolded) {
+ SyntaxNode nextNode = curNode.NextSiblingOrParentsNextSibling;
+ if (nextNode == null)
+ notEndOfNodes = false;
+ else {
+ while (notEndOfNodes && nodeEnum.Current.StartLine < nextNode.StartLine)
+ notEndOfNodes = nodeEnum.MoveNext();
+ }
+ }
+ foldable = true;
}
- while (tok.Start < lines[i].End) {
- if (!multilineToken) {
- if (tok.End > lines[i].End) {//first line of multiline
- multilineToken = true;
- buff = sourceBytes.Slice (tok.Start, lines[i].End - tok.Start);
- } else
- buff = sourceBytes.Slice (tok.Start, tok.Length);
+ //buff = sourceBytes.Slice (lines[l].Start, lines[l].Length);
- gr.SetSource(doc.GetColorForToken (tok.Type));
- }
+ while (tok.Start < lines[l].End) {
+ buff = sourceBytes.Slice (tok.Start, tok.Length);
+ gr.SetSource (doc.GetColorForToken (tok.Type));
int size = buff.Length * 4 + 1;
if (bytes.Length < size)
x += buff.Length;
}
- if (multilineToken) {
- if (tok.End < lines[i].End)//last incomplete line of multiline token
- multilineToken = false;
- else
- break;
- }
-
if (++tokPtr >= doc.Tokens.Length)
break;
tok = doc.Tokens[tokPtr];
if (selectionNotEmpty) {
RectangleD selRect = lineRect;
- if (i >= selStart.Line && i <= selEnd.Line) {
+ if (l >= selStart.Line && l <= selEnd.Line) {
if (selStart.Line == selEnd.Line) {
selRect.X += selStart.VisualCharXPosition;
selRect.Width = selEnd.VisualCharXPosition - selStart.VisualCharXPosition;
- } else if (i == selStart.Line) {
+ } else if (l == selStart.Line) {
selRect.X += selStart.VisualCharXPosition;
selRect.Width -= selStart.VisualCharXPosition - 10.0;
- } else if (i == selEnd.Line)
+ } else if (l == selEnd.Line)
selRect.Width = selEnd.VisualCharXPosition - selRect.X + cb.X;
else
selRect.Width += 10.0;
- buff = sourceBytes.Slice(lines[i].Start, lines[i].Length);
+ 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];
}
//Draw line numbering
- int curLine = i;
if (printLineNumbers){
marginRect.Y = lineRect.Y;
- string strLN = (curLine+1).ToString ();
+ string strLN = (l+1).ToString ();
gr.SetSource (marginBG);
gr.Rectangle (marginRect);
gr.Fill();
gr.ShowText (strLN);
gr.Fill ();
}
+ //draw fold
+ if (foldable) {
+ Rectangle rFld = new Rectangle (cb.X - leftMarginGap - foldMargin,
+ (int)(marginRect.Y + lineHeight / 2.0 - foldSize / 2.0), foldSize, foldSize);
+
+ gr.Rectangle (rFld);
+ if (hoverLoc.HasValue && l == hoverLoc.Value.Line && mouseIsInFoldRect)
+ gr.SetSource (Colors.LightBlue);
+ else
+ gr.SetSource (Colors.White);
+ gr.Fill();
+ gr.SetSource (Colors.Black);
+ gr.Rectangle (rFld, 1.0);
+ if (curNode.isFolded) {
+ gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2);
+ gr.LineTo (rFld.Center.X + 0.5, rFld.Bottom - 2);
+ }
- if (!multilineToken) {
- if (++tokPtr >= doc.Tokens.Length)
- break;
- tok = doc.Tokens[tokPtr];
+ gr.MoveTo (rFld.Left + 2, rFld.Center.Y + 0.5);
+ gr.LineTo (rFld.Right - 2, rFld.Center.Y + 0.5);
+ gr.Stroke ();
}
+ if (++tokPtr >= doc.Tokens.Length)
+ break;
+ tok = doc.Tokens[tokPtr];
+
x = 0;
pixX = cb.Left;
+ pixY += lineHeight;
- y++;
-
-
+ if (foldable && curNode.isFolded) {
+ TextSpan ns = curNode.Span;
+ l = curNode.StartLine + curNode.LineCount;
+ while (tok.End <= lines[l].Start) {
+ if (++tokPtr >= doc.Tokens.Length)
+ break;
+ tok = doc.Tokens[tokPtr];
+ }
+ //tokPtr = doc.FindTokenIndexIncludingPosition (lines[l].Start);
+ } else
+ l ++;
/* } else if (tok2.Type == TokenType.Tabulation) {
int spaceRounding = x % tabSize;
int spaces = spaceRounding == 0 ?
CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" />
<HorizontalStack Height="Fit" Spacing='3'>
<Widget Width="Stretched"/>
- <!--<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="ScrollLine:" Foreground="Grey"/>
<Label Text="{../../tb.ScrollLine}" Margin="3"/>
<Label Text="HoverLine:" Foreground="Grey"/>
- <Label Text="{../../tb.HoverLine}" Margin="3"/>-->
+ <Label Text="{../../tb.HoverLine}" Margin="3"/>
<Label Text="Line:" Foreground="Grey"/>
<Label Text="{../../tb.CurrentLine}" Margin="3"/>
<Label Text="Col:" Foreground="Grey"/>
}
States curState;
- int startOfTok;
-
public StyleTokenizer () {}
}
return false;
}
- protected List<Token> Toks;
- void skipWhiteSpaces (ref SpanCharReader reader) {
- while(!reader.EndOfSpan) {
- switch (reader.Peak) {
- case '\x85':
- case '\x2028':
- case '\xA':
- reader.Read();
- addTok (ref reader, StyleTokenType.LineBreak);
- break;
- case '\xD':
- reader.Read();
- if (reader.IsNextCharIn ('\xA', '\x85'))
- reader.Read();
- addTok (ref reader, StyleTokenType.LineBreak);
- break;
- case '\x20':
- case '\x9':
- char c = reader.Read();
- while (reader.TryPeak (c))
- reader.Read();
- addTok (ref reader, c == '\x20' ? StyleTokenType.WhiteSpace : StyleTokenType.Tabulation);
- break;
- default:
- return;
- }
- }
- }
- void addTok (ref SpanCharReader reader, Enum tokType) {
- if (reader.CurrentPosition == startOfTok)
- return;
- Toks.Add (new Token((TokenType)tokType, startOfTok, reader.CurrentPosition));
- startOfTok = reader.CurrentPosition;
- }
public override Token[] Tokenize (string source) {
- SpanCharReader reader = new SpanCharReader(source);
+ SpanCharReader reader = initParsing (source);
- startOfTok = 0;
- int curObjectLevel = 0;
curState = States.classNames;
- Toks = new List<Token>(100);
while(!reader.EndOfSpan) {
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.HasFlag (TokenType.Trivia)) {
+ 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.EndToken.HasValue)
- CurrentNode.EndToken = previousTok;
- CurrentNode = CurrentNode.Parent;
+ while (currentNode.Parent != null) {
+ if (!currentNode.EndToken.HasValue)
+ storeCurrentNode (previousTok, currentLine);
+ else
+ currentNode = currentNode.Parent;
}
+ setCurrentNodeEndLine (currentLine);
}
}
}
\ No newline at end of file
namespace CECrowPlugin
{
- public class StyleRootSyntax : SyntaxNode {
- internal readonly StyleDocument source;
- public override SyntaxNode Root => this;
+ public class StyleRootSyntax : SyntaxRootNode {
public StyleRootSyntax (StyleDocument source)
- : base (source.Tokens.FirstOrDefault (), source.Tokens.LastOrDefault ()) {
- this.source = source;
+ : base (source) {
}
}
public Token? ValueOpenToken { get; internal set; }
public Token? ValueCloseToken { get; internal set; }
public Token? ValueToken { get; internal set; }
- public AttributeSyntax (Token startTok) : base (startTok) {}
- public override bool IsComplete => base.IsComplete & NameToken.HasValue & EqualToken.HasValue & ValueToken.HasValue & ValueOpenToken.HasValue & ValueCloseToken.HasValue;
+ public AttributeSyntax (int startLine, Token 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
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
-
+
<ItemGroup>
<Compile Include="src\**\*.cs" />
<EmbeddedResource Include="ui\**\*.*" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="../CERoslynPlugin\CERoslynPlugin.csproj" />
+ <ProjectReference Include="../CERoslynPlugin\CERoslynPlugin.csproj" />
</ItemGroup>
-
+
</Project>
namespace NetcoreDbgPlugin
-{
+{
public class NetcoreDbgService : Service {
public NetcoreDbgService () : base () {
}
{
if (base.Project == value || !(value is MSBuildProject msbProj))
return;
- base.Project = value;
+ base.Project = value;
}
}
void initDebugSession () {
if (CurrentState != Status.Init || msbProject == null)
return;
-
+
bool result = procdbg.Start();
procdbg.BeginOutputReadLine();
}
public override void Stop()
{
- CreateNewRequest($"-exec-abort");
+ CreateNewRequest($"-exec-abort");
}
public override void StepIn()
private void Procdbg_Exited(object sender, EventArgs e)
{
DebuggerLog.Add("GDB process Terminated.");
-
+
CurrentState = Status.Init;
}
-
+
void getStackFrames(ThreadInfo thread = null)
{
if (thread == null)
}
void updateWatches () {
foreach (Watch w in Watches)
- w.UpdateValue ();
+ w.UpdateValue ();
}
void tryGoTo(StackFrame frame)
void Procdbg_ErrorDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) {
DebuggerLog.Add($"-> Error: {e.Data}");
- }
+ }
void Procdbg_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) {
if (string.IsNullOrEmpty(e.Data))
} else if (request is Request<BreakPoint> bpReq) {
BreakPoint bp = bpReq.RequestObject;
bp.Update (obj["bkpt"] as MITupple);
-
+
} else
DebuggerLog.Add($"=> request result not handled: {request}");
}
DebuggerLog.Add($"Stopped reason:{reason}");
StackFrame frame = new StackFrame(obj["frame"] as MITupple);
- if (reason == "breakpoint-hit") {
+ if (reason == "breakpoint-hit") {
BreakPoint bp = (BreakPoint)BreakPoints.FirstOrDefault (bk=>bk.Index == int.Parse (obj.GetAttributeValue ("bkptno")));
bp.UpdateLocation (frame);
}
CreateNewRequest (new Request<Watch> (w, $"-var-create {w.Name} {w.Expression} {strThread} {strLevel}"));
}
public void WatchChildrenRequest(Watch w)
- {
+ {
string strThread = CurrentThread == null ? "" : $"--thread {CurrentThread.Id}";
- string strLevel = CurrentFrame == null ? "" : $"--frame {CurrentFrame.Level}";
+ string strLevel = CurrentFrame == null ? "" : $"--frame {CurrentFrame.Level}";
CreateNewRequest (new Request<Watch> (w, $"-var-list-children 1 {w.Name} {strThread} {strLevel}"));
}
<?xml version="1.0"?>
-<DockWindow Caption="Roslyn plugin configuration" Width="300" Height="400" Resizable="false">
+<DockWindow Caption="NetcoreDbg plugin configuration" Width="300" Height="400" Resizable="false">
<VerticalStack RootDataLevel="true" Margin="5">
<HorizontalStack Height="Fit">
<Label Width="200" Text="Netcoredbg path"/>
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Netcore Debugger" Width="Fit" Height="Fit" Resizable="false">
+ <Template>
+ <Border Name="Content" Name="MoveHandle" Margin="5"/>
+ </Template>
+ <HorizontalStack Fit="true">
+ <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}"/>
+ </VerticalStack>
+</DockWindow>
+
+
+++ /dev/null
-<?xml version="1.0"?>
-
-
-
if (eventSource != null)
registerHandles ();
}
- }
+ }
public string Parameters { get; set; }
public ConsoleLogger (LoggerVerbosity verbosity = LoggerVerbosity.Normal)
- {
+ {
this.verbosity = verbosity;
}
public void Initialize (IEventSource eventSource) {
Console.WriteLine (e.Message);
}
- private void EventSource_TargetFinished (object sender, TargetFinishedEventArgs e) {
+ private void EventSource_TargetFinished (object sender, TargetFinishedEventArgs e) {
Console.WriteLine (e.Message);
}
if (e.Importance != MessageImportance.Low)
Console.WriteLine (e.Message);
}
- private void EventSource_MessageRaised_All (object sender, BuildMessageEventArgs e) {
+ private void EventSource_MessageRaised_All (object sender, BuildMessageEventArgs e) {
Console.WriteLine (e.Message);
}
void EventSource_ProjectStarted (object sender, ProjectStartedEventArgs e)
printEvaluatedProperties (result.ProjectStateAfterBuild);
+ var test = result.ProjectStateAfterBuild.GetItems ("Reference");
+
//}
}
public override string Icon {
projectCollection.SetGlobalProperty ("SolutionDir", Path.GetDirectoryName (FullPath) + Path.DirectorySeparatorChar);
projectCollection.SetGlobalProperty ("DefaultItemExcludes", "obj/**/*;bin/**/*");
+ projectCollection.SetGlobalProperty ("TargetFramework", "netcoreapp3.1");
//IDE.ProgressNotify (10);
IsLoaded = true;
}
+
+ void build (params string[] targets) {
+ BuildRequestData buildRequest = new BuildRequestData (FullPath, null, "Current", targets, null);
+ BuildResult buildResult = BuildManager.DefaultBuildManager.Build (buildParams, buildRequest);
+ }
}
}
\ No newline at end of file
namespace CrowEdit.Xml
{
public class XmlSyntaxAnalyser : SyntaxAnalyser {
- public override SyntaxNode Root => CurrentNode;
+ public override SyntaxNode Root => currentNode;
public XmlSyntaxAnalyser (XmlDocument source) : base (source) {
this.source = source;
}
- SyntaxNode CurrentNode;
Token previousTok;
IEnumerator<Token> iter;
+ int currentLine;
+
public override void Process () {
XmlDocument xmlDoc = source as XmlDocument;
Exceptions = new List<SyntaxException> ();
- CurrentNode = new IMLRootSyntax (xmlDoc);
+ currentNode = new IMLRootSyntax (xmlDoc);
previousTok = default;
iter = xmlDoc.Tokens.AsEnumerable().GetEnumerator ();
+ currentLine = 0;
bool notEndOfSource = iter.MoveNext ();
while (notEndOfSource) {
- if (!iter.Current.Type.HasFlag (TokenType.Trivia)) {
- if (CurrentNode is ElementStartTagSyntax tag) {
+ if (iter.Current.Type == TokenType.LineBreak)
+ currentLine++;
+ else if (!iter.Current.Type.HasFlag (TokenType.Trivia)) {
+ if (currentNode is ElementStartTagSyntax tag) {
if (iter.Current.GetTokenType() == XmlTokenType.AttributeName) {
- AttributeSyntax attribute = new AttributeSyntax (iter.Current);
+ AttributeSyntax attribute = new AttributeSyntax (currentLine, iter.Current);
attribute.NameToken = iter.Current;
- CurrentNode = CurrentNode.AddChild (attribute);
+ currentNode = currentNode.AddChild (attribute);
} else if (iter.Current.GetTokenType() == XmlTokenType.ElementName)
tag.NameToken = iter.Current;
else if (iter.Current.GetTokenType() == XmlTokenType.ClosingSign) {
- tag.EndToken = iter.Current;
- CurrentNode = tag.Parent;
- CurrentNode.RemoveChild (tag);
- CurrentNode = CurrentNode.AddChild (new ElementSyntax (tag));
+ storeCurrentNode (iter.Current, currentLine);
+ currentNode.RemoveChild (tag);
+ currentNode = currentNode.AddChild (new ElementSyntax (tag));
} else if (iter.Current.GetTokenType() == XmlTokenType.EmptyElementClosing) {
- tag.EndToken = iter.Current;
- CurrentNode = tag.Parent;
- CurrentNode.RemoveChild (tag);
- CurrentNode.AddChild (new EmptyElementSyntax (tag));
+ storeCurrentNode (iter.Current, currentLine);
+ currentNode.RemoveChild (tag);
+ currentNode = currentNode.AddChild (new EmptyElementSyntax (tag));
+ setCurrentNodeEndLine (currentLine);
+ currentNode = currentNode.Parent;
} else {
Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current));
- CurrentNode.EndToken = previousTok;
- CurrentNode = CurrentNode.Parent;
+ storeCurrentNode (previousTok, currentLine);
continue;
}
- } else if (CurrentNode is ElementSyntax elt) {
+ } else if (currentNode is ElementSyntax elt) {
if (iter.Current.GetTokenType() == XmlTokenType.ElementOpen)
- CurrentNode = CurrentNode.AddChild (new ElementStartTagSyntax (iter.Current));
+ currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, iter.Current));
else if (iter.Current.GetTokenType() == XmlTokenType.EndElementOpen) {
- elt.EndTag = new ElementEndTagSyntax (iter.Current);
- CurrentNode = elt.AddChild (elt.EndTag);
+ elt.EndTag = new ElementEndTagSyntax (currentLine, iter.Current);
+ currentNode = elt.AddChild (elt.EndTag);
}
- } else if (CurrentNode is AttributeSyntax attrib) {
+ } else if (currentNode is AttributeSyntax attrib) {
if (iter.Current.GetTokenType() == XmlTokenType.EqualSign)
if (attrib.EqualToken.HasValue)
Exceptions.Add (new SyntaxException ("Extra equal sign in attribute syntax", iter.Current));
else if (iter.Current.GetTokenType() == XmlTokenType.AttributeValue)
attrib.ValueToken = iter.Current;
else if (iter.Current.GetTokenType() == XmlTokenType.AttributeValueClose) {
- attrib.ValueCloseToken = attrib.EndToken = iter.Current;
- CurrentNode = CurrentNode.Parent;
+ attrib.ValueCloseToken = iter.Current;
+ storeCurrentNode (iter.Current, currentLine);
} else {
Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current));
- CurrentNode.EndToken = previousTok;
- CurrentNode = CurrentNode.Parent;
+ storeCurrentNode (previousTok, currentLine);
continue;
}
- } else if (CurrentNode is ElementEndTagSyntax eltEndTag) {
+ } else if (currentNode is ElementEndTagSyntax eltEndTag) {
if (iter.Current.GetTokenType() == XmlTokenType.ElementName)
eltEndTag.NameToken = iter.Current;
else if (iter.Current.GetTokenType() == XmlTokenType.ClosingSign) {
- eltEndTag.EndToken = eltEndTag.Parent.EndToken = iter.Current;
- CurrentNode = eltEndTag.Parent.Parent;
+ //go up 2 times
+ storeCurrentNode (iter.Current, currentLine);
+ storeCurrentNode (iter.Current, currentLine);
} else {
Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current));
- eltEndTag.EndToken = eltEndTag.Parent.EndToken = previousTok;
- CurrentNode = CurrentNode.Parent.Parent;
+ storeCurrentNode (previousTok, currentLine);
+ storeCurrentNode (previousTok, currentLine);
continue;
}
- } else if (CurrentNode is IMLRootSyntax) {
+ } else if (currentNode is IMLRootSyntax) {
switch (iter.Current.GetTokenType()) {
case XmlTokenType.ElementOpen:
- CurrentNode = CurrentNode.AddChild (new ElementStartTagSyntax (iter.Current));
+ currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, iter.Current));
break;
case XmlTokenType.PI_Start:
- CurrentNode = CurrentNode.AddChild (new ProcessingInstructionSyntax (iter.Current));
+ currentNode = currentNode.AddChild (new ProcessingInstructionSyntax (currentLine, iter.Current));
break;
default:
Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current));
break;
}
- } else if (CurrentNode is ProcessingInstructionSyntax pi) {
+ } else if (currentNode is ProcessingInstructionSyntax pi) {
if (iter.Current.GetTokenType() == XmlTokenType.PI_Target)
pi.NameToken = iter.Current;
else if (iter.Current.GetTokenType() == XmlTokenType.PI_End) {
- pi.EndToken = iter.Current;
- CurrentNode = CurrentNode.Parent;
+ storeCurrentNode (iter.Current, currentLine);
} else if (iter.Current.GetTokenType() == XmlTokenType.AttributeName) {
- AttributeSyntax attribute = new AttributeSyntax (iter.Current);
+ AttributeSyntax attribute = new AttributeSyntax (currentLine, iter.Current);
attribute.NameToken = iter.Current;
- CurrentNode = CurrentNode.AddChild (attribute);
+ currentNode = currentNode.AddChild (attribute);
} else {
Exceptions.Add (new SyntaxException ("Unexpected Token", iter.Current));
- pi.EndToken = previousTok;
- CurrentNode = CurrentNode.Parent;
+ storeCurrentNode (previousTok, currentLine);
continue;
}
}
previousTok = iter.Current;
notEndOfSource = iter.MoveNext ();
}
- while (CurrentNode.Parent != null) {
- if (!CurrentNode.EndToken.HasValue)
- CurrentNode.EndToken = previousTok;
- CurrentNode = CurrentNode.Parent;
+ while (currentNode.Parent != null) {
+ if (!currentNode.EndToken.HasValue)
+ storeCurrentNode (previousTok, currentLine);
+ else
+ currentNode = currentNode.Parent;
}
+ setCurrentNodeEndLine (currentLine);
}
}
}
\ No newline at end of file
// 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 Crow.Text;
using CrowEditBase;
namespace CrowEdit.Xml
{
- public class IMLRootSyntax : SyntaxNode {
- internal readonly XmlDocument source;
- public override SyntaxNode Root => this;
+ public class IMLRootSyntax : SyntaxRootNode {
public IMLRootSyntax (XmlDocument source)
- : base (source.Tokens.FirstOrDefault (), source.Tokens.LastOrDefault ()) {
- this.source = source;
+ : base (source) {
}
}
public class ProcessingInstructionSyntax : SyntaxNode {
public Token? PIEndToken => EndToken.HasValue && EndToken.Value.GetTokenType() == XmlTokenType.PI_End ? EndToken : null;
public Token? NameToken { get; internal set; }
public override bool IsComplete => base.IsComplete & NameToken.HasValue;
- public ProcessingInstructionSyntax (Token startTok)
- : base (startTok) {
+ public ProcessingInstructionSyntax (int startLine, Token startTok)
+ : base (startLine, startTok) {
}
}
public Token? NameToken { get; internal set; }
public Token? CloseToken => EndToken.HasValue && EndToken.Value.GetTokenType() == XmlTokenType.ClosingSign ? EndToken : null;
public override bool IsComplete => base.IsComplete & NameToken.HasValue & CloseToken.HasValue;
- protected ElementTagSyntax (Token startTok)
- : base (startTok) {
+ protected ElementTagSyntax (int startLine, Token startTok)
+ : base (startLine, startTok) {
}
}
public class ElementStartTagSyntax : ElementTagSyntax {
- public ElementStartTagSyntax (Token startTok)
- : base (startTok) {
+ public ElementStartTagSyntax (int startLine, Token startTok)
+ : base (startLine, startTok) {
}
}
public class ElementEndTagSyntax : ElementTagSyntax {
- public ElementEndTagSyntax (Token startTok)
- : base (startTok) {
+ public ElementEndTagSyntax (int startLine, Token startTok)
+ : base (startLine, startTok) {
}
}
public class EmptyElementSyntax : SyntaxNode {
public readonly ElementStartTagSyntax StartTag;
- public EmptyElementSyntax (ElementStartTagSyntax startNode) : base (startNode.StartToken, startNode.EndToken) {
+ public EmptyElementSyntax (ElementStartTagSyntax startNode) : base (startNode.StartLine, startNode.StartToken, startNode.EndToken) {
StartTag = startNode;
AddChild (StartTag);
}
public override bool IsComplete => base.IsComplete & StartTag.IsComplete & (EndTag != null && EndTag.IsComplete);
public ElementSyntax (ElementStartTagSyntax startTag)
- : base (startTag.StartToken) {
+ : base (startTag.StartLine, startTag.StartToken) {
StartTag = startTag;
AddChild (StartTag);
}
public Token? ValueOpenToken { get; internal set; }
public Token? ValueCloseToken { get; internal set; }
public Token? ValueToken { get; internal set; }
- public AttributeSyntax (Token startTok) : base (startTok) {}
+ public AttributeSyntax (int startLine, Token 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
}
States curState;
- int startOfTok;
-
public XmlTokenizer () {}
bool readName (ref SpanCharReader reader) {
}
return false;
}
- protected List<Token> Toks;
- void skipWhiteSpaces (ref SpanCharReader reader) {
- while(!reader.EndOfSpan) {
- switch (reader.Peak) {
- case '\x85':
- case '\x2028':
- case '\xA':
- reader.Read();
- addTok (ref reader, XmlTokenType.LineBreak);
- break;
- case '\xD':
- reader.Read();
- if (reader.IsNextCharIn ('\xA', '\x85'))
- reader.Read();
- addTok (ref reader, XmlTokenType.LineBreak);
- break;
- case '\x20':
- case '\x9':
- char c = reader.Read();
- while (reader.TryPeak (c))
- reader.Read();
- addTok (ref reader, c == '\x20' ? XmlTokenType.WhiteSpace : XmlTokenType.Tabulation);
- break;
- default:
- return;
- }
- }
- }
- void addTok (ref SpanCharReader reader, Enum tokType) {
- if (reader.CurrentPosition == startOfTok)
- return;
- Toks.Add (new Token((TokenType)tokType, startOfTok, reader.CurrentPosition));
- startOfTok = reader.CurrentPosition;
- }
public override Token[] Tokenize (string source) {
- SpanCharReader reader = new SpanCharReader(source);
+ SpanCharReader reader = initParsing (source);
- startOfTok = 0;
int curObjectLevel = 0;
curState = States.Init;
- Toks = new List<Token>(100);
while(!reader.EndOfSpan) {
if (reader.TryPeak ("--")) {
reader.Advance (2);
addTok (ref reader, XmlTokenType.BlockCommentStart);
- if (reader.TryReadUntil ("-->")) {
- addTok (ref reader, XmlTokenType.BlockComment);
- reader.Advance (3);
- addTok (ref reader, XmlTokenType.BlockCommentEnd);
- } else if (reader.TryPeak ("-->")) {
- reader.Advance (3);
- addTok (ref reader, XmlTokenType.BlockCommentEnd);
+ while (!reader.EndOfSpan) {
+ if (reader.Eol()) {
+ addTok (ref reader, XmlTokenType.BlockComment);
+ reader.ReadEol();
+ addTok (ref reader, XmlTokenType.LineBreak);
+ continue;
+ }
+ if (reader.TryPeak ("-->")) {
+ addTok (ref reader, XmlTokenType.BlockComment);
+ reader.Advance (3);
+ addTok (ref reader, XmlTokenType.BlockCommentEnd);
+ } else
+ reader.Read ();
}
} else {
addTok (ref reader, XmlTokenType.DTDObjectOpen);
new ActionCommand("Projects", () => LoadWindow ("#CrowEdit.ui.windows.winProjects.crow", this)),
new ActionCommand("Logs", () => LoadWindow ("#CrowEdit.ui.windows.winLogs.crow", this), "#icons.log.svg"),
new ActionCommand("Services", () => LoadWindow ("#CrowEdit.ui.windows.winServices.crow", this), "#icons.services.svg"),
- new ActionCommand("Plugins", () => LoadWindow ("#CrowEdit.ui.windows.winPlugins.crow", this), "#icons.plugins.svg")
+ new ActionCommand("Plugins", () => LoadWindow ("#CrowEdit.ui.windows.winPlugins.crow", this), "#icons.plugins.svg"),
+ new ActionCommand("Syntax Tree", () => LoadWindow ("#CrowEdit.ui.windows.winSyntaxExplorer.crow", this), "#icons.plugins.svg")
);
CMDHelp = new ActionCommand("Help", () => System.Diagnostics.Debug.WriteLine("help"), "#icons.question.svg");
<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"
- Background="Jet" MouseEnter="{Background=Grey}" MouseLeave="{Background=Jet}" />
+ Background="Jet" MouseEnter="{Background=Grey}" MouseLeave="{Background=Jet}" />
<TextBox Text="{²CurrentDir}" Margin="1"/>
- </HorizontalStack>
+ </HorizontalStack>
<DirectoryView Margin="0" Name="dv" CurrentDirectory="{CurrentDir}" SelectedItemChanged="Dv_SelectedItemChanged" >
<Template>
<TreeView IsRoot="true" Name="treeView" Data="{./FileSystemEntries}" Background="{./Background}"
<ItemTemplate DataType="System.IO.FileInfo">
<ListItem CornerRadius="2" Margin="0" Height="Fit" Width="Stretched"
MouseDoubleClick="OpenWithCrowEdit"
- ContextCommands="{GetCommands}"
+ ContextCommands="{GetCommands}"
Selected="{Background=${ControlHighlight}}"
Unselected="{Background=Transparent}">
<HorizontalStack>
</ItemTemplate>
</TreeView>
</Template>
- </DirectoryView>
+ </DirectoryView>
</VerticalStack>
</DockWindow>
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Syntax" Width="40%">
+ <VerticalStack RootDataLevel="true" Spacing="0" DataSource="{CurrentDocument}">
+ <Label Text="{}"/>
+ <TreeView DataSource="{SyntaxRootNode}" Data="{Children}">
+ <ItemTemplate Data="Children">
+ <Expandable Caption="{}" BubbleEvents="MouseWheel">
+ <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}"
+ 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="l:"/>
+ <Label Style="TreeLabel" Text="{StartLine}"/>
+ <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>
+ </Border>
+ </ListItem>
+ <Container Name="Content" Visible="false"/>
+ </VerticalStack>
+ </Template>
+ </Expandable>
+ </ItemTemplate>
+ </TreeView>
+ </VerticalStack>
+</DockWindow>
+
+