bovender framework
C# framework that implements MVVM and more
Multiline.cs
1 /* Multiline.cs
2  * part of Daniel's XL Toolbox NG
3  *
4  * Copyright 2014-2018 Daniel Kraus
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 using System;
19 using System.Collections.Generic;
20 using System.Collections.ObjectModel;
21 using System.Linq;
22 using System.Text;
23 using System.Text.RegularExpressions;
24 
25 namespace Bovender.Text
26 {
31  public class Multiline
32  {
33  #region Public properties
34 
38  public string Text
39  {
40  get
41  {
42  if (_dirty)
43  {
44  _text = String.Join(Environment.NewLine, _lines);
45  _dirty = false;
46  }
47  return _text;
48  }
49  }
50 
51  public int NumberOfLines
52  {
53  get
54  {
55  return _lines.Count;
56  }
57  }
58 
63  public bool IgnoreHashedComments { get; set; }
64 
65  #endregion
66 
67  #region Public methods
68 
75  public void Add(string text)
76  {
77  Add(TransformNewLines(text), Environment.NewLine);
78  }
79 
86  public void Add(string text, string newLineSeparator)
87  {
88  foreach (string line in text.Split(
89  new string[] { newLineSeparator }, StringSplitOptions.None))
90  {
91  AddLine(line);
92  }
93  }
94 
99  public void AddLine(string line)
100  {
101  if (IgnoreHashedComments)
102  {
103  line = Regex.Replace(line, @"#.*$", String.Empty);
104  // If the line consisted only of a comment, do not add
105  // an empty line.
106  if (String.IsNullOrEmpty(line)) return;
107  }
108  _dirty = true;
109  line = line.TrimEnd(' ', '\t', '\n', '\r');
110  bool forceNewLine = !HasSameIndent(line);
111  forceNewLine |= String.IsNullOrEmpty(line);
112 
113  forceNewLine |= IsListItem(line);
114  if (forceNewLine || _lines.Count == 0)
115  {
116  _lines.Add(line);
117  }
118  else
119  {
120  _lines[_lines.Count - 1] += " " + line;
121  }
122  }
123 
124  #endregion
125 
126  #region Constructors
127 
128  public Multiline()
129  {
130  _dirty = true;
131  _lines = new Collection<string>();
132  }
133 
134  public Multiline(bool ignoreHashedComments)
135  : this()
136  {
137  IgnoreHashedComments = ignoreHashedComments;
138  }
139 
144  public Multiline(string text)
145  : this()
146  {
147  Add(text);
148  }
149 
150  public Multiline(string text, bool ignoreHashedComments)
151  : this(ignoreHashedComments)
152  {
153  Add(text);
154  }
155 
156  #endregion
157 
158  #region Private methods
159 
165  private bool HasSameIndent(string line)
166  {
167  Regex r = new Regex(@"^(\s+)");
168  Match m = r.Match(line);
169  int indent = (m.Success) ? m.Length : 0;
170  bool isSame = _lastIndent == indent;
171  if (String.IsNullOrEmpty(line))
172  {
173  // If current line is empty, prevent next line from being
174  // appended by setting an impossible indent level.
175  _lastIndent = -1;
176  }
177  else
178  {
179  _lastIndent = indent;
180  }
181  return isSame;
182  }
183 
184  private bool IsListItem(string line)
185  {
186  Regex r = new Regex(@"^\s*(([-*])|(#+|\d+)\.?\)?)\s");
187  Match m = r.Match(line);
188  if (m.Success)
189  {
190  _lastIndent = m.Length;
191  return true;
192  }
193  else
194  {
195  return false;
196  }
197  }
198 
206  private string TransformNewLines(string text)
207  {
208  // Transform everything to "\r\n" first.
209  string result = Regex.Replace(text, @"\n\r", "\r\n");
210  result = Regex.Replace(result, @"(?<!\r)\n", "\r\n");
211  result = Regex.Replace(result, @"\r(?!\n)", "\r\n");
212 
213  // Transform the "\r\n" sequences to the one used by the
214  // current environment, but only if it is different.
215  if (Environment.NewLine != "\r\n")
216  {
217  result = Regex.Replace(result, @"\r\n", Environment.NewLine);
218  }
219 
220  return result;
221  }
222 
223  #endregion
224 
225  #region Private fields
226 
227  string _text;
228  bool _dirty;
229  int _lastIndent;
230  Collection<String> _lines;
231 
232  #endregion
233  }
234 }
Represents a text with multiple lines.
Definition: Multiline.cs:31
Multiline(string text)
Creates an instance using text as initial text.
Definition: Multiline.cs:144
void AddLine(string line)
Adds an individual line.
Definition: Multiline.cs:99
void Add(string text)
Adds text to the multiline text.
Definition: Multiline.cs:75
void Add(string text, string newLineSeparator)
Adds text to the multiline text by splitting it into multiple lines by the newLineSeparator ...
Definition: Multiline.cs:86