Skip to content

Commit

Permalink
nano command: implemented a few missing options
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Sep 20, 2019
1 parent 10b405b commit b79a425
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 70 deletions.
25 changes: 13 additions & 12 deletions builtins/src/main/java/org/jline/builtins/Commands.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,23 +116,24 @@ public static void nano(Terminal terminal, PrintStream out, PrintStream err,
" -B --backup When saving a file, back up the previous version of it, using the current filename",
" suffixed with a tilde (~)." ,
" -I --ignorercfiles Don't look at the system's nanorc nor at the user's nanorc." ,
" -Q --quotestr=regex Set the regular expression for matching the quoting part of a line. The default value",
" is \"^([ \t]*([!#%:;>|}]|//))+\".",
" -Q --quotestr=regex Set the regular expression for matching the quoting part of a line.",
" -T --tabsize=number Set the size (width) of a tab to number columns.",
" -U --quickblank Do quick status-bar blanking: status-bar messages will disappear after 1 keystroke",
" instead of 25.",
" -U --quickblank Do quick status-bar blanking: status-bar messages will disappear after 1 keystroke.",
" -c --constantshow Constantly show the cursor position on the status bar.",
" -e --emptyline Do not use the line below the title bar, leaving it entirely blank.",
" -j --jumpyscrolling Scroll the buffer contents per half-screen instead of per line.",
" -l --linenumbers Display line numbers to the left of the text area.",
" -m --mouse Enable mouse support, if available for your system. When enabled, mouse clicks can be",
" used to place the cursor, set the mark (with a double click), and execute shortcuts.",
" -$ --softwrap Enable 'soft wrapping'. This will make nano attempt to display the entire contents of any",
" line, even if it is longer than the screen width, by continuing it over multiple screen lines.",
" -m --mouse Enable mouse support, if available for your system.",
" -$ --softwrap Enable 'soft wrapping'. ",
" -a --atblanks Wrap lines at whitespace instead of always at the edge of the screen.",
" -R --restricted Restricted mode: don't allow suspending; don't allow a file to be appended to,",
" prepended to, or saved under a different name if it already has one;",
" and don't use backup files.",
" -Y --syntax=name The name of the syntax highlighting to use."
" -Y --syntax=name The name of the syntax highlighting to use.",
" -z --suspend Enable the ability to suspend nano using the system's suspend keystroke (usually ^Z).",
" -v --view Don't allow the contents of the file to be altered: read-only mode.",
" -k --cutfromcursor Make the 'Cut Text' command cut from the current cursor position to the end of the line",
" -t --tempfile Save a changed buffer without prompting (when exiting with ^X)."
};
Options opt = Options.compile(usage).parse(argv);
if (opt.isSet("help")) {
Expand Down Expand Up @@ -202,7 +203,7 @@ public static void less(Terminal terminal, InputStream in, PrintStream out, Prin
protected static List<Path> findFiles(Path root, String files) throws IOException{
String regex = files;
Path searchRoot = Paths.get("/");
if (!new File(files).isAbsolute()) {
if (new File(files).isAbsolute()) {
regex = regex.replaceAll("\\\\", "/").replaceAll("//", "/");
if (regex.contains("/")) {
String sr = regex.substring(0, regex.lastIndexOf("/") + 1);
Expand All @@ -211,8 +212,8 @@ protected static List<Path> findFiles(Path root, String files) throws IOExceptio
}
searchRoot = Paths.get(sr + "/");
}
} else {
regex = (root.toString().length() == 0 ? "" : root.toString() + "/") + files;
} else {
regex = (root.toString().length() == 0 ? "" : root.toString() + "/") + files;
regex = regex.replaceAll("\\\\", "/").replaceAll("//", "/");
searchRoot = root;
}
Expand Down
155 changes: 106 additions & 49 deletions builtins/src/main/java/org/jline/builtins/Nano.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ public class Nano implements Editor {
private boolean restricted = false;
private String syntaxName;
private boolean writeBackup = false;
private boolean atBlanks = false;
private boolean view = false;
private boolean cut2end = false;
private boolean tempFile = false;

// Input
protected final List<Buffer> buffers = new ArrayList<>();
Expand All @@ -121,7 +125,6 @@ public class Nano implements Editor {
protected int searchTermId = -1;
protected WriteMode writeMode = WriteMode.WRITE;
protected List<String> cutbuffer = new ArrayList<>();
protected boolean cut2end = false;
protected boolean mark = false;
protected boolean highlight = true;
private List<Path> syntaxFiles = new ArrayList<>();
Expand Down Expand Up @@ -310,7 +313,7 @@ LinkedList<Integer> computeOffsets(String text) {
}

boolean isBreakable(char ch) {
return ch == ' ';
return atBlanks ? ch == ' ' : true;
}

void moveToChar(int pos) {
Expand Down Expand Up @@ -1582,8 +1585,12 @@ public Nano(Terminal terminal, Path root, Options opts, ConfigurationPath config
this.display = new Display(terminal, true);
this.bindingReader = new BindingReader(terminal.reader());
this.size = new Size();
this.vsusp = terminal.getAttributes().getControlChar(ControlChar.VSUSP);
bindKeys();
Attributes attrs = terminal.getAttributes();
this.vsusp = attrs.getControlChar(ControlChar.VSUSP);
if (vsusp > 0) {
attrs.setControlChar(ControlChar.VSUSP, 0);
terminal.setAttributes(attrs);
}
Path nanorc = configPath != null ? configPath.getConfig("jnanorc") : null;
boolean ignorercfiles = opts!=null && opts.isSet("ignorercfiles");
if (nanorc != null && !ignorercfiles) {
Expand Down Expand Up @@ -1634,7 +1641,23 @@ public Nano(Terminal terminal, Path root, Options opts, ConfigurationPath config
if (opts.isSet("softwrap")) {
wrapping = true;
}
if (opts.isSet("atblanks")) {
atBlanks = true;
}
if (opts.isSet("suspend")) {
enableSuspension();
}
if (opts.isSet("view")) {
view = true;
}
if (opts.isSet("cutfromcursor")) {
cut2end = true;
}
if (opts.isSet("tempfile")) {
tempFile = true;
}
}
bindKeys();
}

private void parseConfig(Path file) throws IOException {
Expand Down Expand Up @@ -1674,6 +1697,16 @@ private void parseConfig(Path file) throws IOException {
constantCursor = val;
} else if (option.equals("quickblank")) {
quickBlank = val;
} else if (option.equals("atblanks")) {
atBlanks = val;
} else if (option.equals("suspend")) {
enableSuspension();
} else if (option.equals("view")) {
view = val;
} else if (option.equals("cutfromcursor")) {
cut2end = val;
} else if (option.equals("tempfile")) {
tempFile = val;
} else {
errorMessage = "Nano config: Unknown or unsupported configuration option " + option;
}
Expand Down Expand Up @@ -1730,14 +1763,14 @@ public void run() throws IOException {

Attributes attributes = terminal.getAttributes();
Attributes newAttr = new Attributes(attributes);
if (vsusp > 0) {
attributes.setControlChar(ControlChar.VSUSP, 0);
}
newAttr.setLocalFlags(EnumSet.of(LocalFlag.ICANON, LocalFlag.ECHO, LocalFlag.IEXTEN), false);
newAttr.setInputFlags(EnumSet.of(InputFlag.IXON, InputFlag.ICRNL, InputFlag.INLCR), false);
newAttr.setControlChar(ControlChar.VMIN, 1);
newAttr.setControlChar(ControlChar.VTIME, 0);
newAttr.setControlChar(ControlChar.VINTR, 0);
if (restricted) {
newAttr.setControlChar(ControlChar.VSUSP, 0);
}
terminal.setAttributes(newAttr);
terminal.puts(Capability.enter_ca_mode);
terminal.puts(Capability.keypad_xmit);
Expand Down Expand Up @@ -2394,16 +2427,24 @@ private LinkedHashMap<String, String> searchShortcuts() {
private LinkedHashMap<String, String> standardShortcuts() {
LinkedHashMap<String, String> s = new LinkedHashMap<>();
s.put("^G", "Get Help");
s.put("^O", "WriteOut");
if (!view) {
s.put("^O", "WriteOut");
}
s.put("^R", "Read File");
s.put("^Y", "Prev Page");
s.put("^K", "Cut Text");
if (!view) {
s.put("^K", "Cut Text");
}
s.put("^C", "Cur Pos");
s.put("^X", "Exit");
s.put("^J", "Justify");
if (!view) {
s.put("^J", "Justify");
}
s.put("^W", "Where Is");
s.put("^V", "Next Page");
s.put("^U", "UnCut Text");
if (!view) {
s.put("^U", "UnCut Text");
}
s.put("^T", "To Spell");
return s;
}
Expand Down Expand Up @@ -2692,16 +2733,22 @@ void setMessage(String message) {

boolean quit() throws IOException {
if (buffer.dirty) {
Operation op = getYNC("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? ");
switch (op) {
case CANCEL:
if (tempFile) {
if (!write()) {
return false;
case NO:
break;
case YES:
if (!write()) {
}
} else {
Operation op = getYNC("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? ");
switch (op) {
case CANCEL:
return false;
}
case NO:
break;
case YES:
if (!write()) {
return false;
}
}
}
}
buffers.remove(bufferIndex);
Expand Down Expand Up @@ -2794,6 +2841,14 @@ else if (event.getType() == MouseEvent.Type.Wheel) {
}
}

void enableSuspension() {
if (!restricted && vsusp < 0) {
Attributes attrs = terminal.getAttributes();
attrs.setControlChar(ControlChar.VSUSP, vsusp);
terminal.setAttributes(attrs);
}
}

void toggleSuspension(){
if (restricted) {
setMessage("This function is disabled in restricted mode");
Expand Down Expand Up @@ -2931,40 +2986,53 @@ protected void handle(Signal signal) {

protected void bindKeys() {
keys = new KeyMap<>();
keys.setUnicode(Operation.INSERT);
if (!view) {
keys.setUnicode(Operation.INSERT);

for (char i = 32; i < KEYMAP_LENGTH; i++) {
keys.bind(Operation.INSERT, Character.toString(i));
}
keys.bind(Operation.BACKSPACE, del());
for (char i = 'A'; i <= 'Z'; i++) {
keys.bind(Operation.DO_LOWER_CASE, alt(i));
for (char i = 32; i < KEYMAP_LENGTH; i++) {
keys.bind(Operation.INSERT, Character.toString(i));
}
keys.bind(Operation.BACKSPACE, del());
for (char i = 'A'; i <= 'Z'; i++) {
keys.bind(Operation.DO_LOWER_CASE, alt(i));
}
keys.bind(Operation.WRITE, ctrl('O'), key(terminal, Capability.key_f3));
keys.bind(Operation.JUSTIFY_PARAGRAPH, ctrl('J'), key(terminal, Capability.key_f4));
keys.bind(Operation.CUT, ctrl('K'), key(terminal, Capability.key_f9));
keys.bind(Operation.UNCUT, ctrl('U'), key(terminal, Capability.key_f10));
keys.bind(Operation.REPLACE, ctrl('\\'), key(terminal, Capability.key_f14), alt('r'));
keys.bind(Operation.MARK, ctrl('^'), key(terminal, Capability.key_f15), alt('a'));
keys.bind(Operation.COPY, alt('^'), alt('6'));
keys.bind(Operation.INDENT, alt('}'));
keys.bind(Operation.UNINDENT, alt('{'));
keys.bind(Operation.VERBATIM, alt('v'));
keys.bind(Operation.INSERT, ctrl('I'), ctrl('M'));
keys.bind(Operation.DELETE, ctrl('D'));
keys.bind(Operation.BACKSPACE, ctrl('H'));
keys.bind(Operation.CUT_TO_END, alt('t'));
keys.bind(Operation.JUSTIFY_FILE, alt('j'));
keys.bind(Operation.AUTO_INDENT, alt('i'));
keys.bind(Operation.CUT_TO_END_TOGGLE, alt('k'));
keys.bind(Operation.TABS_TO_SPACE, alt('q'));
keys.bind(Operation.NEXT_PAGE, ctrl('V'), key(terminal, Capability.key_f8));
keys.bind(Operation.PREV_PAGE, ctrl('Y'), key(terminal, Capability.key_f7));
} else {
keys.bind(Operation.NEXT_PAGE, ctrl('V'), key(terminal, Capability.key_f8), " ", "f");
keys.bind(Operation.PREV_PAGE, ctrl('Y'), key(terminal, Capability.key_f7), "b");
}

keys.bind(Operation.HELP, ctrl('G'), key(terminal, Capability.key_f1));
keys.bind(Operation.QUIT, ctrl('X'), key(terminal, Capability.key_f2));
keys.bind(Operation.WRITE, ctrl('O'), key(terminal, Capability.key_f3));
keys.bind(Operation.JUSTIFY_PARAGRAPH, ctrl('J'), key(terminal, Capability.key_f4));

keys.bind(Operation.READ, ctrl('R'), key(terminal, Capability.key_f5));
keys.bind(Operation.SEARCH, ctrl('W'), key(terminal, Capability.key_f6));
keys.bind(Operation.PREV_PAGE, ctrl('Y'), key(terminal, Capability.key_f7));
keys.bind(Operation.NEXT_PAGE, ctrl('V'), key(terminal, Capability.key_f8));

keys.bind(Operation.CUT, ctrl('K'), key(terminal, Capability.key_f9));
keys.bind(Operation.UNCUT, ctrl('U'), key(terminal, Capability.key_f10));
keys.bind(Operation.CUR_POS, ctrl('C'), key(terminal, Capability.key_f11));
keys.bind(Operation.TO_SPELL, ctrl('T'), key(terminal, Capability.key_f11));

keys.bind(Operation.GOTO, ctrl('_'), key(terminal, Capability.key_f13), alt('g'));
keys.bind(Operation.REPLACE, ctrl('\\'), key(terminal, Capability.key_f14), alt('r'));
keys.bind(Operation.MARK, ctrl('^'), key(terminal, Capability.key_f15), alt('a'));
keys.bind(Operation.NEXT_SEARCH, key(terminal, Capability.key_f16), alt('w'));

keys.bind(Operation.COPY, alt('^'), alt('6'));
keys.bind(Operation.INDENT, alt('}'));
keys.bind(Operation.UNINDENT, alt('{'));

keys.bind(Operation.RIGHT, ctrl('F'));
keys.bind(Operation.LEFT, ctrl('B'));
keys.bind(Operation.NEXT_WORD, ctrl(' '));
Expand All @@ -2988,13 +3056,6 @@ protected void bindKeys() {
keys.bind(Operation.PREV_BUFFER, alt(','));
keys.bind(Operation.NEXT_BUFFER, alt('.'));

keys.bind(Operation.VERBATIM, alt('v'));
keys.bind(Operation.INSERT, ctrl('I'), ctrl('M'));
keys.bind(Operation.DELETE, ctrl('D'));
keys.bind(Operation.BACKSPACE, ctrl('H'));
keys.bind(Operation.CUT_TO_END, alt('t'));

keys.bind(Operation.JUSTIFY_FILE, alt('j'));
keys.bind(Operation.COUNT, alt('d'));
keys.bind(Operation.CLEAR_SCREEN, ctrl('L'));

Expand All @@ -3007,13 +3068,9 @@ protected void bindKeys() {
keys.bind(Operation.HIGHLIGHT, alt('y'));

keys.bind(Operation.SMART_HOME_KEY, alt('h'));
keys.bind(Operation.AUTO_INDENT, alt('i'));
keys.bind(Operation.CUT_TO_END_TOGGLE, alt('k'));
keys.bind(Operation.WRAP, alt('l'));
keys.bind(Operation.TABS_TO_SPACE, alt('q'));

keys.bind(Operation.BACKUP, alt('b'));

keys.bind(Operation.NUMBERS, alt('n'));

// TODO: map other keys
Expand Down

0 comments on commit b79a425

Please sign in to comment.