*
* The MIT License (MIT)
*
- * Copyright (C) 2017 Kevin Lamonte
+ * Copyright (C) 2019 Kevin Lamonte
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*/
package jexer.teditor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
*/
public class Document {
+ // ------------------------------------------------------------------------
+ // Variables --------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
/**
* The list of lines.
*/
*/
private boolean overwrite = false;
+ /**
+ * If true, the document has been edited.
+ */
+ private boolean dirty = false;
+
/**
* The default color for the TEditor class.
*/
*/
private Highlighter highlighter = new Highlighter();
+ // ------------------------------------------------------------------------
+ // Constructors -----------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Construct a new Document from an existing text string.
+ *
+ * @param str the text string
+ * @param defaultColor the color for unhighlighted text
+ */
+ public Document(final String str, final CellAttributes defaultColor) {
+ this.defaultColor = defaultColor;
+
+ // TODO: set different colors based on file extension
+ highlighter.setJavaColors();
+
+ String [] rawLines = str.split("\n");
+ for (int i = 0; i < rawLines.length; i++) {
+ lines.add(new Line(rawLines[i], this.defaultColor, highlighter));
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Document ---------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
/**
* Get the overwrite flag.
*
return overwrite;
}
+ /**
+ * Get the dirty value.
+ *
+ * @return true if the buffer is dirty
+ */
+ public boolean isDirty() {
+ return dirty;
+ }
+
+ /**
+ * Save contents to file.
+ *
+ * @param filename file to save to
+ * @throws IOException if a java.io operation throws
+ */
+ public void saveToFilename(final String filename) throws IOException {
+ OutputStreamWriter output = null;
+ try {
+ output = new OutputStreamWriter(new FileOutputStream(filename),
+ "UTF-8");
+
+ for (Line line: lines) {
+ output.write(line.getRawString());
+ output.write("\n");
+ }
+
+ dirty = false;
+ }
+ finally {
+ if (output != null) {
+ output.close();
+ }
+ }
+ }
+
/**
* Set the overwrite flag.
*
}
/**
- * Construct a new Document from an existing text string.
+ * Set the current cursor position of the editing line. 0-based.
*
- * @param str the text string
- * @param defaultColor the color for unhighlighted text
+ * @param cursor the new cursor position
*/
- public Document(final String str, final CellAttributes defaultColor) {
- this.defaultColor = defaultColor;
-
- // TODO: set different colors based on file extension
- highlighter.setJavaColors();
-
- String [] rawLines = str.split("\n");
- for (int i = 0; i < rawLines.length; i++) {
- lines.add(new Line(rawLines[i], this.defaultColor, highlighter));
+ public void setCursor(final int cursor) {
+ if (cursor >= lines.get(lineNumber).getDisplayLength()) {
+ lines.get(lineNumber).end();
+ } else {
+ lines.get(lineNumber).setCursor(cursor);
}
}
if (lineNumber < lines.size() - 1) {
int x = lines.get(lineNumber).getCursor();
lineNumber++;
- if (x > lines.get(lineNumber).getDisplayLength()) {
+ if (x >= lines.get(lineNumber).getDisplayLength()) {
lines.get(lineNumber).end();
} else {
lines.get(lineNumber).setCursor(x);
if (lineNumber > lines.size() - 1) {
lineNumber = lines.size() - 1;
}
- if (x > lines.get(lineNumber).getDisplayLength()) {
+ if (x >= lines.get(lineNumber).getDisplayLength()) {
lines.get(lineNumber).end();
} else {
lines.get(lineNumber).setCursor(x);
if (lineNumber > 0) {
int x = lines.get(lineNumber).getCursor();
lineNumber--;
- if (x > lines.get(lineNumber).getDisplayLength()) {
+ if (x >= lines.get(lineNumber).getDisplayLength()) {
lines.get(lineNumber).end();
} else {
lines.get(lineNumber).setCursor(x);
if (lineNumber < 0) {
lineNumber = 0;
}
- if (x > lines.get(lineNumber).getDisplayLength()) {
+ if (x >= lines.get(lineNumber).getDisplayLength()) {
lines.get(lineNumber).end();
} else {
lines.get(lineNumber).setCursor(x);
* @return true if the cursor position changed
*/
public boolean left() {
- return lines.get(lineNumber).left();
+ if (!lines.get(lineNumber).left()) {
+ // We are on the leftmost column, wrap
+ if (up()) {
+ end();
+ } else {
+ return false;
+ }
+ }
+ return true;
}
/**
* @return true if the cursor position changed
*/
public boolean right() {
- return lines.get(lineNumber).right();
+ if (!lines.get(lineNumber).right()) {
+ // We are on the rightmost column, wrap
+ if (down()) {
+ home();
+ } else {
+ return false;
+ }
+ }
+ return true;
}
/**
* Delete the character under the cursor.
*/
public void del() {
- lines.get(lineNumber).del();
+ dirty = true;
+ int cursor = lines.get(lineNumber).getCursor();
+ if (cursor < lines.get(lineNumber).getDisplayLength() - 1) {
+ lines.get(lineNumber).del();
+ } else if (lineNumber < lines.size() - 2) {
+ // Join two lines
+ StringBuilder newLine = new StringBuilder(lines.
+ get(lineNumber).getRawString());
+ newLine.append(lines.get(lineNumber + 1).getRawString());
+ lines.set(lineNumber, new Line(newLine.toString(),
+ defaultColor, highlighter));
+ lines.get(lineNumber).setCursor(cursor);
+ lines.remove(lineNumber + 1);
+ }
}
/**
* Delete the character immediately preceeding the cursor.
*/
public void backspace() {
- lines.get(lineNumber).backspace();
+ dirty = true;
+ int cursor = lines.get(lineNumber).getCursor();
+ if (cursor > 0) {
+ lines.get(lineNumber).backspace();
+ } else if (lineNumber > 0) {
+ // Join two lines
+ lineNumber--;
+ String firstLine = lines.get(lineNumber).getRawString();
+ if (firstLine.length() > 0) {
+ // Backspacing combining two lines
+ StringBuilder newLine = new StringBuilder(firstLine);
+ newLine.append(lines.get(lineNumber + 1).getRawString());
+ lines.set(lineNumber, new Line(newLine.toString(),
+ defaultColor, highlighter));
+ lines.get(lineNumber).setCursor(firstLine.length());
+ lines.remove(lineNumber + 1);
+ } else {
+ // Backspacing an empty line
+ lines.remove(lineNumber);
+ lines.get(lineNumber).setCursor(0);
+ }
+ }
+ }
+
+ /**
+ * Split the current line into two, like pressing the enter key.
+ */
+ public void enter() {
+ dirty = true;
+ int cursor = lines.get(lineNumber).getCursor();
+ String original = lines.get(lineNumber).getRawString();
+ String firstLine = original.substring(0, cursor);
+ String secondLine = original.substring(cursor);
+ lines.add(lineNumber + 1, new Line(secondLine, defaultColor,
+ highlighter));
+ lines.set(lineNumber, new Line(firstLine, defaultColor, highlighter));
+ lineNumber++;
+ lines.get(lineNumber).home();
}
/**
* @param ch the character to replace or insert
*/
public void addChar(final char ch) {
+ dirty = true;
if (overwrite) {
lines.get(lineNumber).replaceChar(ch);
} else {
return n;
}
+ /**
+ * Get the current line length.
+ *
+ * @return the number of cells needed to display the current line
+ */
+ public int getLineLength() {
+ return lines.get(lineNumber).getDisplayLength();
+ }
+
}