Skip to content

Commit

Permalink
Merge pull request vrapper#67 from richq/master
Browse files Browse the repository at this point in the history
Support history in command line mode.
  • Loading branch information
keforbes committed May 29, 2012
2 parents fd40c01 + 02a7f0b commit 1622d4a
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public interface UserInterfaceService {
/**
* The command line is used for showing the currently typed command or search.
*/
void setCommandLine(String content);
void setCommandLine(String content, int position);

/**
* Indicates the current mode of the editor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ public void leaveMode(ModeSwitchHint... hints) {

public boolean handleKey(KeyStroke stroke) {
parser.type(stroke);
String buffer = isEnabled ? parser.getBuffer() : "";
editorAdaptor.getUserInterfaceService().setCommandLine(buffer);
String buffer = "";
int position = 0;
if (isEnabled) {
buffer = parser.getBuffer();
position = parser.getPosition();
}
editorAdaptor.getUserInterfaceService().setCommandLine(buffer, position);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,73 @@ public abstract class AbstractCommandParser {
protected static final KeyStroke KEY_CTRL_C = ctrlKey('c');
protected static final KeyStroke KEY_BACKSP = key(SpecialKey.BACKSPACE);
protected static final KeyStroke KEY_CTRL_V = key((char) 22);
protected static final KeyStroke KEY_UP = key(SpecialKey.ARROW_UP);
protected static final KeyStroke KEY_DOWN = key(SpecialKey.ARROW_DOWN);
protected static final KeyStroke KEY_RIGHT = key(SpecialKey.ARROW_RIGHT);
protected static final KeyStroke KEY_LEFT = key(SpecialKey.ARROW_LEFT);
protected final StringBuffer buffer;
protected final EditorAdaptor editor;
private final CommandLineHistory history;
private boolean modified;
private int position;

public AbstractCommandParser(EditorAdaptor vim) {
public AbstractCommandParser(EditorAdaptor vim, CommandLineHistory history) {
this.editor = vim;
buffer = new StringBuffer();
position = 0;
modified = false;
if (history != null)
this.history = history;
else
this.history = new CommandLineHistory();
}

/**
* Appends typed characters to the internal buffer. Deletes a char from the
* buffer on press of the backspace key. Parses and executes the buffer on
* press of the return key. Clears the buffer on press of the escape key.
* Up/down arrows handle command line history.
*/
public void type(KeyStroke e) {
Command c = null;
if (e.equals(KEY_RETURN)) {
c = parseAndExecute();
} else if (e.equals(KEY_BACKSP))
buffer.setLength(buffer.length()-1);
// TODO: on Mac OS, Cmd-V should be used
else if (e.equals(KEY_CTRL_V)) {
} else if (e.equals(KEY_BACKSP)) {
// only delete if not trying to delete the initial command character from under a command
if (position > 1 || buffer.length() == 1) {
buffer.replace(position - 1, position, "");
position--;
modified = true;
}
// TODO: on Mac OS, Cmd-V should be used
} else if (e.equals(KEY_CTRL_V)) {
String text = editor.getRegisterManager().getRegister(
RegisterManager.REGISTER_NAME_CLIPBOARD).getContent().getText();
text = text.replace('\n', ' ').replace('\r', ' ');
buffer.append(text);
} else
buffer.append(e.getCharacter());
} else if (e.equals(KEY_UP)) {
if (modified)
history.setTemp(getCommand());
String previous = history.getPrevious();
setCommandFromHistory(previous);
} else if (e.equals(KEY_DOWN)) {
if (modified)
history.setTemp(getCommand());
String next = history.getNext();
setCommandFromHistory(next);
} else if (e.equals(KEY_RIGHT)) {
position++;
if (position > buffer.length())
position--;
} else if (e.equals(KEY_LEFT)) {
position--;
if (position <= 0)
position++;
} else {
buffer.insert(position, e.getCharacter());
position++;
modified = true;
}

if (buffer.length() == 0 || e.equals(KEY_RETURN)
|| e.equals(KEY_ESCAPE) || e.equals(KEY_CTRL_C)) {
Expand All @@ -61,6 +101,19 @@ else if (e.equals(KEY_CTRL_V)) {
}
}

private void setCommandFromHistory(String cmd) {
if (cmd == null)
return;
modified = false;
buffer.setLength(1);
buffer.append(cmd);
position = buffer.length();
}

public int getPosition() {
return position;
}

public String getBuffer() {
return buffer.toString();
}
Expand All @@ -76,9 +129,14 @@ public String getBuffer() {
*/
public abstract Command parseAndExecute(String first, String command);

private String getCommand() {
return buffer.substring(1, buffer.length());
}

private Command parseAndExecute() {
String first = buffer.substring(0,1);
String command = buffer.substring(1, buffer.length());
String command = getCommand();
history.append(command);
return parseAndExecute(first, command);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package net.sourceforge.vrapper.vim.modes.commandline;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Stores the command line history and remove duplicates.
*/
public class CommandLineHistory {
List<String> history = new ArrayList<String>();
int position = 0;
String original;

public void append(String command) {
history.add(0, command);
position = -1;
removeDuplicates();
}

private void removeDuplicates() {
Set<String> contents = new HashSet<String>();
List<String> tmp = new ArrayList<String>();
for (String cmd : history) {
if (contents.contains(cmd))
continue;
contents.add(cmd);
tmp.add(cmd);
}
history.clear();
history.addAll(tmp);
}

public void setTemp(String temp) {
original = temp;
position = -1;
}

/**
* Get the previous entry in the history that matches the current
* edited command.
* @return the command in the history or null if none found to match.
*/
public String getPrevious() {
String result = null;
while (position >= -1 && (position + 1) < history.size()) {
position++;
String tmp = history.get(position);
if (tmp.startsWith(original)) {
result = tmp;
break;
}
}
if (position >= history.size())
position = history.size() - 1;
return result;
}

/**
* Get the next entry in the history that matches the current
* edited command.
* @return the command in the history or the original command if none
* found to match.
*/
public String getNext() {
String result = original;
position--;
while (position >= 0 && position < history.size()) {
String tmp = history.get(position);
position--;
if (tmp.startsWith(original)) {
result = tmp;
break;
}
}
if (position < 0)
position = -1;
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ public class CommandLineMode extends AbstractCommandLineMode {
public static final String DISPLAY_NAME = "COMMAND LINE";
public static final String NAME = "command mode";
public static final String KEYMAP_NAME = "Command Mode Keymap";
private CommandLineHistory history = new CommandLineHistory();

public CommandLineMode(EditorAdaptor editorAdaptor) {
super(editorAdaptor);
}

@Override
protected CommandLineParser createParser() {
return new CommandLineParser(editorAdaptor);
return new CommandLineParser(editorAdaptor, history);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ private static Evaluator buildConfigEvaluator() {
}

public CommandLineParser(EditorAdaptor vim) {
super(vim);
this(vim, null);
}

public CommandLineParser(EditorAdaptor vim, CommandLineHistory history) {
super(vim, history);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class PasteRegisterMode extends AbstractCommandLineMode {

public static final String DISPLAY_NAME = "PASTE REGISTER";
public static final String NAME = "paste register";
private CommandLineHistory history = new CommandLineHistory();

public String getDisplayName() {
return DISPLAY_NAME;
Expand All @@ -47,13 +48,13 @@ protected char activationChar() {

@Override
protected AbstractCommandParser createParser() {
return new PasteRegisterParser(editorAdaptor);
return new PasteRegisterParser(editorAdaptor, history);
}

private class PasteRegisterParser extends AbstractCommandParser {

public PasteRegisterParser(EditorAdaptor vim) {
super(vim);
public PasteRegisterParser(EditorAdaptor vim, CommandLineHistory history) {
super(vim, history);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public class SearchCommandParser extends AbstractCommandParser {
private static final Pattern AFTER_SEARCH_PATTERN = Pattern.compile("(e|b)?\\+?(-?\\d+)?");
private Command commandToExecute;

public SearchCommandParser(EditorAdaptor vim, Command commandToExecute) {
super(vim);
public SearchCommandParser(EditorAdaptor vim, Command commandToExecute, CommandLineHistory history) {
super(vim, history);
this.commandToExecute = commandToExecute;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public <T> void optionChanged(Option<T> option, T oldValue, T newValue) {
private int originalTopLine;
private Command command;
private SearchCommandParser searchParser;
private CommandLineHistory history = new CommandLineHistory();

public SearchMode(EditorAdaptor editorAdaptor) {
super(editorAdaptor);
Expand All @@ -77,7 +78,7 @@ public void enterMode(ModeSwitchHint... args) {
command = ((ExecuteCommandHint.OnLeave) args[1]).getCommand();
startPos = editorAdaptor.getCursorService().getPosition();
originalTopLine = editorAdaptor.getViewportService().getViewPortInformation().getTopLine();
searchParser = new SearchCommandParser(editorAdaptor, command);
searchParser = new SearchCommandParser(editorAdaptor, command, history);
super.enterMode(args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ public EclipseUserInterfaceService(IEditorPart editor, ITextViewer textViewer) {
editor.getSite().getWorkbenchWindow().getPartService().addPartListener(new PartChangeListener());
}

public void setCommandLine(String content) {
public void setCommandLine(String content, int position) {
statusLine.setContent(content);
statusLine.setCaretPosition(position);
}

public void setEditorMode(String modeName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
*/
public class StatusLine implements PaintListener {

private final static int COMMAND_CHAR_INDENT = 5;
private int horScroll = 0;
private int verScroll = 0;
private String content = "";
private final StyledText parent;
private Rectangle currentRect;
private int position = 0;

public StatusLine(StyledText textWidget) {
this.parent = textWidget;
Expand All @@ -41,12 +43,17 @@ public void paintControl(PaintEvent e) {
if (horScroll == parent.getHorizontalBar().getSelection()
&& verScroll == parent.getVerticalBar().getSelection()) {
e.gc.setLineWidth(1);
// Color color = e.gc.getForeground();
// e.gc.setForeground(new Color(e.display, 0, 0, 0));
e.gc.fillRectangle(rect);
e.gc.drawRectangle(rect);
// e.gc.setForeground(color);
e.gc.drawString(content, 5, bottom - height + offset);
int x1 = COMMAND_CHAR_INDENT;
e.gc.drawString(content, x1, bottom - height + offset);
// draw the caret
int y1 = bottom - height + offset;
int y2 = bottom + offset;
for (int i = 0; i < position; i++) {
x1 += e.gc.getAdvanceWidth(content.charAt(i));
}
e.gc.drawLine(x1, y1, x1, y2);
} else {
parent.redraw();
horScroll = parent.getHorizontalBar().getSelection();
Expand Down Expand Up @@ -74,6 +81,14 @@ public void setContent(String content) {
}
}

/** Set the position of the caret in characters.
*
* @param position the position of the caret in characters.
*/
public void setCaretPosition(int position) {
this.position = position;
}

/**
* Controls whether the status line will be painted into the parent component.
* @param enabled whether the status line will be painted.
Expand Down

0 comments on commit 1622d4a

Please sign in to comment.