From e23989a4e74f7a7a08496aac956d1abe429bd6c0 Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Fri, 16 Aug 2019 22:19:45 -0500 Subject: [PATCH] forward/backward word, hide mouse when typing --- src/jexer/TEditorWidget.java | 10 ++ src/jexer/TEditorWindow.java | 46 +++++++++ src/jexer/teditor/Document.java | 160 +++++++++++++++++++++++++++++++- src/jexer/teditor/Line.java | 12 +++ 4 files changed, 226 insertions(+), 2 deletions(-) diff --git a/src/jexer/TEditorWidget.java b/src/jexer/TEditorWidget.java index 8b105f8b..0f8f7715 100644 --- a/src/jexer/TEditorWidget.java +++ b/src/jexer/TEditorWidget.java @@ -207,6 +207,16 @@ public class TEditorWidget extends TWidget { } else if (keypress.equals(kbRight)) { document.right(); alignTopLine(true); + } else if (keypress.equals(kbAltLeft) + || keypress.equals(kbCtrlLeft) + ) { + document.backwardsWord(); + alignTopLine(false); + } else if (keypress.equals(kbAltRight) + || keypress.equals(kbCtrlRight) + ) { + document.forwardsWord(); + alignTopLine(true); } else if (keypress.equals(kbUp)) { document.up(); alignTopLine(false); diff --git a/src/jexer/TEditorWindow.java b/src/jexer/TEditorWindow.java index b64f0c71..85bb91a2 100644 --- a/src/jexer/TEditorWindow.java +++ b/src/jexer/TEditorWindow.java @@ -73,6 +73,17 @@ public class TEditorWindow extends TScrollableWindow { */ private String filename = ""; + /** + * If true, hide the mouse after typing a keystroke. + */ + private boolean hideMouseWhenTyping = true; + + /** + * If true, the mouse should not be displayed because a keystroke was + * typed. + */ + private boolean typingHidMouse = false; + // ------------------------------------------------------------------------ // Constructors ----------------------------------------------------------- // ------------------------------------------------------------------------ @@ -173,6 +184,10 @@ public class TEditorWindow extends TScrollableWindow { // Use TWidget's code to pass the event to the children. super.onMouseDown(mouse); + if (hideMouseWhenTyping) { + typingHidMouse = false; + } + if (mouseOnEditor(mouse)) { // The editor might have changed, update the scollbars. setBottomValue(editField.getMaximumRowNumber()); @@ -197,6 +212,10 @@ public class TEditorWindow extends TScrollableWindow { // Use TWidget's code to pass the event to the children. super.onMouseUp(mouse); + if (hideMouseWhenTyping) { + typingHidMouse = false; + } + if (mouse.isMouse1() && mouseOnVerticalScroller(mouse)) { // Clicked on vertical scrollbar editField.setVisibleRowNumber(getVerticalValue()); @@ -215,6 +234,10 @@ public class TEditorWindow extends TScrollableWindow { // Use TWidget's code to pass the event to the children. super.onMouseMotion(mouse); + if (hideMouseWhenTyping) { + typingHidMouse = false; + } + if (mouseOnEditor(mouse) && mouse.isMouse1()) { // The editor might have changed, update the scollbars. setBottomValue(editField.getMaximumRowNumber()); @@ -239,6 +262,10 @@ public class TEditorWindow extends TScrollableWindow { */ @Override public void onKeypress(final TKeypressEvent keypress) { + if (hideMouseWhenTyping) { + typingHidMouse = true; + } + // Use TWidget's code to pass the event to the children. super.onKeypress(keypress); @@ -318,6 +345,18 @@ public class TEditorWindow extends TScrollableWindow { super.onCommand(command); } + /** + * Returns true if this window does not want the application-wide mouse + * cursor drawn over it. + * + * @return true if this window does not want the application-wide mouse + * cursor drawn over it + */ + @Override + public boolean hasHiddenMouse() { + return (super.hasHiddenMouse() || typingHidMouse); + } + // ------------------------------------------------------------------------ // TEditorWindow ---------------------------------------------------------- // ------------------------------------------------------------------------ @@ -344,6 +383,13 @@ public class TEditorWindow extends TScrollableWindow { i18n.getString("statusBarOpen")); statusBar.addShortcutKeypress(kbF10, cmMenu, i18n.getString("statusBarMenu")); + + // Hide mouse when typing option + if (System.getProperty("jexer.TEditor.hideMouseWhenTyping", + "true").equals("false")) { + + hideMouseWhenTyping = false; + } } /** diff --git a/src/jexer/teditor/Document.java b/src/jexer/teditor/Document.java index 56591244..2abfef66 100644 --- a/src/jexer/teditor/Document.java +++ b/src/jexer/teditor/Document.java @@ -209,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. * @@ -309,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 */ @@ -326,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 */ @@ -342,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. * diff --git a/src/jexer/teditor/Line.java b/src/jexer/teditor/Line.java index f3168fdf..7cd5feba 100644 --- a/src/jexer/teditor/Line.java +++ b/src/jexer/teditor/Line.java @@ -155,6 +155,18 @@ public class Line { position = screenToTextPosition(screenPosition); } + /** + * 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() { + if (position == rawText.length()) { + return -1; + } + return rawText.codePointAt(position); + } + /** * Get the on-screen display length. * -- 2.27.0