From: Jean-Philippe Bruyère Date: Mon, 26 Feb 2018 01:30:11 +0000 (+0100) Subject: design mode, crowide wip, style parser (nok) X-Git-Tag: 0.7.3~4^2~41 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=fb8665226c737859d0458c984972d8e630741475;p=jp%2Fcrow.git design mode, crowide wip, style parser (nok) --- diff --git a/Crow.csproj b/Crow.csproj index 6a4c56b3..41e556f8 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -32,7 +32,7 @@ true false $(SolutionDir)build\Debug - DEBUG_UPDATE0;DEBUG_FOCUS0;DEBUG_DISPOSE0;DEBUG_LAYOUTING0;TRACE0;DEBUG;MEASURE_TIME;DEBUG_LOAD;DEBUG_BINDING0;DEBUG_CLIP_RECTANGLE0 + DESIGN_MODE;DEBUG_UPDATE0;DEBUG_FOCUS0;DEBUG_DISPOSE0;DEBUG_LAYOUTING0;TRACE0;DEBUG;MEASURE_TIME;DEBUG_LOAD0;DEBUG_BINDING0;DEBUG_CLIP_RECTANGLE0 true diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index 1f6b3c8a..566a1e69 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -28,6 +28,8 @@ prompt 4 false + $(SolutionDir)build\obj\$(Configuration) + $(SolutionDir)build\$(Configuration) none @@ -35,6 +37,8 @@ prompt 0 false + $(SolutionDir)build\obj\$(Configuration) + $(SolutionDir)build\$(Configuration) Program @@ -112,6 +116,7 @@ + @@ -158,6 +163,9 @@ Crow.MenuItem.template + + + diff --git a/CrowIDE/src/ImlVisualEditor.cs b/CrowIDE/src/ImlVisualEditor.cs index 74187b2e..3d59e9be 100644 --- a/CrowIDE/src/ImlVisualEditor.cs +++ b/CrowIDE/src/ImlVisualEditor.cs @@ -88,7 +88,9 @@ namespace Crow.Coding set { if (HoverWidget == value) return; + imlVE.HoverWidget = value; + NotifyValueChanged ("HoverWidget", HoverWidget); } } @@ -131,8 +133,12 @@ namespace Crow.Coding return; imlError = value; NotifyValueChanged ("IMLError", imlError); + NotifyValueChanged ("HasError", HasError); } } + [XmlIgnore]public bool HasError { + get { return imlError != null; } + } void reload(){ if (projectItem == null) @@ -147,7 +153,8 @@ namespace Crow.Coding imlVE.LoadIMLFragment(projectItem.Source); IMLError = null; } catch (Exception ex) { - IMLError = ex; + IMLError = ex.InnerException; + Console.WriteLine (ex.ToString ()); } } @@ -207,6 +214,12 @@ namespace Crow.Coding { //base.onMouseDown (sender, e); SelectedItem = HoverWidget; + + if (SelectedItem != null && projectItem != null) { + projectItem.CurrentLine = HoverWidget.design_line; + projectItem.CurrentColumn = HoverWidget.design_column; + } + } protected override void onDraw (Cairo.Context gr) { diff --git a/CrowIDE/src/Project.cs b/CrowIDE/src/Project.cs index 098cfdd2..1cbdecbf 100644 --- a/CrowIDE/src/Project.cs +++ b/CrowIDE/src/Project.cs @@ -73,11 +73,7 @@ namespace Crow.Coding } } public bool IsStartupProject { - get { - bool result = solution.StartupProject == this; - System.Diagnostics.Debug.WriteLine ("is startup project tested for {0} => {1}", this.ProjectGuid, result); - return result; - } + get { return solution.StartupProject == this; } } public string Path { get { return System.IO.Path.Combine (solution.SolutionFolder, solutionProject.RelativePath.Replace('\\','/')); } @@ -327,8 +323,11 @@ namespace Crow.Coding } parameters.ReferencedAssemblies.Add (pi.Path); string fullHintPath = System.IO.Path.GetFullPath(System.IO.Path.Combine (RootDir, pi.HintPath.Replace('\\','/'))); - if (File.Exists(fullHintPath)) - File.Copy (fullHintPath, System.IO.Path.Combine(outputDir, System.IO.Path.GetFileName(fullHintPath))); + if (File.Exists (fullHintPath)) { + string outPath = System.IO.Path.Combine (outputDir, System.IO.Path.GetFileName (fullHintPath)); + if (!File.Exists(outPath)) + File.Copy (fullHintPath, outPath); + } } parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/System.Core.dll"; parameters.CompilerOptions += " /reference:/usr/lib/mono/4.5/mscorlib.dll"; diff --git a/CrowIDE/src/ProjectNodes.cs b/CrowIDE/src/ProjectNodes.cs index ac2602e3..c668cfd3 100644 --- a/CrowIDE/src/ProjectNodes.cs +++ b/CrowIDE/src/ProjectNodes.cs @@ -42,7 +42,11 @@ namespace Crow.Coding Compile, EmbeddedResource, } - + public enum CopyToOutputState { + Never, + Always, + PreserveNewest + } public class ProjectNode : IValueChange { #region IValueChange implementation @@ -137,21 +141,23 @@ namespace Crow.Coding } } } - public enum CopyToOutputState { - Never, - Always, - PreserveNewest - } - public class ProjectFile : ProjectItem { - bool isDirty = false; + + public class ProjectFile : ProjectItem { bool isOpened = false; -// bool isSelected = false; DateTime accessTime; string source; + string origSource; object selectedItem; + public List Commands; - public ProjectFile (ProjectItem pi) : base (pi.Project, pi.node){ + public ProjectFile (ProjectItem pi) : base (pi.Project, pi.node){ + Commands = new List (new Crow.Command[] { + new Crow.Command(new Action(() => Open())) + { Caption = "Open", Icon = new SvgPicture("#Crow.Coding.ui.icons.outbox.svg"), CanExecute = false}, + new Crow.Command(new Action(() => Save())) + { Caption = "Save", Icon = new SvgPicture("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false}, + }); } public string ResourceID { @@ -169,14 +175,9 @@ namespace Crow.Coding } public string Source { get { - if (!isOpened) { - accessTime = System.IO.File.GetLastWriteTime (AbsolutePath); - using (StreamReader sr = new StreamReader (AbsolutePath)) { - source = sr.ReadToEnd (); - } - isOpened = true; - isDirty = false; - } else { + if (!isOpened) + Open (); + else { if (DateTime.Compare ( accessTime, System.IO.File.GetLastWriteTime (AbsolutePath)) < 0) @@ -189,9 +190,31 @@ namespace Crow.Coding return; source = value; NotifyValueChanged ("Source", source); + NotifyValueChanged ("IsDirty", IsDirty); + } + } + public bool IsDirty { + get { return source != origSource; } + } + int curLine, curColumn; + public int CurrentColumn{ + get { return curColumn; } + set { + if (curColumn == value) + return; + curColumn = value; + NotifyValueChanged ("CurrentColumn", curColumn); + } + } + public int CurrentLine{ + get { return curLine; } + set { + if (curLine == value) + return; + curLine = value; + NotifyValueChanged ("CurrentLine", curLine); } } - // public bool IsSelected { // get { return isSelected; } // set { @@ -212,16 +235,36 @@ namespace Crow.Coding NotifyValueChanged ("SelectedItem", selectedItem); } } + public CopyToOutputState CopyToOutputDirectory { get { XmlNode xn = node.SelectSingleNode ("CopyToOutputDirectory"); - if (xn == null) - return CopyToOutputState.Never; - CopyToOutputState tmp = (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); - return tmp; - //return xn == null ? CopyToOutputState.Never : (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); +// if (xn == null) +// return CopyToOutputState.Never; +// CopyToOutputState tmp = (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); +// return tmp; + return xn == null ? CopyToOutputState.Never : + (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); + } + } + + public void Open () { + accessTime = System.IO.File.GetLastWriteTime (AbsolutePath); + using (StreamReader sr = new StreamReader (AbsolutePath)) { + source = sr.ReadToEnd (); } + isOpened = true; + origSource = source; + NotifyValueChanged ("IsDirty", false); } + public void Save () { + using (StreamWriter sw = new StreamWriter (AbsolutePath)) { + sw.Write (source); + } + origSource = source; + NotifyValueChanged ("IsDirty", false); + } + public void OnQueryClose (object sender, EventArgs e){ Project.solution.CloseItem (this); } diff --git a/CrowIDE/src/Solution.cs b/CrowIDE/src/Solution.cs index 1c1bac70..6746f5d3 100644 --- a/CrowIDE/src/Solution.cs +++ b/CrowIDE/src/Solution.cs @@ -139,11 +139,11 @@ namespace Crow.Coding{ void onSelectedItemChanged (object sender, SelectionChangeEventArgs e){ ProjectItem pi = e.NewValue as ProjectItem; - if (pi == null) - return; - if (openedItems.Contains (pi)) - return; - openedItems.AddElement (pi); + if (pi != null) { + if (!openedItems.Contains (pi)) + openedItems.AddElement (pi); + } + this.SelectedItem = pi; } public void OnCloseTab (object sender, MouseButtonEventArgs e){ diff --git a/CrowIDE/src/SourceEditor/CSharpParser.cs b/CrowIDE/src/SourceEditor/CSharpParser.cs index 7d2e28e5..7d56ce43 100644 --- a/CrowIDE/src/SourceEditor/CSharpParser.cs +++ b/CrowIDE/src/SourceEditor/CSharpParser.cs @@ -1,44 +1,253 @@ using System; using Crow; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Linq; namespace Crow.Coding { public class CSharpParser : Parser { - public new enum TokenType { - Unknown = Parser.TokenType.Unknown, - WhiteSpace = Parser.TokenType.WhiteSpace, - LineComment = Parser.TokenType.LineComment, - BlockComment = Parser.TokenType.BlockComment, - OpenParenth, - CloseParenth, - OpenBlock, - CloseBlock, - StatementEnding, - UnaryOp, - BinaryOp, - Affectation, - StringLiteral, - CharacterLiteral, - DigitalLiteral, - Literal, - Identifier, - Indexer, - Type, - Preprocessor, + #region keywords + string[] keywords = new string[] { + "abstract", + "as", + "ascending", + "async", + "await", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "descending", + "do", + "double", + "dynamic", + "else", + "enum", + "equals", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "from", + "get", + "goto", + "group", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "join", + "let", + "lock", + "long", + "nameof", + "namespace", + "new", + "null", + "object", + "operator", + "orderby", + "out", + "override", + "params", + "partial", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "select", + "set", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "value", + "var", + "virtual", + "void", + "volatile", + "when", + "where", + "while", + "yield " + }; + #endregion + + public enum States + { + init, + BlockComment, + InNameSpace, + InClass, + InMember, + Unknown, } public CSharpParser (CodeBuffer _buffer) : base(_buffer) { } + #region Regular Expression for validity checks + private static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + private static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}"); + private static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + private static Regex rxDecimal = new Regex(@"[0-9]+"); + private static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + #endregion + + #region Character ValidityCheck + public bool nextCharIsValidCharStartName + { + get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); } + } + public bool nextCharIsValidCharName + { + get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); } + } + #endregion + + States curState = States.init; + States savedState = States.init; + public override void ParseCurrentLine () { - throw new NotImplementedException (); + Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + CodeLine cl = buffer [currentLine]; + cl.Tokens = new List (); + + + //retrieve current parser state from previous line + if (currentLine > 0) + curState = (States)buffer[currentLine - 1].EndingState; + else + curState = States.init; + + States previousEndingState = (States)cl.EndingState; + + while (! eol) { + SkipWhiteSpaces (); + + if (eol) + break; + + if (Peek () == '\n') { + if (currentTok != TokenType.Unknown) + throw new ParsingException (this, "Unexpected end of line"); + Read (); + eol = true; + continue; + } + + if (curState == States.BlockComment) { + if (currentTok != TokenType.Unknown) + Debugger.Break (); + + currentTok.Start = CurrentPosition; + currentTok.Type = (Parser.TokenType)TokenType.BlockComment; + currentTok += ReadLineUntil ("*/"); + if (Peek (2) == "*/") { + readToCurrTok (2); + curState = savedState; + } + saveAndResetCurrentTok (); + continue; + } + + switch (Peek()) { + case '#': + readToCurrTok (true); + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.Preprocessor); + break; + case '/': + readToCurrTok (true); + switch (Peek ()) { + case '*': + readToCurrTok (); + currentTok += ReadLine (); + //currentTok.Type = (Parser.TokenType)TokenType.BlockComment; + savedState = curState; + curState = States.BlockComment; + saveAndResetCurrentTok (TokenType.BlockComment); + break; + case '/': + //readToCurrTok (); + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.LineComment); + //currentTok.Type = (Parser.TokenType)TokenType.LineComment; + break; + default: + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.Unknown); + break; + } + break; + default: + if (nextCharIsValidCharStartName) { + readToCurrTok (true); + while (nextCharIsValidCharName) + readToCurrTok (); + + if (keywords.Contains (currentTok.Content)) + saveAndResetCurrentTok (TokenType.Keyword); + else + saveAndResetCurrentTok (TokenType.Identifier); + continue; + } + readToCurrTok (true); + currentTok+=ReadLine (); + saveAndResetCurrentTok (TokenType.Unknown); + break; + } + } + + if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1) + buffer [currentLine + 1].Tokens = null; + + cl.EndingState = (int)curState; } public override void SyntaxAnalysis () { - throw new NotImplementedException (); + RootNode = new Node () { Name = "RootNode", Type="Root" }; } } } diff --git a/CrowIDE/src/SourceEditor/CodeBuffer.cs b/CrowIDE/src/SourceEditor/CodeBuffer.cs index 399d10ab..31739bdc 100644 --- a/CrowIDE/src/SourceEditor/CodeBuffer.cs +++ b/CrowIDE/src/SourceEditor/CodeBuffer.cs @@ -338,7 +338,7 @@ namespace Crow.Coding if (_currentCol > lines [_currentLine].Length) _currentCol = lines [_currentLine].Length; - Debug.WriteLine ("buff cur line: " + _currentLine); + //Debug.WriteLine ("buff cur line: " + _currentLine); PositionChanged.Raise (this, null); } } diff --git a/CrowIDE/src/SourceEditor/Parser.cs b/CrowIDE/src/SourceEditor/Parser.cs index 79dc086f..f3dced9b 100644 --- a/CrowIDE/src/SourceEditor/Parser.cs +++ b/CrowIDE/src/SourceEditor/Parser.cs @@ -3,6 +3,7 @@ using System.IO; using Crow; using System.Collections.Generic; using System.Diagnostics; +using System.Text; namespace Crow.Coding { @@ -16,27 +17,28 @@ namespace Crow.Coding /// see XMLParser for example. /// public enum TokenType { - Unknown, - WhiteSpace, - NewLine, - LineComment, - BlockCommentStart, - BlockComment, - BlockCommentEnd, - Type, - Identifier, - Indexer, - OpenBlock, - CloseBlock, - StatementEnding, - UnaryOp, - BinaryOp, - Affectation, - StringLitteralOpening, - StringLitteralClosing, - StringLitteral, - NumericLitteral, - Preprocessor, + Unknown = 0, + WhiteSpace = 1, + NewLine = 2, + LineComment = 3, + BlockCommentStart = 4, + BlockComment = 5, + BlockCommentEnd = 6, + Type = 7, + Identifier = 8, + Indexer = 9, + OpenBlock = 10, + CloseBlock = 11, + StatementEnding = 12, + UnaryOp = 13, + BinaryOp = 14, + Affectation = 15, + StringLitteralOpening = 16, + StringLitteralClosing = 17, + StringLitteral = 18, + NumericLitteral = 19, + Preprocessor = 20, + Keyword = 21, } #region CTOR @@ -196,6 +198,17 @@ namespace Crow.Coding currentTok = default(Token); } /// + /// Save current token into current TokensLine after having skipped white spaces and raz current token + /// + protected void saveAndResetAfterWhiteSpaceSkipping() { + buffer[currentLine].Tokens.Add (currentTok); + currentTok = default(Token); + if (WpToken == null) + return; + buffer[currentLine].Tokens.Add ((Token)WpToken); + WpToken = null; + } + /// /// read one char and add current token to current TokensLine, current token is reset /// /// Type of the token @@ -213,6 +226,14 @@ namespace Crow.Coding saveAndResetCurrentTok (); } /// + /// Save current tok after having skipped white spaces + /// + /// set the type of the tok + protected void saveAndResetAfterWhiteSpaceSkipping(System.Enum type) { + currentTok.Type = (TokenType)type; + saveAndResetAfterWhiteSpaceSkipping (); + } + /// /// Peek next char, emit '\n' if current column > buffer's line length /// Throw error if eof is true /// @@ -253,10 +274,13 @@ namespace Crow.Coding /// /// string read protected virtual string ReadLine () { - string tmp = ""; - while (!eol) - tmp += Read (); - return tmp; + StringBuilder tmp = new StringBuilder(); + char c = Read (); + while (!eol) { + tmp.Append (c); + c = Read (); + } + return tmp.ToString(); } /// /// read until end expression is reached or end of line. @@ -278,20 +302,30 @@ namespace Crow.Coding return tmp; } /// - /// skip white spaces, but not line break. Save spaces in a WhiteSpace token. + /// skip white spaces, but not line break. Save spaces in a WhiteSpace token and dont + /// save it directely if currentTok is not null /// protected void SkipWhiteSpaces () { - if (currentTok.Type != TokenType.Unknown) - throw new ParsingException (this, "current token should be reset to unknown (0) before skiping white spaces"); + if (WpToken != null) + throw new ParsingException (this, "white space token already pending"); + Token wp = default(Token); while (!eol) { if (!char.IsWhiteSpace (Peek ())||Peek()=='\n') break; - readToCurrTok (currentTok.Type == TokenType.Unknown); - currentTok.Type = TokenType.WhiteSpace; + if (wp.Type == TokenType.Unknown) + wp.Start = CurrentPosition; + wp += Read(); + wp.Type = TokenType.WhiteSpace; } - if (currentTok.Type != TokenType.Unknown) - saveAndResetCurrentTok (); + if (wp.Type == TokenType.Unknown) + return; + wp.End = CurrentPosition; + if (currentTok.Type == TokenType.Unknown) + buffer [currentLine].Tokens.Add (wp); + else + WpToken = wp; } + protected object WpToken = null; #endregion } } \ No newline at end of file diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index 677ba8b7..db83b2ba 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -47,20 +47,26 @@ namespace Crow.Coding #region CTOR public SourceEditor (): base() { - formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.UnitedNationsBlue, Color.Transparent)); + formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.Teal, Color.Transparent)); formatting.Add ((int)XMLParser.TokenType.ElementName, new TextFormatting (Color.DarkBlue, Color.Transparent)); formatting.Add ((int)XMLParser.TokenType.ElementStart, new TextFormatting (Color.Black, Color.Transparent)); formatting.Add ((int)XMLParser.TokenType.ElementEnd, new TextFormatting (Color.Black, Color.Transparent)); formatting.Add ((int)XMLParser.TokenType.ElementClosing, new TextFormatting (Color.Black, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.Affectation, new TextFormatting (Color.Black, Color.Transparent)); formatting.Add ((int)XMLParser.TokenType.AttributeValueOpening, new TextFormatting (Color.Carmine, Color.Transparent)); formatting.Add ((int)XMLParser.TokenType.AttributeValueClosing, new TextFormatting (Color.Carmine, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Color.OrangeRed, Color.Transparent, false, true)); - formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.GreenCrayola, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); + formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Color.TractorRed, Color.Transparent, false, true)); + formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.AoEnglish, Color.Transparent)); + + formatting.Add ((int)Parser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); + formatting.Add ((int)Parser.TokenType.LineComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); + formatting.Add ((int)Parser.TokenType.Affectation, new TextFormatting (Color.Black, Color.Transparent)); + formatting.Add ((int)Parser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent)); parsing.Add (".crow", "Crow.Coding.XMLParser"); + parsing.Add (".template", "Crow.Coding.XMLParser"); + parsing.Add (".cs", "Crow.Coding.CSharpParser"); + parsing.Add (".style", "Crow.Coding.StyleParser"); buffer = new CodeBuffer (); buffer.LineUpadateEvent += Buffer_LineUpadateEvent; @@ -97,20 +103,27 @@ namespace Crow.Coding int leftMargin = 0; //margin used to display line numbers, folding errors,etc... int visibleLines = 1; int visibleColumns = 1; + int firstPrintedLine = -1; + int printedCurrentLine = 0;//Index of the currentline in the PrintedLines array + CodeBuffer buffer; Parser parser; - Color selBackground; - Color selForeground; -// int _currentCol; //0 based cursor position in string -// int _currentLine; - + List PrintedLines;//list of lines visible in the Editor depending on scrolling and folding Dictionary formatting = new Dictionary(); Dictionary parsing = new Dictionary(); + Color selBackground; + Color selForeground; + int selStartCol; + int selEndCol; + protected Rectangle rText; protected FontExtents fe; protected TextExtents te; + + Point mouseLocalPos; + bool doubleClicked = false; #endregion void measureLeftMargin () { @@ -126,7 +139,7 @@ namespace Crow.Coding void findLongestLineAndUpdateMaxScrollX() { buffer.FindLongestVisualLine (); MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns); +// Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns); } /// /// Updates visible line in widget, adapt max scroll y and updatePrintedLines @@ -136,15 +149,15 @@ namespace Crow.Coding NotifyValueChanged ("VisibleLines", visibleLines); updateMaxScrollY (); updatePrintedLines (); - System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines); - System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY); +// System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines); +// System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY); } void updateVisibleColumns(){ visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width - leftMargin)/ fe.MaxXAdvance); MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin); - System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX); +// System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin); +// System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX); } void updateMaxScrollY () { if (parser == null || !foldingEnabled) { @@ -156,14 +169,7 @@ namespace Crow.Coding if (buffer.UnfoldedLines > 0) NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines); } - } - - int firstPrintedLine = -1; - /// - /// list of lines visible in the Editor depending on scrolling and folding - /// - List PrintedLines; - + } void updatePrintedLines () { lock (buffer.EditMutex) { PrintedLines = new List (); @@ -206,6 +212,7 @@ namespace Crow.Coding MaxScrollX = MaxScrollY = 0; PrintedLines = null; RegisterForGraphicUpdate (); + notifyPositionChanged (); } void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e) { @@ -229,6 +236,7 @@ namespace Crow.Coding updatePrintedLines (); updateMaxScrollY (); RegisterForGraphicUpdate (); + notifyPositionChanged (); } void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e) { @@ -245,6 +253,7 @@ namespace Crow.Coding updatePrintedLines (); updateMaxScrollY (); RegisterForGraphicUpdate (); + notifyPositionChanged (); } void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e) { @@ -263,10 +272,13 @@ namespace Crow.Coding findLongestLineAndUpdateMaxScrollX (); RegisterForGraphicUpdate (); + notifyPositionChanged (); } void Buffer_PositionChanged (object sender, EventArgs e) { + RegisterForGraphicUpdate (); updateOnScreenCurLineFromBuffCurLine (); + notifyPositionChanged (); } void Buffer_SelectionChanged (object sender, EventArgs e) @@ -281,6 +293,40 @@ namespace Crow.Coding } #endregion + public int CurrentColumn{ + get { return buffer == null ? 0 : buffer.CurrentColumn+1; } + set { + try { + buffer.CurrentColumn = value - 1; + } catch (Exception ex) { + Console.WriteLine ("Error cur column: " + ex.ToString ()); + } + } + } + public int CurrentLine{ + get { return buffer == null ? 0 : buffer.CurrentLine+1; } + set { + try { + int l = value - 1; + buffer.CurrentLine = l; + if (buffer [l].IsFolded) + buffer.ToogleFolding (l); + } catch (Exception ex) { + Console.WriteLine ("Error cur column: " + ex.ToString ()); + } + } + } + + void notifyPositionChanged (){ + try { + + NotifyValueChanged ("CurrentLine", buffer.CurrentLine+1); + NotifyValueChanged ("CurrentColumn", buffer.CurrentColumn+1); + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + Parser getParserFromExt (string extension) { if (string.IsNullOrEmpty(extension)) return null; @@ -296,10 +342,8 @@ namespace Crow.Coding [XmlAttributeAttribute] public bool PrintLineNumbers { - get { return Configuration.Global.Get ("PrintLineNumbers"); - } - set - { + get { return Configuration.Global.Get ("PrintLineNumbers"); } + set { if (PrintLineNumbers == value) return; Configuration.Global.Set ("PrintLineNumbers", value); @@ -367,81 +411,6 @@ namespace Crow.Coding RegisterForRedraw (); } } - - // [XmlAttributeAttribute][DefaultValue(0)] -// public int CurrentColumn{ -// get { return _currentCol; } -//// set { -//// if (value == _currentCol) -//// return; -//// if (value < 0) -//// _currentCol = 0; -//// else if (value > buffer[_currentLine].PrintableLength) -//// _currentCol = buffer[_currentLine].PrintableLength; -//// else -//// _currentCol = value; -//// -//// buffer.SetBufferPos (CurrentPosition); -//// -//// if (_currentCol < ScrollX) -//// ScrollX = _currentCol; -//// else if (_currentCol >= ScrollX + visibleColumns) -//// ScrollX = _currentCol - visibleColumns + 1; -//// -//// NotifyValueChanged ("CurrentColumn", _currentCol); -//// } -// } -// [XmlAttributeAttribute][DefaultValue(0)] -// public int CurrentLine{ -// get { return _currentLine; } -//// set { -//// if (value == _currentLine) -//// return; -//// if (value >= buffer.LineCount) -//// _currentLine = buffer.LineCount-1; -//// else if (value < 0) -//// _currentLine = 0; -//// else -//// _currentLine = value; -//// -//// if (_currentCol > buffer[_currentLine].PrintableLength) -//// CurrentColumn = buffer[_currentLine].PrintableLength;//buffer.setBufferPos is called inside -//// else -//// buffer.SetBufferPos (CurrentPosition); -//// -////// if (_currentLine < ScrollY) -////// ScrollY = _currentLine; -////// else if (_currentLine >= ScrollY + visibleLines) -////// ScrollY = _currentLine - visibleLines + 1; -//// -//// NotifyValueChanged ("CurrentLine", _currentLine); -//// } -// } -// /// -// /// Current position is in the printed coord system, tabulation chars are replaced with 4 spaces, -// /// while in the buffer, the position holds tabulations as single chars -// /// -// /// The current position. -// [XmlIgnore]public Point CurrentPosition { -// get { return new Point(CurrentColumn, CurrentLine); } -// set { -// _currentCol = value.X; -// _currentLine = value.Y; -// -// if (_currentCol < ScrollX) -// ScrollX = _currentCol; -// else if (_currentCol >= ScrollX + visibleColumns) -// ScrollX = _currentCol - visibleColumns + 1; -//// -//// if (_currentLine < ScrollY) -//// ScrollY = _currentLine; -//// else if (_currentLine >= ScrollY + visibleLines) -//// ScrollY = _currentLine - visibleLines + 1; -// -// NotifyValueChanged ("CurrentColumn", _currentCol); -// NotifyValueChanged ("CurrentLine", _currentLine); -// } -// } // [XmlIgnore]public string SelectedText // { @@ -459,11 +428,6 @@ namespace Crow.Coding printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine); } -// void setCurrentLineFromBuffer () { -// _currentLine = buffer.CurrentLine; -// NotifyValueChanged ("CurrentLine", _currentLine); -// } - public override int ScrollY { get { return base.ScrollY; @@ -476,12 +440,6 @@ namespace Crow.Coding } } - - /// - /// Index of the currentline in the PrintedLines array - /// - int printedCurrentLine = 0; - /// /// Current editor line, when set, update buffer.CurrentLine /// @@ -498,7 +456,7 @@ namespace Crow.Coding printedCurrentLine = visibleLines - 1; }else printedCurrentLine = value; - Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ()); + //Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ()); //update position in buffer buffer.CurrentLine = buffer.IndexOf (PrintedLines[printedCurrentLine]); } @@ -537,6 +495,7 @@ namespace Crow.Coding buffer.CurrentColumn++; return true; } + #region Drawing void drawLine(Context gr, Rectangle cb, int i) { CodeLine cl = PrintedLines[i]; @@ -557,6 +516,7 @@ namespace Crow.Coding mgFg = Color.LightGray; }else if (buffer.CurrentLine == lineIndex) { mgFg = Color.Black; + mgBg = Color.DarkGray; } string strLN = (lineIndex+1).ToString (); gr.SetSourceColor (mgBg); @@ -778,16 +738,8 @@ namespace Crow.Coding updateVisibleColumns (); } - int selStartCol; - int selEndCol; - protected override void onDraw (Context gr) { -// if (!System.Threading.Monitor.TryEnter (buffer.EditMutex)) { -// RegisterForGraphicUpdate (); -// return; -// } - base.onDraw (gr); gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); @@ -826,13 +778,8 @@ namespace Crow.Coding #endregion #region Mouse handling - Point mouseLocalPos; - bool doubleClicked = false; void updateCurrentPos(){ -// if (mouseLocalPos.X < 0) -// CurrentColumn--; -// else PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height)); int curVisualCol = ScrollX + (int)Math.Round ((mouseLocalPos.X - leftMargin) / fe.MaxXAdvance); @@ -1085,8 +1032,6 @@ namespace Crow.Coding break; case Key.F8: toogleFolding (buffer.CurrentLine); -// if (parser != null) -// reparseSource (); break; default: break; @@ -1099,8 +1044,6 @@ namespace Crow.Coding buffer.Insert (e.KeyChar.ToString()); buffer.ResetSelection (); - - //RegisterForGraphicUpdate(); } #endregion } diff --git a/CrowIDE/src/SourceEditor/StyleParser.cs b/CrowIDE/src/SourceEditor/StyleParser.cs new file mode 100644 index 00000000..e699695d --- /dev/null +++ b/CrowIDE/src/SourceEditor/StyleParser.cs @@ -0,0 +1,154 @@ +using System; +using Crow; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Linq; + +namespace Crow.Coding +{ + public class StyleParser : Parser + { + enum States { init, classNames, members } + + public StyleParser (CodeBuffer _buffer) : base(_buffer) + { + } + + #region Regular Expression for validity checks + private static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + private static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}"); + private static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + private static Regex rxDecimal = new Regex(@"[0-9]+"); + private static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + #endregion + + #region Character ValidityCheck + public bool nextCharIsValidCharStartName + { + get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); } + } + public bool nextCharIsValidCharName + { + get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); } + } + #endregion + + States curState = States.classNames; + + public override void ParseCurrentLine () + { + Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + CodeLine cl = buffer [currentLine]; + cl.Tokens = new List (); + WpToken = null; + + //retrieve current parser state from previous line + if (currentLine > 0) + curState = (States)buffer[currentLine - 1].EndingState; + else + curState = States.init; + + States previousEndingState = (States)cl.EndingState; + + while (! eol) { + SkipWhiteSpaces (); + + if (eol) + break; + + if (Peek () == '\n') { + if (currentTok != TokenType.Unknown) + throw new ParsingException (this, "Unexpected end of line"); + Read (); + eol = true; + continue; + } + + switch (Peek()) { + case '/': + readToCurrTok (true); + switch (Peek ()) { + case '/': + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.LineComment); + break; + default: + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.Unknown); + break; + } + break; + case ',': + if (currentTok.Type != TokenType.Identifier || curState == States.members ) + throw new ParsingException (this, "Unexpected char ','"); + saveAndResetAfterWhiteSpaceSkipping (TokenType.Type);//save previous token as class + readToCurrTok (true); + saveAndResetCurrentTok (TokenType.UnaryOp); + curState = States.classNames; + break; + case '{': + if (currentTok.Type != TokenType.Identifier || curState == States.members) + throw new ParsingException (this, "Unexpected char '}'"); + + saveAndResetAfterWhiteSpaceSkipping (TokenType.Type);//save previous token as class + + readToCurrTok (true); + saveAndResetCurrentTok (TokenType.OpenBlock); + curState = States.members; + break; + case '}': + if (curState != States.members) + throw new ParsingException (this, "Unexpected char '}'"); + readToCurrTok (true); + saveAndResetCurrentTok (TokenType.CloseBlock); + curState = States.classNames; + break; + case '=': + if (currentTok.Type != TokenType.Identifier) + throw new ParsingException (this, "Unexpected char '='"); + + saveAndResetAfterWhiteSpaceSkipping ();//save previous token as propertyname + + curState = States.members; + + readToCurrTok (true); + saveAndResetCurrentTok (TokenType.Affectation); + + SkipWhiteSpaces (); + + currentTok+=ReadLineUntil(";"); + saveAndResetCurrentTok (TokenType.StringLitteral); + + if (Peek() != ';') + throw new ParsingException (this, "Expecting ';'"); + readToCurrTok (true); + saveAndResetCurrentTok (TokenType.StatementEnding); + break; + default: + if (currentTok.Type != TokenType.Unknown) + throw new ParsingException (this, "error"); + + if (nextCharIsValidCharStartName) { + readToCurrTok (true); + while (nextCharIsValidCharName) + readToCurrTok (); + } + currentTok.Type = TokenType.Identifier; + currentTok.End = CurrentPosition; + break; + } + } + + if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1) + buffer [currentLine + 1].Tokens = null; + + cl.EndingState = (int)curState; + } + public override void SyntaxAnalysis () + { + RootNode = new Node () { Name = "RootNode", Type="Root" }; + } + } +} + diff --git a/CrowIDE/src/SourceEditor/XMLParser.cs b/CrowIDE/src/SourceEditor/XMLParser.cs index 2a8ffeb1..952e038b 100644 --- a/CrowIDE/src/SourceEditor/XMLParser.cs +++ b/CrowIDE/src/SourceEditor/XMLParser.cs @@ -17,16 +17,16 @@ namespace Crow.Coding BlockCommentStart = Parser.TokenType.BlockCommentStart, BlockComment = Parser.TokenType.BlockComment, BlockCommentEnd = Parser.TokenType.BlockCommentEnd, - Affectation = Parser.TokenType.Affectation, - XMLDecl = Parser.TokenType.Preprocessor, - ElementStart, - ElementEnd, - ElementClosing = Parser.TokenType.StatementEnding, ElementName = Parser.TokenType.Type, AttributeName = Parser.TokenType.Identifier, + ElementClosing = Parser.TokenType.StatementEnding, + Affectation = Parser.TokenType.Affectation, AttributeValueOpening = Parser.TokenType.StringLitteralOpening, AttributeValueClosing = Parser.TokenType.StringLitteralClosing, AttributeValue = Parser.TokenType.StringLitteral, + XMLDecl = Parser.TokenType.Preprocessor, + ElementStart = 50, + ElementEnd = 51, } public enum States @@ -221,10 +221,15 @@ namespace Crow.Coding while (nextCharIsValidCharName) readToCurrTok (); saveAndResetCurrentTok (TokenType.AttributeName); + + SkipWhiteSpaces (); + if (Peek () != '=') throw new ParsingException (this, "Expecting: '='"); readAndResetCurrentTok (TokenType.Affectation, true); + SkipWhiteSpaces (); + char openAttVal = Peek (); if (openAttVal != '"' && openAttVal != '\'') throw new ParsingException (this, "Expecting attribute value enclosed either in '\"' or in \"'\""); @@ -250,7 +255,6 @@ namespace Crow.Coding cl.EndingState = (int)curState; } - public override void SyntaxAnalysis () { RootNode = new Node () { Name = "RootNode", Type="Root" }; diff --git a/CrowIDE/ui/CrowIDE.crow b/CrowIDE/ui/CrowIDE.crow index d963b5e5..d2be368c 100644 --- a/CrowIDE/ui/CrowIDE.crow +++ b/CrowIDE/ui/CrowIDE.crow @@ -32,6 +32,7 @@ +