Add 'src/jexer/' from commit 'cf01c92f5809a0732409e280fb0f32f27393618d'
[nikiroo-utils.git] / src / jexer / teditor / Document.java
index e1a28a0d37f39504c482da627c880110e3d1a9d8..2abfef6635f3c1877fc733ee36ea8c67d01160b6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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"),
@@ -41,6 +41,10 @@ import jexer.bits.CellAttributes;
  */
 public class Document {
 
+    // ------------------------------------------------------------------------
+    // Variables --------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
     /**
      * The list of lines.
      */
@@ -72,6 +76,32 @@ public class Document {
      */
     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.
      *
@@ -179,6 +209,15 @@ public class Document {
         return lines.get(lineNumber).getCursor();
     }
 
+    /**
+     * Get the character at the current cursor position in the text.
+     *
+     * @return the character, or -1 if the cursor is at the end of the line
+     */
+    public int getChar() {
+        return lines.get(lineNumber).getChar();
+    }
+
     /**
      * Set the current cursor position of the editing line.  0-based.
      *
@@ -192,24 +231,6 @@ public class Document {
         }
     }
 
-    /**
-     * 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));
-        }
-    }
-
     /**
      * Increment the line number by one.  If at the last line, do nothing.
      *
@@ -297,7 +318,8 @@ public class Document {
     }
 
     /**
-     * Decrement the cursor by one.  If at the first column, do nothing.
+     * Decrement the cursor by one.  If at the first column on the first
+     * line, do nothing.
      *
      * @return true if the cursor position changed
      */
@@ -314,7 +336,8 @@ public class Document {
     }
 
     /**
-     * Increment the cursor by one.  If at the last column, do nothing.
+     * Increment the cursor by one.  If at the last column on the last line,
+     * do nothing.
      *
      * @return true if the cursor position changed
      */
@@ -330,6 +353,151 @@ public class Document {
         return true;
     }
 
+    /**
+     * Go back to the beginning of this word if in the middle, or the
+     * beginning of the previous word.
+     */
+    public void backwardsWord() {
+
+        // If at the beginning of a word already, push past it.
+        if ((getChar() != -1)
+            && (getRawLine().length() > 0)
+            && !Character.isSpace((char) getChar())
+        ) {
+            left();
+        }
+
+        // int line = lineNumber;
+        while ((getChar() == -1)
+            || (getRawLine().length() == 0)
+            || Character.isSpace((char) getChar())
+        ) {
+            if (left() == false) {
+                return;
+            }
+        }
+
+
+        assert (getChar() != -1);
+
+        if (!Character.isSpace((char) getChar())
+            && (getRawLine().length() > 0)
+        ) {
+            // Advance until at the beginning of the document or a whitespace
+            // is encountered.
+            while (!Character.isSpace((char) getChar())) {
+                int line = lineNumber;
+                if (left() == false) {
+                    // End of document, bail out.
+                    return;
+                }
+                if (lineNumber != line) {
+                    // We wrapped a line.  Here that counts as whitespace.
+                    right();
+                    return;
+                }
+            }
+        }
+
+        // We went one past the word, push back to the first character of
+        // that word.
+        right();
+        return;
+    }
+
+    /**
+     * Go to the beginning of the next word.
+     */
+    public void forwardsWord() {
+        int line = lineNumber;
+        while ((getChar() == -1)
+            || (getRawLine().length() == 0)
+        ) {
+            if (right() == false) {
+                return;
+            }
+            if (lineNumber != line) {
+                // We wrapped a line.  Here that counts as whitespace.
+                if (!Character.isSpace((char) getChar())) {
+                    // We found a character immediately after the line.
+                    // Done!
+                    return;
+                }
+                // Still looking...
+                line = lineNumber;
+            }
+        }
+        assert (getChar() != -1);
+
+        if (!Character.isSpace((char) getChar())
+            && (getRawLine().length() > 0)
+        ) {
+            // Advance until at the end of the document or a whitespace is
+            // encountered.
+            while (!Character.isSpace((char) getChar())) {
+                line = lineNumber;
+                if (right() == false) {
+                    // End of document, bail out.
+                    return;
+                }
+                if (lineNumber != line) {
+                    // We wrapped a line.  Here that counts as whitespace.
+                    if (!Character.isSpace((char) getChar())
+                        && (getRawLine().length() > 0)
+                    ) {
+                        // We found a character immediately after the line.
+                        // Done!
+                        return;
+                    }
+                    break;
+                }
+            }
+        }
+
+        while ((getChar() == -1)
+            || (getRawLine().length() == 0)
+        ) {
+            if (right() == false) {
+                return;
+            }
+            if (lineNumber != line) {
+                // We wrapped a line.  Here that counts as whitespace.
+                if (!Character.isSpace((char) getChar())) {
+                    // We found a character immediately after the line.
+                    // Done!
+                    return;
+                }
+                // Still looking...
+                line = lineNumber;
+            }
+        }
+        assert (getChar() != -1);
+
+        if (Character.isSpace((char) getChar())) {
+            // Advance until at the end of the document or a non-whitespace
+            // is encountered.
+            while (Character.isSpace((char) getChar())) {
+                if (right() == false) {
+                    // End of document, bail out.
+                    return;
+                }
+            }
+            return;
+        }
+
+        // We wrapped the line to get here.
+        return;
+    }
+
+    /**
+     * Get the raw string that matches this line.
+     *
+     * @return the string
+     */
+    public String getRawLine() {
+        return lines.get(lineNumber).getRawString();
+    }
+
     /**
      * Go to the first column of this line.
      *
@@ -401,7 +569,7 @@ public class Document {
      */
     public void enter() {
         dirty = true;
-        int cursor = lines.get(lineNumber).getCursor();
+        int cursor = lines.get(lineNumber).getRawCursor();
         String original = lines.get(lineNumber).getRawString();
         String firstLine = original.substring(0, cursor);
         String secondLine = original.substring(cursor);
@@ -418,7 +586,7 @@ public class Document {
      *
      * @param ch the character to replace or insert
      */
-    public void addChar(final char ch) {
+    public void addChar(final int ch) {
         dirty = true;
         if (overwrite) {
             lines.get(lineNumber).replaceChar(ch);