예제 #1
0
 private static void Output(ColoredCharacter[] result, ref int index, string value, ConsoleColor color)
 {
     for (var i = 0; i < value.Length; i++, index++)
     {
         result[index] = new ColoredCharacter(value[i], color);
     }
 }
예제 #2
0
        public ColoredCharacter[] Highlight(string line)
        {
            var index  = 0;
            var result = new ColoredCharacter[line.Length];

            while (index < line.Length)
            {
                switch (_state)
                {
                case TokenState.None:
                    ColorNone(line, result, ref index);
                    break;

                case TokenState.MultiComment:
                    ColorMultiComment(line, result, ref index);
                    break;

                case TokenState.String:
                    ColorString(line, result, ref index);
                    break;
                }
            }

            return(result);
        }
예제 #3
0
        private void ColorMultiComment(string line, ColoredCharacter[] result, ref int index)
        {
            while (_multiCommentDepth > 0)
            {
                if (index >= line.Length)
                {
                    return;
                }

                if (OutputIfNext(line, result, ref index, "/*", CommentColor))
                {
                    _multiCommentDepth++;
                    continue;
                }

                if (OutputIfNext(line, result, ref index, "*/", CommentColor))
                {
                    _multiCommentDepth--;
                    continue;
                }

                result[index] = new ColoredCharacter(line[index], CommentColor);
                index++;
            }

            _state = TokenState.None;
        }
예제 #4
0
        private void ColorString(string line, ColoredCharacter[] result, ref int index)
        {
            while (index < line.Length)
            {
                var ch = line[index];

                if (ch == '\\' && index + 1 < line.Length && line[index + 1] == _stringTerminator)
                {
                    result[index + 0] = new ColoredCharacter('\\', StringColor);
                    result[index + 1] = new ColoredCharacter(_stringTerminator, StringColor);
                    index            += 2;
                    continue;
                }

                result[index] = new ColoredCharacter(ch, StringColor);
                index++;

                if (ch == _stringTerminator)
                {
                    _state            = TokenState.None;
                    _stringTerminator = '\0';
                    return;
                }
            }
        }
예제 #5
0
        public ColoredCharacter[] Highlight(string line)
        {
            var index = 0;
            var result = new ColoredCharacter[line.Length];

            while (index < line.Length)
            {
                switch (_state)
                {
                    case TokenState.None:
                        ColorNone(line, result, ref index);
                        break;

                    case TokenState.MultiComment:
                        ColorMultiComment(line, result, ref index);
                        break;

                    case TokenState.String:
                        ColorString(line, result, ref index);
                        break;
                }
            }

            return result;
        }
예제 #6
0
        private void ColorNone(string line, ColoredCharacter[] result, ref int index)
        {
            while (index < line.Length)
            {
                if (OutputIfNext(line, result, ref index, "//", CommentColor))
                {
                    for (var i = index; i < line.Length; i++, index++)
                    {
                        result[i] = new ColoredCharacter(line[i], CommentColor);
                    }

                    return;
                }

                if (OutputIfNext(line, result, ref index, "/*", CommentColor))
                {
                    _state             = TokenState.MultiComment;
                    _multiCommentDepth = 1;
                    return;
                }

                var ch = line[index];

                if (OutputIfNext(line, result, ref index, "\"", StringColor) ||
                    OutputIfNext(line, result, ref index, "\'", StringColor))
                {
                    _state            = TokenState.String;
                    _stringTerminator = ch;
                    return;
                }

                if (Operators.TryGetValue(ch, out var operators))
                {
                    var idx = index;
                    var op  = operators.FirstOrDefault(s => IsNext(line, idx, s));

                    if (op != null)
                    {
                        Output(result, ref index, op, OperatorColor);
                        continue;
                    }
                }

                if (char.IsLetter(ch) || ch == '_' || ch == '`')
                {
                    var start = index;

                    var isBacktick = ch == '`';

                    if (isBacktick)
                    {
                        index++; // opening backtick
                    }
                    while (index < line.Length && (char.IsLetterOrDigit(line[index]) || line[index] == '_'))
                    {
                        index++;
                    }

                    if (isBacktick && index < line.Length && line[index] == '`')
                    {
                        index++; // closing backtick
                    }
                    var word = line.Substring(start, index - start);
                    index = start;

                    if (isBacktick)
                    {
                        Output(result, ref index, word, OperatorColor);
                        continue;
                    }

                    if (Keywords.Contains(word))
                    {
                        Output(result, ref index, word, KeywordColor);
                        continue;
                    }

                    Output(result, ref index, word, IdentifierColor);
                    continue;
                }

                if (char.IsDigit(ch))
                {
                    var format     = NumberFormat.Decimal;
                    var hasDecimal = false;
                    var hasExp     = false;
                    var justTake   = false;

                    if (ch == '0' && index + 1 < line.Length)
                    {
                        var nextChar = line[index + 1];

                        if (nextChar == 'x' || nextChar == 'X')
                        {
                            format = NumberFormat.Hexadecimal;
                        }

                        if (nextChar == 'b' || nextChar == 'B')
                        {
                            format = NumberFormat.Binary;
                        }

                        if (format != NumberFormat.Decimal)
                        {
                            if (index + 2 < line.Length && line[index + 2] == '_')
                            {
                                result[index++] = new ColoredCharacter('0', NumberColor);
                                continue;
                            }

                            result[index + 0] = new ColoredCharacter('0', NumberColor);
                            result[index + 1] = new ColoredCharacter(nextChar, NumberColor);
                            index            += 2;
                        }
                    }

                    bool IsDigit(char c) =>
                    char.IsDigit(c) || (format == NumberFormat.Hexadecimal && HexChars.Contains(c));

                    while (index < line.Length)
                    {
                        var c = line[index];

                        if (justTake)
                        {
                            justTake        = false;
                            result[index++] = new ColoredCharacter(c, NumberColor);
                            continue;
                        }

                        if (c == '_' && (index + 1 < line.Length && IsDigit(line[index + 1])))
                        {
                            result[index++] = new ColoredCharacter(c, NumberColor);
                            continue;
                        }

                        if (format == NumberFormat.Decimal)
                        {
                            if (c == '.' && !hasDecimal && !hasExp)
                            {
                                hasDecimal = true;

                                if (index + 1 >= line.Length || !IsDigit(line[index + 1]))
                                {
                                    break;
                                }

                                result[index++] = new ColoredCharacter(c, NumberColor);
                                continue;
                            }

                            if ((c == 'e' || c == 'E') && !hasExp)
                            {
                                if (index + 1 < line.Length)
                                {
                                    var next = line[index + 1];
                                    if (next == '+' || next == '-')
                                    {
                                        justTake = true;
                                    }
                                }

                                hasExp          = true;
                                result[index++] = new ColoredCharacter(c, NumberColor);
                                continue;
                            }
                        }

                        if (!IsDigit(c))
                        {
                            break;
                        }

                        result[index++] = new ColoredCharacter(c, NumberColor);
                    }

                    continue;
                }

                result[index] = new ColoredCharacter(line[index], OtherColor);
                index++;
            }
        }
예제 #7
0
        private static Highlighter Redraw()
        {
            var inputString    = new string(_input.ToArray());
            var newHighlighter = _originalHighlighter.Clone();
            var currentColors  = newHighlighter.Highlight(inputString);

            SavePosition();

            var length = Math.Max(currentColors.Length, _previousColors.Length);

            int start = 0;

            for (; start < length; start++)
            {
                if (start >= _previousColors.Length || start >= currentColors.Length)
                {
                    break;
                }

                var prev = _previousColors[start];
                var curr = currentColors[start];

                if (prev.Character != curr.Character || prev.Color != curr.Color)
                {
                    break;
                }
            }

            Move(-_position + start);

            ConsoleColor?prevColor = null;

            for (var i = start; i < length; i++)
            {
                var curr = new ColoredCharacter(' ', ConsoleColor.Gray);

                if (i < currentColors.Length)
                {
                    curr = currentColors[i];
                }

                if (!prevColor.HasValue || prevColor.Value != curr.Color)
                {
                    Console.ForegroundColor = curr.Color;
                }

                prevColor = curr.Color;

                Console.Write(curr.Character);
                _position++;

                if (Console.CursorLeft == Console.BufferWidth - 1 && Console.CursorTop == Console.BufferHeight - 1)
                {
                    Console.WriteLine();
                    Move(-1);
                    _position++;
                }
            }

            RestorePosition();

            _previousColors = currentColors;
            return(newHighlighter);
        }
예제 #8
0
        private void ColorString(string line, ColoredCharacter[] result, ref int index)
        {
            while (index < line.Length)
            {
                var ch = line[index];

                if (ch == '\\' && index + 1 < line.Length && line[index + 1] == _stringTerminator)
                {
                    result[index + 0] = new ColoredCharacter('\\', StringColor);
                    result[index + 1] = new ColoredCharacter(_stringTerminator, StringColor);
                    index += 2;
                    continue;
                }

                result[index] = new ColoredCharacter(ch, StringColor);
                index++;

                if (ch == _stringTerminator)
                {
                    _state = TokenState.None;
                    _stringTerminator = '\0';
                    return;
                }
            }
        }
예제 #9
0
        private void ColorNone(string line, ColoredCharacter[] result, ref int index)
        {
            while (index < line.Length)
            {
                if (OutputIfNext(line, result, ref index, "//", CommentColor))
                {
                    for (var i = index; i < line.Length; i++, index++)
                    {
                        result[i] = new ColoredCharacter(line[i], CommentColor);
                    }

                    return;
                }

                if (OutputIfNext(line, result, ref index, "/*", CommentColor))
                {
                    _state = TokenState.MultiComment;
                    _multiCommentDepth = 1;
                    return;
                }

                var ch = line[index];

                if (OutputIfNext(line, result, ref index, "\"", StringColor) ||
                    OutputIfNext(line, result, ref index, "\'", StringColor))
                {
                    _state = TokenState.String;
                    _stringTerminator = ch;
                    return;
                }

                string[] operators;
                if (Operators.TryGetValue(ch, out operators))
                {
                    var idx = index;
                    var op = operators.FirstOrDefault(s => IsNext(line, idx, s));

                    if (op != null)
                    {
                        Output(result, ref index, op, OperatorColor);
                        continue;
                    }
                }

                if (char.IsLetter(ch) || ch == '_')
                {
                    var start = index;

                    while (index < line.Length && (char.IsLetterOrDigit(line[index]) || line[index] == '_'))
                    {
                        index++;
                    }

                    var word = line.Substring(start, index - start);
                    index = start;

                    if (Keywords.Contains(word))
                    {
                        Output(result, ref index, word, KeywordColor);
                        continue;
                    }

                    Output(result, ref index, word, IdentifierColor);
                    continue;
                }

                if (char.IsDigit(ch))
                {
                    var format = NumberFormat.Decimal;
                    var hasDecimal = false;
                    var hasExp = false;
                    var justTake = false;

                    if (ch == '0' && index + 1 < line.Length)
                    {
                        var nextChar = line[index + 1];

                        if (nextChar == 'x' || nextChar == 'X')
                            format = NumberFormat.Hexadecimal;

                        if (nextChar == 'b' || nextChar == 'B')
                            format = NumberFormat.Binary;

                        if (format != NumberFormat.Decimal)
                        {
                            if (index + 2 < line.Length && line[index + 2] == '_')
                            {
                                result[index++] = new ColoredCharacter('0', NumberColor);
                                continue;
                            }

                            result[index + 0] = new ColoredCharacter('0', NumberColor);
                            result[index + 1] = new ColoredCharacter(nextChar, NumberColor);
                            index += 2;
                        }
                    }

                    Func<char, bool> isDigit = c => char.IsDigit(c) || (format == NumberFormat.Hexadecimal && HexChars.Contains(c));

                    while (index < line.Length)
                    {
                        var c = line[index];

                        if (justTake)
                        {
                            justTake = false;
                            result[index++] = new ColoredCharacter(c, NumberColor);
                            continue;
                        }

                        if (c == '_' && (index + 1 < line.Length && isDigit(line[index + 1])))
                        {
                            result[index++] = new ColoredCharacter(c, NumberColor);
                            continue;
                        }

                        if (format == NumberFormat.Decimal)
                        {
                            if (c == '.' && !hasDecimal && !hasExp)
                            {
                                hasDecimal = true;

                                if (index + 1 >= line.Length || !isDigit(line[index + 1]))
                                    break;

                                result[index++] = new ColoredCharacter(c, NumberColor);
                                continue;
                            }

                            if ((c == 'e' || c == 'E') && !hasExp)
                            {
                                if (index + 1 < line.Length)
                                {
                                    var next = line[index + 1];
                                    if (next == '+' || next == '-')
                                        justTake = true;
                                }

                                hasExp = true;
                                result[index++] = new ColoredCharacter(c, NumberColor);
                                continue;
                            }
                        }

                        if (!isDigit(c))
                            break;

                        result[index++] = new ColoredCharacter(c, NumberColor);
                    }

                    continue;
                }

                result[index] = new ColoredCharacter(line[index], OtherColor);
                index++;
            }
        }
예제 #10
0
        private void ColorMultiComment(string line, ColoredCharacter[] result, ref int index)
        {
            while (_multiCommentDepth > 0)
            {
                if (index >= line.Length)
                    return;

                if (OutputIfNext(line, result, ref index, "/*", CommentColor))
                {
                    _multiCommentDepth++;
                    continue;
                }

                if (OutputIfNext(line, result, ref index, "*/", CommentColor))
                {
                    _multiCommentDepth--;
                    continue;
                }

                result[index] = new ColoredCharacter(line[index], CommentColor);
                index++;
            }

            _state = TokenState.None;
        }
예제 #11
0
        private static bool OutputIfNext(string line, ColoredCharacter[] result, ref int index, string value, ConsoleColor color)
        {
            var isNext = IsNext(line, index, value);

            if (isNext)
                Output(result, ref index, value, color);

            return isNext;
        }
예제 #12
0
 private static void Output(ColoredCharacter[] result, ref int index, string value, ConsoleColor color)
 {
     for (var i = 0; i < value.Length; i++, index++)
     {
         result[index] = new ColoredCharacter(value[i], color);
     }
 }