*/
public abstract void setValue(@NotNull String name, @NotNull String value, @NotNull String defaultValue);
+ @Nullable
public abstract String[] getValues(@NonNls String name);
public abstract void setValues(@NonNls String name, String[] values);
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
import java.util.Map;
return myMap.containsKey(name);
}
+ @Nullable
@Override
public String[] getValues(@NonNls String name) {
final String value = getValue(name);
--- /dev/null
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.commandInterface.commandsWithArgs;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Information about command and its arguments to save in history / pass to execution etc.
+ *
+ * @author Ilya.Kazakevich
+ */
+public class CommandExecutionInfo {
+ /**
+ * Command and arguments separator.
+ */
+ private static final String SEPARATOR = " ";
+ @NotNull
+ private final String myCommandName;
+ @NotNull
+ private final String[] myArguments;
+
+ /**
+ * @param commandName command
+ * @param arguments its arguments
+ */
+ public CommandExecutionInfo(@NotNull final String commandName, @NotNull final String... arguments) {
+ myCommandName = commandName;
+ myArguments = arguments.clone();
+ }
+
+ /**
+ * @return command
+ */
+ @NotNull
+ public String getCommandName() {
+ return myCommandName;
+ }
+
+ /**
+ * @return command arguments
+ */
+ @NotNull
+ public String[] getArguments() {
+ return myArguments.clone();
+ }
+
+ /**
+ * @return command in format "command arg1 arg2". Opposite to {@link #fromString(String)}
+ * @see #fromString(String)
+ */
+ @NotNull
+ public String toString() {
+ // TODO: What if command or argument has space in it? Escape somehow!
+ return StringUtil.join(ArrayUtil.mergeArrays(new String[]{myCommandName}, myArguments), SEPARATOR);
+ }
+
+ /**
+ * @param stringToUnserialize string created by {@link #toString()}
+ * @return command parsed from string
+ * @see #toString()
+ */
+ @Nullable
+ public static CommandExecutionInfo fromString(@NotNull final String stringToUnserialize) {
+ // TODO: What if command or argument has space in it? Escape somehow!
+ final List<String> strings = StringUtil.split(stringToUnserialize, SEPARATOR);
+ if (strings.isEmpty()) {
+ return null;
+ }
+ return new CommandExecutionInfo(strings.get(0), ArrayUtil.toStringArray(strings.subList(1, strings.size())));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CommandExecutionInfo)) return false;
+
+ CommandExecutionInfo info = (CommandExecutionInfo)o;
+
+ if (!Arrays.equals(myArguments, info.myArguments)) return false;
+ if (!myCommandName.equals(info.myCommandName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myCommandName.hashCode();
+ result = 31 * result + Arrays.hashCode(myArguments);
+ return result;
+ }
+}
}
if (!suggestionInfo.myShowOnlyWhenRequested && !suggestions.isEmpty()) {
+ final SuggestionsBuilder suggestionsBuilder = getBuilderWithHistory();
+ suggestionsBuilder.add(suggestions);
+
myView
- .displaySuggestions(new SuggestionsBuilder(suggestions, true), suggestionInfo.myAbsolute, null);
+ .displaySuggestions(suggestionsBuilder, suggestionInfo.myAbsolute, null);
}
else {
myView.removeSuggestions();
}
}
+ /**
+ * @return builder that already has history in its prefix group (see {@link com.jetbrains.python.suggestionList.SuggestionsBuilder})
+ */
+ @NotNull
+ private SuggestionsBuilder getBuilderWithHistory() {
+ final SuggestionsBuilder suggestionsBuilder = new SuggestionsBuilder();
+ final List<CommandExecutionInfo> history = getHistory();
+ final Collection<String> historyCommands = new LinkedHashSet<String>();
+ for (final CommandExecutionInfo info : history) {
+ historyCommands.add(info.toString());
+ }
+
+ if (!historyCommands.isEmpty()) {
+ // TODO: Later implement folding by name
+ suggestionsBuilder.changeGroup(false);
+ suggestionsBuilder
+ .add(ArrayUtil.toStringArray(historyCommands));
+ suggestionsBuilder.changeGroup(true);
+ }
+
+ return suggestionsBuilder;
+ }
+
+ /**
+ * @return execution info from history. It is empty by default, child should implement it.
+ */
+ @NotNull
+ protected List<CommandExecutionInfo> getHistory() {
+ return Collections.emptyList();
+ }
+
+ /**
+ * @return command that entered in box, or null of just entered
+ */
+ @Nullable
+ protected CommandExecutionInfo getCommandToExecute() {
+ return myStrategy.getCommandToExecute();
+ }
+
/**
* Finds and sets appropriate strategy
*/
final SuggestionInfo suggestionInfo = myStrategy.getSuggestionInfo();
final List<String> suggestions = suggestionInfo.getSuggestions();
if (!suggestions.isEmpty()) {
- myView.displaySuggestions(new SuggestionsBuilder(suggestions, true), suggestionInfo.myAbsolute, null);
+ final SuggestionsBuilder suggestionsBuilder = getBuilderWithHistory();
+ suggestionsBuilder.add(suggestions);
+ myView.displaySuggestions(suggestionsBuilder, suggestionInfo.myAbsolute, null);
}
}
*/
package com.jetbrains.python.commandInterface.commandsWithArgs;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
return ((lastPart != null) && !getSuggestionInfo().getSuggestions().contains(lastPart));
}
+ @Nullable
+ @Override
+ CommandExecutionInfo getCommandToExecute() {
+ return new CommandExecutionInfo(myCommand.getName(), ArrayUtil.toStringArray(myArguments));
+ }
+
@NotNull
@Override
ErrorInfo getShowErrorInfo() {
package com.jetbrains.python.commandInterface.commandsWithArgs;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
private boolean isTextBoxEmpty() {
return myPresenter.getView().getText().isEmpty();
}
+
+ @Nullable
+ @Override
+ CommandExecutionInfo getCommandToExecute() {
+ return null;
+ }
}
package com.jetbrains.python.commandInterface.commandsWithArgs;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
abstract SuggestionInfo getSuggestionInfo();
+ /**
+ * @return command that entered in box, or null of just entered
+ */
+ @Nullable
+ abstract CommandExecutionInfo getCommandToExecute();
+
+
/**
* @return errors
*/
private static class MyCellRenderer extends DefaultListCellRenderer {
@NotNull
private static final Color ODD_GROUP_SELECTED_BACKGROUND_COLOR =
- EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR);
+ EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.SELECTED_TEARLINE_COLOR);
@NotNull
private static final Color ODD_GROUP_BACKGROUND_COLOR =
- EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND);
+ EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.TEARLINE_COLOR);
@Override
public Component getListCellRendererComponent(final JList list,
if (element.myOddGroup) {
component.setBackground(isSelected ? ODD_GROUP_SELECTED_BACKGROUND_COLOR : ODD_GROUP_BACKGROUND_COLOR);
+ final Font oldFont = component.getFont();
+ component.setFont(new Font(oldFont.getName(), Font.ITALIC, oldFont.getSize()));
}
if (!(component instanceof JLabel)) {
/**
* Builds list of suggestions.
+ * <p/>
* You may create suggestions from words, you may add new groups and do other useful things.
* It works like chain pattern, so it returns itself.
+ * <p/>
+ * Builder consists of 2 groups: prefix (first one) and main (second one) group.
+ * Each may be empty.
+ * Use {@link #changeGroup(boolean)} to switch between them
*
* @author Ilya.Kazakevich
*/
public class SuggestionsBuilder {
+ private static final MySuggestionComparator SUGGESTION_COMPARATOR = new MySuggestionComparator();
@NotNull
- private final List<List<Suggestion>> myList = new ArrayList<List<Suggestion>>();
+ private final List<Suggestion> myPrefixGroup = new ArrayList<Suggestion>();
+ @NotNull
+ private final List<Suggestion> myMainGroup = new ArrayList<Suggestion>();
+ @NotNull
+ private List<Suggestion> myCurrentGroup = myMainGroup;
public SuggestionsBuilder() {
- myList.add(new ArrayList<Suggestion>());
+
}
/**
* @param words list of words to add (to the first group)
- * @param sort sort passed words
*/
- public SuggestionsBuilder(@NotNull List<String> words, final boolean sort) {
- this();
- if (sort) {
- // No guarantee passed argument is mutable
- //noinspection AssignmentToMethodParameter
- words = new ArrayList<String>(words);
- Collections.sort(words);
- }
+ public SuggestionsBuilder(@NotNull final List<String> words) {
add(words);
}
/**
- * Creates next group and sets it as default
+ * Switches to the next group and sets it as default
+ *
+ * @param main use main group if true, prefix otherwise
*/
- public SuggestionsBuilder nextGroup() {
- if (!getCurrentGroup().isEmpty()) {
- myList.add(new ArrayList<Suggestion>());
- }
+ public SuggestionsBuilder changeGroup(final boolean main) {
+ myCurrentGroup = (main ? myMainGroup : myPrefixGroup);
return this;
}
* @param strong strong or not
*/
public SuggestionsBuilder add(@NotNull final String text, final boolean strong) {
- getCurrentGroup().add(new Suggestion(text, strong));
+ myCurrentGroup.add(new Suggestion(text, strong));
+ Collections.sort(myCurrentGroup, SUGGESTION_COMPARATOR);
return this;
}
- /**
- * @return elements from current group
- */
- @NotNull
- private List<Suggestion> getCurrentGroup() {
- return myList.get(myList.size() - 1);
- }
/**
* @return all suggestions in format [group1[sugg1, sugg2]]
*/
@NotNull
List<List<Suggestion>> getList() {
- return Collections.unmodifiableList(myList);
+ return Collections.unmodifiableList(Arrays.asList(myPrefixGroup, myMainGroup));
}
+ @Override
+ public String toString() {
+ return "SuggestionsBuilder{" +
+ "myPrefixGroup=" + myPrefixGroup +
+ ", myMainGroup=" + myMainGroup +
+ ", myCurrentGroup=" + myCurrentGroup +
+ '}';
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
SuggestionsBuilder builder = (SuggestionsBuilder)o;
- if (!myList.equals(builder.myList)) return false;
+ if (!myPrefixGroup.equals(builder.myPrefixGroup)) return false;
+ if (!myMainGroup.equals(builder.myMainGroup)) return false;
return true;
}
@Override
public int hashCode() {
- return myList.hashCode();
+ int result = myPrefixGroup.hashCode();
+ result = 31 * result + myMainGroup.hashCode();
+ return result;
}
- @Override
- public String toString() {
- return "SuggestionsBuilder{" +
- "myList=" + myList +
- '}';
+ private static class MySuggestionComparator implements Comparator<Suggestion> {
+ @Override
+ public int compare(final Suggestion o1, final Suggestion o2) {
+ return o1.getText().compareTo(o2.getText());
+ }
}
}