]> O.S.I.I.S - jp/crowedit.git/commitdiff
wip
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 25 Feb 2025 01:38:41 +0000 (02:38 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 25 Feb 2025 01:38:41 +0000 (02:38 +0100)
37 files changed:
CrowEditBase/src/Compiler/SourceDocument.cs
CrowEditBase/src/Compiler/SyntaxAnalyser.cs
CrowEditBase/src/Compiler/SyntaxException.cs [new file with mode: 0644]
CrowEditBase/src/Compiler/SyntaxNode.cs
CrowEditBase/src/Compiler/TokenReader.cs [new file with mode: 0644]
CrowEditBase/src/Compiler/Tokenizer.cs
CrowEditBase/src/CrowEditBase.cs
CrowEditBase/src/Debug/Debugger.cs
CrowEditBase/src/Editor.cs
CrowEditBase/src/SourceEditor.cs
CrowEditBase/src/TextDocument.cs
CrowEditBase/ui/CrowEdit.style
CrowEditBase/ui/DockWindowToolbar.template [new file with mode: 0644]
CrowEditBase/ui/SimpleStatus.template [new file with mode: 0644]
CrowEditBase/ui/sourceEditor.itmp
plugins/CECrowPlugin/src/ImlDocument.cs
plugins/CECrowPlugin/src/Parsing/Styling/SyntaxAnalyser.cs
plugins/CEEbnfPlugin/src/Parsing/EbnfDocument.cs
plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxAnalyser.cs
plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxNodes.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/EbnfTokenType.cs
plugins/CEEbnfPlugin/src/Parsing/EbnfTokenizer.cs
plugins/CEEbnfPlugin/src/Parsing/SymbolDecl.cs
plugins/CEEbnfPlugin/src/Parsing/SyntaxNodes.cs [deleted file]
plugins/CENetcoreDbgPlugin/ui/winDebugging.crow
plugins/CERoslynPlugin/src/SyntaxAnalyser.cs
plugins/CEXmlPlugin/src/Parsing/SyntaxAnalyser.cs [deleted file]
plugins/CEXmlPlugin/src/Parsing/SyntaxNodes.cs [deleted file]
plugins/CEXmlPlugin/src/Parsing/XmlDocument.cs
plugins/CEXmlPlugin/src/Parsing/XmlSyntaxAnalyser.cs [new file with mode: 0644]
plugins/CEXmlPlugin/src/Parsing/XmlSyntaxNodes.cs [new file with mode: 0644]
src/CrowEdit.cs
ui/windows/winEditor.crow
ui/windows/winFileExplorer.crow
ui/windows/winLogs.crow
ui/windows/winProjects.crow
ui/windows/winSyntaxExplorer.crow

index 6a28378c5eb3aa62bfcdc40d7215ee24290ce523..48bfd658122258cd6e57710af7b2925061641d5e 100644 (file)
@@ -19,6 +19,13 @@ namespace CrowEditBase
                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;
@@ -31,6 +38,7 @@ namespace CrowEditBase
                }
                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;
@@ -44,7 +52,7 @@ namespace CrowEditBase
                                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)
@@ -93,7 +101,6 @@ namespace CrowEditBase
                        base.apply(change);
 
                        Tokenizer tokenizer = CreateTokenizer ();
-                       tokens = tokenizer.Tokenize (Source);
                        SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
                        
                        if (syntaxAnalyser == null) {
@@ -101,6 +108,13 @@ namespace CrowEditBase
                                return;
                        }
 
+                       SyntaxNode changedNode = RootNode.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
+                       
+                       
+                       tokens = tokenizer.Tokenize (Source);
+
+
+
                        syntaxAnalyser.Process ();
                        NotifyValueChanged("Exceptions", syntaxAnalyser.Exceptions);
 
@@ -157,7 +171,7 @@ namespace CrowEditBase
                        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;
@@ -176,6 +190,7 @@ namespace CrowEditBase
                /// <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);
index dcac0eb560e939041053bf8e3feef0f78a9ce848..ab2df6784b707d2125c02050b758b46260a0b332 100644 (file)
@@ -1,4 +1,4 @@
-// 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;
@@ -7,37 +7,101 @@ using System.Linq;
 
 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;
diff --git a/CrowEditBase/src/Compiler/SyntaxException.cs b/CrowEditBase/src/Compiler/SyntaxException.cs
new file mode 100644 (file)
index 0000000..d889cc3
--- /dev/null
@@ -0,0 +1,16 @@
+// 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
index 4f10b435e5086d00e520365bfd9f10b138ae43ab..4d28970f55044f6303667be275a7f324d6e2ae07 100644 (file)
@@ -10,22 +10,31 @@ using Crow;
 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;
@@ -43,15 +52,28 @@ namespace CrowEditBase
                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;
@@ -101,15 +123,8 @@ namespace CrowEditBase
                }
 
                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;
 
@@ -125,9 +140,9 @@ namespace CrowEditBase
                                        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 ();
                                }
@@ -144,7 +159,8 @@ namespace CrowEditBase
                        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);
                }
@@ -152,7 +168,7 @@ namespace CrowEditBase
                        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;
@@ -160,7 +176,7 @@ namespace CrowEditBase
                        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)
@@ -205,10 +221,9 @@ namespace CrowEditBase
                        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();
        }
diff --git a/CrowEditBase/src/Compiler/TokenReader.cs b/CrowEditBase/src/Compiler/TokenReader.cs
new file mode 100644 (file)
index 0000000..daf32fb
--- /dev/null
@@ -0,0 +1,68 @@
+// 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
index b62d05c64c9b1788f2976f9dff1c2d28a706fbb4..06c33cadb5f50418e8cb4c12519eb0bc1492721b 100644 (file)
@@ -39,16 +39,20 @@ namespace CrowEditBase
                        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();
index fc8086962dc4ae7c58c902bba65a9f9802e163f8..985c14b1bfc5976910776f62ba8e4f226ffabb0e 100644 (file)
@@ -318,7 +318,10 @@ namespace CrowEditBase
                                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;
@@ -333,10 +336,74 @@ namespace CrowEditBase
                }
                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> (@"
@@ -409,7 +476,7 @@ namespace CrowEditBase
                                                        <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>
index 221c5d8dc59321fcce399301f79079a0be95895d..225a0632a8f75c16ceb7710edf7f5329caad1281 100644 (file)
@@ -27,7 +27,7 @@ namespace CrowEditBase
 
                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");
index a9bbb771cdac3192b92065ad8063bf0cc0a98a3a..dc9613f49b1b351bf0db7b31caa2256635da655c 100644 (file)
@@ -75,7 +75,7 @@ namespace Crow
 
                #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;
@@ -89,6 +89,7 @@ namespace Crow
                                currentLoc = value;
                                NotifyValueChanged ("CurrentLine", CurrentLine);
                                NotifyValueChanged ("CurrentColumn", CurrentColumn);
+                               NotifyValueChanged ("TabulatedColumn", TabulatedColumn);
 
                                CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
                        }
@@ -115,6 +116,10 @@ namespace Crow
                                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>
@@ -131,11 +136,9 @@ namespace Crow
                //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.
@@ -165,7 +168,16 @@ namespace Crow
                                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)
@@ -175,15 +187,17 @@ namespace Crow
                /// </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 () {
@@ -192,20 +206,50 @@ namespace Crow
                        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);
@@ -214,7 +258,7 @@ namespace Crow
                        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;
                }
@@ -315,12 +359,11 @@ namespace Crow
                        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;
                                        }
@@ -440,12 +483,9 @@ namespace Crow
                        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;
@@ -455,26 +495,29 @@ namespace Crow
                                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);
@@ -485,17 +528,35 @@ namespace Crow
                        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);
@@ -505,14 +566,17 @@ namespace Crow
                                        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);
@@ -521,7 +585,7 @@ namespace Crow
                                        if (loc.VisualCharXPosition <= cPos + halfWidth) {
                                                loc.Column = i;
                                                loc.VisualCharXPosition = cPos;
-                                               location = loc;
+                                               loc.TabulatedColumn = totChar;
                                                return;
                                        }
 
@@ -529,9 +593,63 @@ namespace Crow
                                }
                                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)) {
@@ -884,12 +1002,13 @@ namespace Crow
                }
 
                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();
index 24319dc8b905a9864d4540e14123dac940f466fb..a1aac8a95700e4aa3d1233b7f5f6f2086a4968ab 100644 (file)
@@ -16,20 +16,6 @@ namespace Crow
 {
        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;
@@ -54,6 +40,7 @@ namespace Crow
                        }
                }
 
+               #region suggestions and autocomplete
                ListBox overlay;
                IList suggestions;
                volatile bool disableSuggestions;
@@ -71,7 +58,7 @@ namespace Crow
                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) ||
@@ -141,12 +128,13 @@ namespace Crow
                        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;
 
@@ -159,6 +147,7 @@ namespace Crow
                        leftMargin += leftMarginRightGap;
                        //updateVisibleColumns ();
                }
+               #endregion
 
                protected override CharLocation? CurrentLoc {
                        get => currentLoc;
@@ -176,9 +165,11 @@ namespace Crow
                                }
                                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);
@@ -498,6 +489,13 @@ namespace Crow
 
                        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);
@@ -506,43 +504,49 @@ namespace Crow
 
                        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) {
@@ -566,13 +570,13 @@ namespace Crow
                                        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;
                                }
@@ -593,7 +597,7 @@ namespace Crow
                                }
 
 
-                               double spacePixelWidth = gr.TextExtents (" ").XAdvance;
+                               //double spacePixelWidth = gr.TextExtents (" ").XAdvance;
                                int x = 0;
                                double  pixX = cb.Left,
                                                pixY = cb.Top;
@@ -614,6 +618,7 @@ namespace Crow
                                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)) {
@@ -635,6 +640,7 @@ namespace Crow
                                        }
 
                                        //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);
@@ -644,13 +650,26 @@ namespace Crow
                                                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;
                                                }
@@ -662,7 +681,7 @@ namespace Crow
 
                                        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));;
@@ -670,22 +689,18 @@ namespace Crow
                                                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,
@@ -709,13 +724,17 @@ namespace Crow
                                                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;
@@ -741,6 +760,9 @@ namespace Crow
                                                                pixX += spacePixelWidth * tok2.Length;*/
                                }
                                //gr.Translate (ScrollX, ScrollY);
+                       } catch (Exception e) {
+                               Console.WriteLine(e.Message);
+                               Console.WriteLine(e.StackTrace);
                        } finally {
                                doc.ExitReadLock ();
                        }
index 84cfb3a16ff02abfb07ba8c1c05231a03f023593..a786dc5a014e3b51d373cd5a4dda990c7d5bf458 100644 (file)
@@ -58,7 +58,7 @@ namespace CrowEditBase
                {
                        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)
@@ -118,9 +118,6 @@ namespace CrowEditBase
                }
                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;
@@ -140,7 +137,6 @@ namespace CrowEditBase
                        writeToDisk ();
                }
 
-
                protected override void undo () {
                        editorRWLock.EnterWriteLock ();
                        try {
index 3895519553b47f72b4d7a8babfe40bd6d29588f3..a48dd48a8359061eea743d867393f3a1f72c2501 100644 (file)
@@ -92,6 +92,8 @@ DockWindow {
        Background = "${DockWindowBackground}";
        Margin="0";
        RootDataLevel = "true";
+       HorizontalAlignment = "Center";
+       VerticalAlignment = "Center";
 }
 DockWindow2 {
        Template = "#ui.DockWindow2.template";
@@ -99,6 +101,17 @@ DockWindow2 {
        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";
 }
diff --git a/CrowEditBase/ui/DockWindowToolbar.template b/CrowEditBase/ui/DockWindowToolbar.template
new file mode 100644 (file)
index 0000000..78322ad
--- /dev/null
@@ -0,0 +1,7 @@
+<?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
diff --git a/CrowEditBase/ui/SimpleStatus.template b/CrowEditBase/ui/SimpleStatus.template
new file mode 100644 (file)
index 0000000..9b124d3
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Label Background="{./Background}"/>
\ No newline at end of file
index 02b65436d170784934b73df01aaa7e59a1b6e405..321014a9b19522bc5bf20278e25f99dc49669357 100644 (file)
@@ -12,7 +12,7 @@
                                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"/>
@@ -21,7 +21,7 @@
                        <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>
index 1519a75d48fd513aba5831db673c2f0ac0a9e68b..fad6b30f0cc0e3197da77dd7af7c76361f38e94a 100644 (file)
@@ -41,7 +41,7 @@ namespace CECrowPlugin
 
                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);
                }
@@ -49,47 +49,65 @@ namespace CECrowPlugin
                        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) {
@@ -108,17 +126,17 @@ namespace CECrowPlugin
                                                }
                                        }
                                }
-                       } 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) {
index dfcb8b8dde46a852ff99175033518fb3c86e103b..47f589d146abc3b151850499930faa194658d302 100644 (file)
@@ -24,7 +24,6 @@ namespace CECrowPlugin.Style
 
                public override void Process () {
                        StyleDocument doc = source as StyleDocument;
-                       Exceptions = new List<SyntaxException> ();
                        currentNode = new StyleRootSyntax (doc);
                        currentLine = 0;
                        Span<Token> toks = source.Tokens;
@@ -52,8 +51,8 @@ namespace CECrowPlugin.Style
                                tokIdx++;
                        }
                        while (currentNode.Parent != null) {
-                               if (!currentNode.LastTokenOffset.HasValue)
-                                       storeCurrentNode (-1);
+                               if (!currentNode.TokenCount.HasValue)
+                                       setEndLineForCurrentNode (-1);
                                else
                                        currentNode = currentNode.Parent;
                        }
index b0af947b4d7c2e6958772e1baae746b2d928d17f..02d976b0db8d67e1d97301d059717b30906be0ca 100644 (file)
@@ -37,11 +37,20 @@ namespace CrowEdit.Ebnf
                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);
 
                }
        }
index f29c291043f144d2c2cd7f891ab98350c3268279..af47d3c49682d575777de283cb885e4622e2dd67 100644 (file)
@@ -8,84 +8,91 @@ using CrowEditBase;
 
 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;
 
@@ -128,7 +135,7 @@ namespace CrowEdit.Ebnf
                        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 ();
@@ -193,7 +200,7 @@ namespace CrowEdit.Ebnf
                                                        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));
@@ -233,22 +240,22 @@ namespace CrowEdit.Ebnf
                                        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 ();
@@ -257,7 +264,7 @@ namespace CrowEdit.Ebnf
                                                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)
@@ -295,10 +302,10 @@ namespace CrowEdit.Ebnf
                                                                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");
@@ -329,7 +336,7 @@ namespace CrowEdit.Ebnf
                                                                                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));
diff --git a/plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxNodes.cs b/plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxNodes.cs
new file mode 100644 (file)
index 0000000..c6615d0
--- /dev/null
@@ -0,0 +1,95 @@
+// 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
index 40e7d633a31a441f6ebeb1e3fd2ed5787cd801c1..1056ec2050a696d9cf807e53806b3cf0e2bd7880 100644 (file)
@@ -22,12 +22,12 @@ namespace CrowEdit.Ebnf
                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,// '-'
index 01a5435339d6d6e8780d0723a1e6f3cea17f5b6d..f852d3b3bb2f3874214866495cb090de1b64def0 100644 (file)
@@ -89,13 +89,19 @@ namespace CrowEdit.Ebnf
                                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();
@@ -111,11 +117,11 @@ namespace CrowEdit.Ebnf
                                        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();
@@ -133,15 +139,15 @@ namespace CrowEdit.Ebnf
                                        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);
index 4319909e75a961d9dabcec4a3f5fe8ca4c63556f..ad63b3b53524fa60e901f88978f6f0ee7ff8dee2 100644 (file)
@@ -6,23 +6,6 @@ using CrowEditBase;
 
 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;
diff --git a/plugins/CEEbnfPlugin/src/Parsing/SyntaxNodes.cs b/plugins/CEEbnfPlugin/src/Parsing/SyntaxNodes.cs
deleted file mode 100644 (file)
index 17036ca..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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
index 130890bb7ec68e99c084cdadaa74e95778f9cfdf..8bb379aab7f5e09988e417315bb12dd97d30f84a 100644 (file)
@@ -1,12 +1,20 @@
 <?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>
index 30a769495dd73a29d92adbdc140bb3b85562542e..2c6a545dd99e43bd6c95221544096c14805823ae 100644 (file)
@@ -15,12 +15,16 @@ namespace CERoslynPlugin
        }
        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);
                }
        }
diff --git a/plugins/CEXmlPlugin/src/Parsing/SyntaxAnalyser.cs b/plugins/CEXmlPlugin/src/Parsing/SyntaxAnalyser.cs
deleted file mode 100644 (file)
index 7450155..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// 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
diff --git a/plugins/CEXmlPlugin/src/Parsing/SyntaxNodes.cs b/plugins/CEXmlPlugin/src/Parsing/SyntaxNodes.cs
deleted file mode 100644 (file)
index 166f09d..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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
index 791813662ad1ef8ad21455b0bf47fb6226c573f9..09ef50961b57baa0cc78310ad71a94479392db83 100644 (file)
@@ -6,6 +6,7 @@ using Crow.Text;
 using System.Collections;
 using CrowEditBase;
 using Drawing2D;
+using System.Collections.Generic;
 
 namespace CrowEdit.Xml
 {
@@ -24,10 +25,16 @@ 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) {
@@ -39,13 +46,68 @@ namespace CrowEdit.Xml
                        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(
@@ -53,14 +115,14 @@ namespace CrowEdit.Xml
                                                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)
@@ -83,5 +145,6 @@ namespace CrowEdit.Xml
                        return Colors.Red;
 
                }
+               protected bool previousTokHasFlag(XmlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
        }
 }
\ No newline at end of file
diff --git a/plugins/CEXmlPlugin/src/Parsing/XmlSyntaxAnalyser.cs b/plugins/CEXmlPlugin/src/Parsing/XmlSyntaxAnalyser.cs
new file mode 100644 (file)
index 0000000..c56ade2
--- /dev/null
@@ -0,0 +1,139 @@
+// 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
diff --git a/plugins/CEXmlPlugin/src/Parsing/XmlSyntaxNodes.cs b/plugins/CEXmlPlugin/src/Parsing/XmlSyntaxNodes.cs
new file mode 100644 (file)
index 0000000..892347f
--- /dev/null
@@ -0,0 +1,74 @@
+// 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
index a1377a349e0544b2408609d6f9cd8d4ede496396..051d6c53f79fda0fbfcc3f934687f054ab9cef3a 100644 (file)
@@ -94,7 +94,7 @@ namespace CrowEdit
                        saveLogsConfig ();
                        saveWinConfigs ();
                }
-               DockStack mainDock;
+               
                public Command CMDSave, CMDSaveAs, CMDQuit, CMDHelp, CMDAbout, CMDOptions;
 
                void initCommands (){
@@ -138,50 +138,7 @@ namespace CrowEdit
                        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;
index 8734e7d65640ce2b97a88b76284668d466249939..b81176e399771ae98a48be63449badbdc934640d 100644 (file)
@@ -1,5 +1,5 @@
 <?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>
index b00d43ae3192685467a5210d13e15f67df9aa431..b6c6722a5d8c68625721f91e08e6e7eef6fe733d 100644 (file)
@@ -1,5 +1,5 @@
 <?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"
index de66b595d0de124bf2863127bd9e1d22b803dc0f..80cedd339f946295b11f02e7646020d62fbbd94f 100644 (file)
@@ -1,5 +1,5 @@
 <?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}">
index 2b86351a9726150ce17246850be1d9f34cfe19f6..f94e69d9b2b221e2cff687438d739d07fa2c03f2 100644 (file)
@@ -1,5 +1,5 @@
 <?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">
index e60c384d8818e151ce3615327b278e5899ba0b5f..d2e113f89342f57e7b80d0443367afb93d758251 100644 (file)
                                        </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>