package com.stardust.scriptdroid.ui.edit.completion;
import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import com.google.gson.Gson;
import com.stardust.pio.PFile;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.jecelyin.editor.v2.core.widget.TextView;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Created by Stardust on 2017/2/17.
*/
public class CodeCompletion implements TextWatcher {
public static class CodeCompletionItem implements Comparable<CodeCompletionItem> {
String mDisplayText, mAppendText;
CodeCompletionItem(String displayText, String appendText) {
mDisplayText = displayText;
mAppendText = appendText;
}
CodeCompletionItem(String text) {
this(text, text);
}
public String getAppendText() {
return mAppendText;
}
public String getDisplayText() {
return mDisplayText;
}
@Override
public int compareTo(CodeCompletionItem o) {
return mDisplayText.compareTo(o.mDisplayText);
}
}
interface OnCodeCompletionChangeListener {
void OnCodeCompletionChange(Collection<CodeCompletionItem>... list);
}
private static final String TAG = "CodeCompletion";
private OnCodeCompletionChangeListener mOnCodeCompletionChangeListener;
private TextView mEditText;
public CodeCompletion(OnCodeCompletionChangeListener listener) {
mOnCodeCompletionChangeListener = listener;
}
public void setEditText(TextView editText) {
mEditText = editText;
mEditText.addTextChangedListener(this);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
int position = mEditText.getSelectionStart();
String str = parseWordBefore(s, position);
if (!TextUtils.isEmpty(str))
searchCodeCompletion(str);
else
mOnCodeCompletionChangeListener.OnCodeCompletionChange(DEFAULT_CODE_COMPLETION_LIST);
}
private String parseWordBefore(Editable s, int position) {
int i;
for (i = position - 1; i >= 0; i--) {
if (position - i > KEY_WORD_LENGTH_MAX) {
return null;
}
if (!Character.isLetter(s.charAt(i))) {
break;
}
}
if (i < position - 1) {
return s.subSequence(i + 1, position).toString();
}
return null;
}
private static final String[] KEYWORDS = {"arguments", "break", "case", "catch", "class", "continue", "default", "do", "else", "eval", "export", "false", "for", "function", "if", "import", "in", "int", "new", "null", "package", "return", "switch", "this", "throw", "throws", "true", "try", "typeof", "var", "volatile", "while", "with", "Array", "Date", "hasOwnProperty", "Infinity", "isFinite", "isNaN", "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String", "toString", "undefined", "valueOf"};
private static final int KEY_WORD_LENGTH_MAX = 15;
public void setFunctions(String[] functions) {
mFunctions = functions;
}
private String[] mFunctions = new String[0];
private boolean searchCodeCompletion(String str) {
Collection<CodeCompletionItem> c = searchWordCompletion(str);
c.addAll(searchCodeCompletion(str, mFunctions));
c.addAll(searchKeyWordCompletion(str));
if (c.size() > 0) {
mOnCodeCompletionChangeListener.OnCodeCompletionChange(c, DEFAULT_CODE_COMPLETION_LIST);
return true;
} else {
mOnCodeCompletionChangeListener.OnCodeCompletionChange(DEFAULT_CODE_COMPLETION_LIST);
return false;
}
}
private Collection<CodeCompletionItem> searchWordCompletion(String str) {
if (mEditText.getEditableText().length() < Pref.getMaxTextLengthForCodeCompletion()) {
return searchCodeCompletion(str, splitWord(mEditText.getEditableText().toString()));
}
return new TreeSet<>();
}
private Collection<CodeCompletionItem> searchCodeCompletion(String str, String[] words) {
Set<CodeCompletionItem> set = new TreeSet<>();
for (String word : words) {
// TODO: 2017/2/18 优化 字典树
if (word.startsWith(str) && str.length() < word.length()) {
set.add(new CodeCompletionItem(word, word.substring(str.length())));
}
}
return set;
}
private String[] splitWord(String s) {
// TODO: 2017/2/18 优化。利用上次结果
return s.split("[\\W]");
}
private Collection<CodeCompletionItem> searchKeyWordCompletion(String str) {
return searchCodeCompletion(str, KEYWORDS);
}
private static final String[] DEFAULT_CODE_COMPLETIONS = new String[]{"=", "(", ")", ";", "{", "}", "\"", "!", "[", "]", "\\", ">", "<", ".", ", "};
private static final List<CodeCompletionItem> DEFAULT_CODE_COMPLETION_LIST = new ArrayList<>();
static {
for (String str : DEFAULT_CODE_COMPLETIONS) {
DEFAULT_CODE_COMPLETION_LIST.add(new CodeCompletionItem(str));
}
}
}