TEditor 50% complete
[nikiroo-utils.git] / src / jexer / teditor / Word.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2017 Kevin Lamonte
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29 package jexer.teditor;
30
31 import jexer.bits.CellAttributes;
32
33 /**
34 * A Word represents text that was entered by the user. It can be either
35 * whitespace or non-whitespace.
36 *
37 * Very dumb highlighting is supported, it has no sense of parsing (not even
38 * comments). For now this only highlights some Java keywords and
39 * puctuation.
40 */
41 public class Word {
42
43 /**
44 * The color to render this word as on screen.
45 */
46 private CellAttributes color = new CellAttributes();
47
48 /**
49 * The default color for the TEditor class.
50 */
51 private CellAttributes defaultColor = null;
52
53 /**
54 * The text highlighter to use.
55 */
56 private Highlighter highlighter = null;
57
58 /**
59 * The actual text of this word. Average word length is 6 characters,
60 * with a lot of shorter ones, so start with 3.
61 */
62 private StringBuilder text = new StringBuilder(3);
63
64 /**
65 * Get the color used to display this word on screen.
66 *
67 * @return the color
68 */
69 public CellAttributes getColor() {
70 return new CellAttributes(color);
71 }
72
73 /**
74 * Set the color used to display this word on screen.
75 *
76 * @param color the color
77 */
78 public void setColor(final CellAttributes color) {
79 color.setTo(color);
80 }
81
82 /**
83 * Get the text to display.
84 *
85 * @return the text
86 */
87 public String getText() {
88 return text.toString();
89 }
90
91 /**
92 * Get the on-screen display length.
93 *
94 * @return the number of cells needed to display this word
95 */
96 public int getDisplayLength() {
97 // For now, just use the text length. In the future, this will be a
98 // grapheme count.
99
100 // TODO: figure out how to handle the tab character. Do we have a
101 // global tab stops list and current word position?
102 return text.length();
103 }
104
105 /**
106 * See if this is a whitespace word. Note that empty string is
107 * considered whitespace.
108 *
109 * @return true if this word is whitespace
110 */
111 public boolean isWhitespace() {
112 if (text.length() == 0) {
113 return true;
114 }
115 if (Character.isWhitespace(text.charAt(0))) {
116 return true;
117 }
118 return false;
119 }
120
121 /**
122 * Construct a word with one character.
123 *
124 * @param ch the first character of the word
125 * @param defaultColor the color for unhighlighted text
126 * @param highlighter the highlighter to use
127 */
128 public Word(final char ch, final CellAttributes defaultColor,
129 final Highlighter highlighter) {
130
131 this.defaultColor = defaultColor;
132 this.highlighter = highlighter;
133 text.append(ch);
134 }
135
136 /**
137 * Construct a word with an empty string.
138 *
139 * @param defaultColor the color for unhighlighted text
140 * @param highlighter the highlighter to use
141 */
142 public Word(final CellAttributes defaultColor,
143 final Highlighter highlighter) {
144
145 this.defaultColor = defaultColor;
146 this.highlighter = highlighter;
147 }
148
149 /**
150 * Perform highlighting.
151 */
152 public void applyHighlight() {
153 color.setTo(defaultColor);
154 if (highlighter == null) {
155 return;
156 }
157 String key = text.toString();
158 CellAttributes newColor = highlighter.getColor(key);
159 if (newColor != null) {
160 color.setTo(newColor);
161 }
162 }
163
164 /**
165 * Add a character to this word. If this is a whitespace character
166 * adding to a non-whitespace word, create a new word and return that;
167 * similarly if this a non-whitespace character adding to a whitespace
168 * word, create a new word and return that.
169 *
170 * @param ch the new character to add
171 * @return either this word (if it was added), or a new word that
172 * contains ch
173 */
174 public Word addChar(final char ch) {
175 if (text.length() == 0) {
176 text.append(ch);
177 return this;
178 }
179
180 // Give the highlighter the option to split here.
181 if (highlighter != null) {
182 if (highlighter.shouldSplit(ch)
183 || highlighter.shouldSplit(text.charAt(0))
184 ) {
185 Word newWord = new Word(ch, defaultColor, highlighter);
186 return newWord;
187 }
188 }
189
190 // Highlighter didn't care, so split at whitespace.
191 if (Character.isWhitespace(text.charAt(0))
192 && Character.isWhitespace(ch)
193 ) {
194 // Adding to a whitespace word, keep at it.
195 text.append(ch);
196 return this;
197 }
198 if (!Character.isWhitespace(text.charAt(0))
199 && !Character.isWhitespace(ch)
200 ) {
201 // Adding to a non-whitespace word, keep at it.
202 text.append(ch);
203 return this;
204 }
205
206 // Switching from whitespace to non-whitespace or vice versa, so
207 // split here.
208 Word newWord = new Word(ch, defaultColor, highlighter);
209 return newWord;
210 }
211
212 }