]> O.S.I.I.S - jp/crowedit.git/commitdiff
move lines handling in TextBuffer
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 25 Feb 2025 15:47:27 +0000 (16:47 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 25 Feb 2025 15:47:27 +0000 (16:47 +0100)
CrowEditBase/src/Compiler/SourceDocument.cs
CrowEditBase/src/Compiler/SyntaxNode.cs
CrowEditBase/src/Compiler/SyntaxRootNode.cs [new file with mode: 0644]
CrowEditBase/src/Editor.cs
CrowEditBase/src/TextBuffer.cs [new file with mode: 0644]
CrowEditBase/src/TextDocument.cs

index 741db824710e61db1e2eb917b05fdc0abdddaf75..32e75c236f771aa4b2f93cebab82adc97d40e057 100644 (file)
@@ -47,7 +47,6 @@ namespace CrowEditBase
 
                public Token[] Tokens => tokens;
                public IEnumerable<SyntaxNode> SyntaxRootChildNodes => root?.children;
-               public LineCollection Lines => lines;
                public Token FindTokenIncludingPosition (int pos) {
                        if (pos == 0 || tokens == null || tokens.Length == 0)
                                return default;
@@ -65,7 +64,7 @@ namespace CrowEditBase
                /// <summary>
                /// if outermost is true, return oldest ancestor exept root node, useful for folding.
                /// </summary>
-               public SyntaxNode FindNodeIncludingPosition (int pos, bool outerMost = false) {
+               /*public SyntaxNode FindNodeIncludingPosition (int pos, bool outerMost = false) {
                        if (root == null)
                                return null;
                        if (!root.Contains (pos))
@@ -90,14 +89,15 @@ namespace CrowEditBase
                        if (!root.Contains (span))
                                return null;
                        return root.FindNodeIncludingSpan (span);
-               }
+               }*/
+               
                protected override void reloadFromFile () {
                        base.reloadFromFile ();
                        parse ();
                }
                protected override void apply(TextChange change)
                {
-                       SyntaxNode editedNode = FindNodeIncludingSpan (new TextSpan (change.Start, change.End));
+                       SyntaxNode editedNode = root?.FindNodeIncludingSpan (new TextSpan (change.Start, change.End));
 
                        base.apply(change);
 
@@ -153,10 +153,10 @@ namespace CrowEditBase
                }
 
                internal void updateCurrentTokAndNode (CharLocation loc) {
-                       int pos = lines.GetAbsolutePosition(loc);
+                       int pos = buffer.GetAbsolutePosition(loc);
                        if (tokens.Length > 0) {
                                currentTokenIndex = FindTokenIndexIncludingPosition (pos);
-                               CurrentNode = FindNodeIncludingSpan (currentToken.Span);
+                               CurrentNode = root?.FindNodeIncludingSpan (currentToken.Span);
                                NotifyValueChanged ("CurrentTokenString", (object)CurrentTokenString);
                                //NotifyValueChanged ("CurrentTokenType", (uint)(currentToken.Type)>>8);
                                NotifyValueChanged ("CurrentTokenType", (object)GetTokenTypeString(currentToken.Type));
index 0d418649ed8d3707e84cf3ca0619154a2714b7c1..4de25e48b758ded84119cc8ce47e3a17b7191d19 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;
@@ -9,26 +9,6 @@ using Crow;
 
 namespace CrowEditBase
 {
-       public abstract class SyntaxRootNode : SyntaxNode {
-               protected readonly SourceDocument source;
-               public SyntaxRootNode (SourceDocument source) {
-                       this.source = source;
-               }
-               public override int TokenIndexBase => 0;
-               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 < source.Tokens.Length ? Root.GetText(source.Tokens[idx].Span).ToString() : 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 string GetTokenString(Token tok) =>
-                       source.GetText(tok.Span).ToString();
-       }
        public class SyntaxNode : CrowEditComponent {
                internal SyntaxNode () {}
                public SyntaxNode (int startLine, int tokenBase, int? lastTokenIdx = null) {
@@ -37,7 +17,9 @@ namespace CrowEditBase
                        if (lastTokenIdx.HasValue)
                                TokenCount = lastTokenIdx - tokenBase;
                }
+               
                bool _isExpanded;
+
                public bool isExpanded {
                        get => _isExpanded;
                        set {
diff --git a/CrowEditBase/src/Compiler/SyntaxRootNode.cs b/CrowEditBase/src/Compiler/SyntaxRootNode.cs
new file mode 100644 (file)
index 0000000..7955c33
--- /dev/null
@@ -0,0 +1,29 @@
+// 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;
+using Crow.Text;
+
+namespace CrowEditBase
+{
+       public abstract class SyntaxRootNode : SyntaxNode {
+               protected readonly SourceDocument source;
+               public SyntaxRootNode (SourceDocument source) {
+                       this.source = source;
+               }
+               public override int TokenIndexBase => 0;
+               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 < source.Tokens.Length ? Root.GetText(source.Tokens[idx].Span).ToString() : 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 string GetTokenString(Token tok) =>
+                       source.GetText(tok.Span).ToString();
+       }
+}
\ No newline at end of file
index f447ad5749672841e047ede5f001212519e534aa..00f2e37b9f3fd7b1004c01f65a095c129ef1cb15 100644 (file)
@@ -384,7 +384,7 @@ namespace Crow
                                        }
                                //}
 
-                               if (document.Lenght > 0) {
+                               if (document.Length > 0) {
                                        Foreground?.SetAsSource (IFace, gr);
 
                                        TextExtents extents;
@@ -839,7 +839,7 @@ namespace Crow
                                        break;
                                case Key.Delete:
                                        if (selection.IsEmpty) {
-                                               if (selection.Start == document.Lenght)
+                                               if (selection.Start == document.Length)
                                                        return;
                                                if (CurrentLoc.Value.Column >= document.GetLine (CurrentLoc.Value.Line).Length)
                                                        update (new TextChange (selection.Start, document.GetLine (CurrentLoc.Value.Line).LineBreakLength, ""));
diff --git a/CrowEditBase/src/TextBuffer.cs b/CrowEditBase/src/TextBuffer.cs
new file mode 100644 (file)
index 0000000..505098e
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright (c) 2021-2021  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using Crow.Text;
+
+namespace CrowEditBase
+{
+       public class TextBuffer {
+               static int bufferExpension = 100;
+               int length;
+               Memory<char> buffer;
+               ReadOnlyMemory<char> origBuffer;
+               LineCollection lines;
+               public bool mixedLineBreak = false;
+               public string lineBreak = null;
+
+               public Span<char> Span => buffer.Span.Slice(0, length);
+               public ReadOnlySpan<char> ReadOnlySpan => buffer.Span.Slice(0, length);
+               public bool IsEmpty => length == 0;
+               public bool IsDirty => origBuffer.Span.Equals(buffer.Span, StringComparison.Ordinal);
+               public int LinesCount => lines.Count;
+               public int Length => length;
+               public ReadOnlyMemory<char> ReadOnlyCopy {
+                       get {
+                               return ReadOnlySpan.ToArray();
+                       }
+               } 
+               public void ResetDirtyState () {
+                       origBuffer = buffer.ToArray();
+               }
+               public TextBuffer(ReadOnlySpan<char> origText) {
+                       length = origText.Length;
+                       buffer = new char[length + bufferExpension];
+                       origText.CopyTo(buffer.Span);
+                       lines = new LineCollection (10);
+                       if (IsEmpty)
+                               lines.Add (new TextLine (0, 0, 0));
+                       else
+                               lines.Update (Span);
+               }
+               public void Update (TextChange change) {
+                       ReadOnlySpan<char> orig = buffer.Span;
+                       char[] newBuff = null;
+                       Span<char> tmp;
+                       if (buffer.Length < length + change.CharDiff) {
+                               newBuff = new char[length + change.CharDiff + bufferExpension];
+                               tmp = newBuff;
+                               orig.Slice(0, change.Start).CopyTo(tmp);
+                               if (change.CharDiff == 0)
+                                       orig.Slice(change.End, length - change.End).CopyTo(tmp.Slice(change.End));
+                       } else
+                               tmp = buffer.Span;
+                       
+                       if (change.CharDiff != 0)
+                               orig.Slice(change.End, length - change.End).CopyTo(tmp.Slice(change.End2));
+                       if (!string.IsNullOrEmpty (change.ChangedText))
+                               change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start));
+                       
+                       if (newBuff != null)
+                               buffer = newBuff;
+                       length += change.CharDiff;
+
+                       lines.Update (change);
+               }
+               public string GetLineBreak () {
+                       if (string.IsNullOrEmpty (lineBreak)) {
+                               mixedLineBreak = false;
+
+                               if (lines.Count == 0 || lines[0].LineBreakLength == 0)
+                                       lineBreak = Environment.NewLine;
+                               else {
+                                       lineBreak = ReadOnlySpan.GetLineBreak (lines[0]).ToString ();
+                                       for (int i = 1; i < lines.Count; i++) {
+                                               if (!ReadOnlySpan.GetLineBreak (lines[i]).SequenceEqual (lineBreak)) {
+                                                       mixedLineBreak = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       return lineBreak;
+               }
+               public CharLocation GetLocation (int absolutePosition) => lines.GetLocation (absolutePosition);
+               public TextLine GetLine (int index) => lines[index];
+               public int GetAbsolutePosition (CharLocation loc) => lines.GetAbsolutePosition (loc);
+               public CharLocation EndLocation => new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length);
+        public override string ToString() => ReadOnlySpan.ToString();
+    }
+}
\ No newline at end of file
index 9242e5b6739b860032c09ab585768f77ced8ba5e..43f14c27977c40e79459cfdcf6a11212215ad156 100644 (file)
@@ -11,48 +11,10 @@ using Crow.Text;
 using static CrowEditBase.CrowEditBase;
 using System.Collections.Immutable;
 using System.Reflection.Metadata;
+using System.Diagnostics;
 
 namespace CrowEditBase
 {
-       public class TextBuffer {
-               static int bufferExpension = 100;
-               int lenght;
-               Memory<char> buffer;
-               ReadOnlyMemory<char> origBuffer;
-               public Span<char> Span => buffer.Span.Slice(0, lenght);
-               public bool IsEmpty => lenght == 0;
-               public bool IsDirty => origBuffer.Span.Equals(buffer.Span, StringComparison.Ordinal);
-               public void ResetDirtyState () {
-                       origBuffer = buffer.ToArray();
-               }
-               public TextBuffer(ReadOnlySpan<char> origText) {
-                       lenght = origText.Length;
-                       buffer = new char[lenght + bufferExpension];
-                       origText.CopyTo(buffer.Span);
-               }
-               public void Update (TextChange change) {
-                       ReadOnlySpan<char> orig = buffer.Span;
-                       char[] newBuff = null;
-                       Span<char> tmp;
-                       if (buffer.Length < lenght + change.CharDiff) {
-                               newBuff = new char[lenght + change.CharDiff + bufferExpension];
-                               tmp = newBuff;
-                               orig.Slice(0, change.Start).CopyTo(tmp);
-                               if (change.CharDiff == 0)
-                                       orig.Slice(change.End, lenght - change.End).CopyTo(tmp.Slice(change.End));
-                       } else
-                               tmp = buffer.Span;
-                       
-                       if (change.CharDiff != 0)
-                               orig.Slice(change.End, lenght - change.End).CopyTo(tmp.Slice(change.End2));
-                       if (!string.IsNullOrEmpty (change.ChangedText))
-                               change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start));
-                       
-                       if (newBuff != null)
-                               buffer = newBuff;
-                       lenght += change.CharDiff;
-               }               
-       }
        public class TextDocument : Document {
                public TextDocument (string fullPath, string editorPath = "default")
                        : base (fullPath, editorPath) {
@@ -60,19 +22,8 @@ namespace CrowEditBase
                }
 
                protected TextBuffer buffer;
-               public ReadOnlySpan<char> source => buffer.Span;
-
+               public ReadOnlySpan<char> source => buffer.ReadOnlySpan;
                System.Text.Encoding encoding = System.Text.Encoding.UTF8;
-               protected bool mixedLineBreak = false;
-               protected string lineBreak = null;
-
-
-                               
-
-//                             NotifyValueChanged ("IsDirty", IsDirty);
-//                             CMDSave.CanExecute = IsDirty;
-
-               protected LineCollection lines;
 
                public override bool IsDirty => buffer.IsDirty;
                                /// dictionnary of object per document client, when not null, client must reload content of document.
@@ -116,7 +67,6 @@ namespace CrowEditBase
                }
 
 
-
                protected override void writeToDisk () {
                        using (Stream s = new FileStream(FullPath, FileMode.Create)) {
                                using (StreamWriter sw = new StreamWriter (s, encoding))
@@ -134,6 +84,12 @@ namespace CrowEditBase
                                        encoding = sr.CurrentEncoding;
                                }
                        }
+                       ReadOnlyMemory<char> testbuff = buffer.ReadOnlyCopy;
+                       
+                       buffer.Update(new TextChange(0,0,"test"));
+                       
+                       Debug.WriteLine($"buffer: {buffer.ToString()}");
+                       Debug.WriteLine($"testbuff: {testbuff.ToString()}");
                }
                protected override void initNewFile()
                {
@@ -214,7 +170,6 @@ namespace CrowEditBase
                protected virtual void apply (TextChange change) {
 
                        buffer.Update(change);
-                       lines.Update (change);
 
                        NotifyValueChanged ("IsDirty", IsDirty);
                        CMDSave.CanExecute = IsDirty;                   
@@ -235,40 +190,11 @@ namespace CrowEditBase
                protected void onTextChanged (object sender, TextChangeEventArgs e) {
                        applyTextChange (e.Change, sender);
                }
-               protected void getLines () {
-                       documentRWLock.EnterWriteLock ();
-                       if (lines == null)
-                               lines = new LineCollection (10);
-                       else
-                               lines.Clear ();
 
-                       if (buffer.IsEmpty)
-                               lines.Add (new TextLine (0, 0, 0));
-                       else
-                               lines.Update (source);
-                       documentRWLock.ExitWriteLock ();
-               }
                public string GetLineBreak () {
                        documentRWLock.EnterReadLock ();
                        try {
-                               if (string.IsNullOrEmpty (lineBreak)) {
-                                       mixedLineBreak = false;
-
-                                       if (lines.Count == 0 || lines[0].LineBreakLength == 0)
-                                               lineBreak = Environment.NewLine;
-                                       else {
-                                               lineBreak = source.GetLineBreak (lines[0]).ToString ();
-
-                                               for (int i = 1; i < lines.Count; i++) {
-                                                       ReadOnlySpan<char> lb = source.GetLineBreak (lines[i]);
-                                                       if (!lb.SequenceEqual (lineBreak)) {
-                                                               mixedLineBreak = true;
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                               }
-                               return lineBreak;
+                               return buffer.GetLineBreak();
                        } finally {
                                documentRWLock.ExitReadLock();
                        }
@@ -276,7 +202,7 @@ namespace CrowEditBase
                public CharLocation GetLocation (int absolutePosition) {
                        documentRWLock.EnterReadLock ();
                        try {
-                               return lines.GetLocation (absolutePosition);
+                               return buffer.GetLocation (absolutePosition);
                        } finally {
                                documentRWLock.ExitReadLock();
                        }
@@ -284,7 +210,7 @@ namespace CrowEditBase
                public int GetAbsolutePosition (CharLocation loc) {
                        documentRWLock.EnterReadLock ();
                        try {
-                               return lines.GetAbsolutePosition (loc);
+                               return buffer.GetAbsolutePosition (loc);
                        } finally {
                                documentRWLock.ExitReadLock();
                        }
@@ -293,7 +219,7 @@ namespace CrowEditBase
                        get {
                                documentRWLock.EnterReadLock ();
                                try {
-                                       return new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length);
+                                       return buffer.EndLocation;
                                } finally {
                                        documentRWLock.ExitReadLock();
                                }
@@ -301,21 +227,19 @@ namespace CrowEditBase
                }
                public int LinesCount {
                        get {
-                               if (lines == null)
-                                       getLines();
                                documentRWLock.EnterReadLock ();
                                try {
-                                       return lines.Count;
+                                       return buffer.LinesCount;
                                } finally {
                                        documentRWLock.ExitReadLock();
                                }
                        }
                }
-               public int Lenght {
+               public int Length {
                        get {
                                documentRWLock.EnterReadLock ();
                                try {
-                                       return source.Length;
+                                       return buffer.Length;
                                } finally {
                                        documentRWLock.ExitReadLock();
                                }
@@ -324,7 +248,7 @@ namespace CrowEditBase
                public TextLine GetLine (int index) {
                        documentRWLock.EnterReadLock ();
                        try {
-                               return lines[index];
+                               return buffer.GetLine(index);
                        } finally {
                                documentRWLock.ExitReadLock();
                        }
@@ -357,13 +281,13 @@ namespace CrowEditBase
                public virtual CharLocation GetWordStart (CharLocation loc) {
                        documentRWLock.EnterReadLock ();
                        try {
-                               int pos = lines.GetAbsolutePosition (loc);
+                               int pos = buffer.GetAbsolutePosition (loc);
                                //skip white spaces
                                while (pos > 0 && !char.IsLetterOrDigit (source[pos-1]))
                                        pos--;
                                while (pos > 0 && char.IsLetterOrDigit (source[pos-1]))
                                        pos--;
-                               return lines.GetLocation (pos);
+                               return buffer.GetLocation (pos);
                        } finally {
                                documentRWLock.ExitReadLock();
                        }
@@ -371,13 +295,13 @@ namespace CrowEditBase
                public virtual CharLocation GetWordEnd (CharLocation loc) {
                        documentRWLock.EnterReadLock ();
                        try {
-                               int pos = lines.GetAbsolutePosition (loc);
+                               int pos = buffer.GetAbsolutePosition (loc);
                                //skip white spaces
-                               while (pos < Lenght - 1 && !char.IsLetterOrDigit (source[pos]))
+                               while (pos < Length - 1 && !char.IsLetterOrDigit (source[pos]))
                                        pos++;
-                               while (pos < Lenght - 1 && char.IsLetterOrDigit (source[pos]))
+                               while (pos < Length - 1 && char.IsLetterOrDigit (source[pos]))
                                        pos++;
-                               return lines.GetLocation (pos);
+                               return buffer.GetLocation (pos);
                        } finally {
                                documentRWLock.ExitReadLock();
                        }