1+ #region BSD 3-Clause License
2+ // <copyright file="ConsoleSourceMap.cs" company="Edgerunner.org">
3+ // Copyright 2020
4+ // </copyright>
5+ //
6+ // BSD 3-Clause License
7+ //
8+ // Copyright (c) 2020,
9+ // All rights reserved.
10+ //
11+ // Redistribution and use in source and binary forms, with or without
12+ // modification, are permitted provided that the following conditions are met:
13+ //
14+ // 1. Redistributions of source code must retain the above copyright notice, this
15+ // list of conditions and the following disclaimer.
16+ //
17+ // 2. Redistributions in binary form must reproduce the above copyright notice,
18+ // this list of conditions and the following disclaimer in the documentation
19+ // and/or other materials provided with the distribution.
20+ //
21+ // 3. Neither the name of the copyright holder nor the names of its
22+ // contributors may be used to endorse or promote products derived from
23+ // this software without specific prior written permission.
24+ //
25+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28+ // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29+ // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30+ // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31+ // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32+ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33+ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35+ #endregion
36+
37+ using System ;
38+ using System . Collections . Generic ;
39+
40+ using Org . Edgerunner . ANTLR4 . Tools . Common . Grammar ;
41+
42+ namespace Org . Edgerunner . ANTLR4 . Tools . Testing . Grun . SyntaxHighlighting
43+ {
44+ public class ConsoleSourceMap : IConsoleSourceMap
45+ {
46+ /// <summary>
47+ /// Initializes a new instance of the <see cref="ConsoleSourceMap"/> class.
48+ /// </summary>
49+ /// <param name="source">The source text to map.</param>
50+ /// <param name="consoleBufferWidth">Width of the console buffer.</param>
51+ /// <param name="consoleBufferHeight">Height of the console buffer.</param>
52+ /// <exception cref="ArgumentNullException"><paramref name="source"/> must not be null.</exception>
53+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="consoleBufferWidth"/> and <paramref name="consoleBufferHeight"/> must be 1 or greater.</exception>
54+ public ConsoleSourceMap ( string source , int consoleBufferWidth , int consoleBufferHeight )
55+ {
56+ if ( consoleBufferWidth <= 1 )
57+ throw new ArgumentOutOfRangeException ( nameof ( consoleBufferWidth ) ) ;
58+ if ( consoleBufferHeight <= 1 )
59+ throw new ArgumentOutOfRangeException ( nameof ( consoleBufferHeight ) ) ;
60+ Source = source ?? throw new ArgumentNullException ( nameof ( source ) ) ;
61+ ConsoleBufferWidth = consoleBufferWidth ;
62+ ConsoleBufferHeight = consoleBufferHeight ;
63+ LineMap = new Dictionary < int , int > ( ) ;
64+ CreateSourceMapData ( ) ;
65+ }
66+
67+ private void CreateSourceMapData ( )
68+ {
69+ var offset = 0 ;
70+ var sourceLines = Source . Split ( '\r ' , '\n ' ) ;
71+ var start = sourceLines . Length - ConsoleBufferHeight ;
72+ var lastLine = sourceLines . Length ;
73+ for ( int i = start ; i < lastLine ; i ++ )
74+ {
75+ var line = sourceLines [ i ] ;
76+ LineMap . Add ( i + 1 , i + offset ) ;
77+ if ( line . Length > ConsoleBufferWidth )
78+ {
79+ offset += line . Length / ConsoleBufferWidth ;
80+ //offset += (int)Math.Truncate((double)(line.Length / ConsoleBufferWidth));
81+ if ( line . Length % ConsoleBufferWidth == 0 )
82+ offset -- ;
83+ }
84+ }
85+ }
86+
87+ private Dictionary < int , int > LineMap { get ; }
88+
89+ /// <summary>
90+ /// Gets the source text.
91+ /// </summary>
92+ /// <value>The source text.</value>
93+ public string Source { get ; }
94+
95+ /// <summary>
96+ /// Gets the width of the console buffer.
97+ /// </summary>
98+ /// <value>The width of the console buffer.</value>
99+ public int ConsoleBufferWidth { get ; }
100+
101+ /// <summary>
102+ /// Gets the height of the console buffer.
103+ /// </summary>
104+ /// <value>The height of the console buffer.</value>
105+ public int ConsoleBufferHeight { get ; }
106+
107+ /// <inheritdoc/>
108+ /// <exception cref="ArgumentOutOfRangeException">
109+ /// line
110+ /// or
111+ /// column
112+ /// </exception>
113+ public Place TranslateSourcePositionToConsole ( int line , int column )
114+ {
115+ if ( line <= 1 )
116+ throw new ArgumentOutOfRangeException ( nameof ( line ) ) ;
117+ if ( column <= 1 )
118+ throw new ArgumentOutOfRangeException ( nameof ( column ) ) ;
119+
120+ if ( ! LineMap . TryGetValue ( line , out var newLine ) )
121+ return Place . Empty ;
122+
123+ var newColumn = ( column % ConsoleBufferWidth ) - 1 ;
124+
125+ return new Place ( newLine , newColumn ) ;
126+ }
127+ }
128+ }
0 commit comments