📄 pyselection.java
字号:
int openParIndex = line.indexOf('(');
if (openParIndex == -1) { // we are in a line that does not have a parentesis
return null;
}
int lineOffset = getStartLineOffset();
StringBuffer buf = new StringBuffer();
String docContents = doc.get();
int i = lineOffset + openParIndex;
int j = ParsingUtils.eatPar(docContents, i, buf);
String insideParentesisTok = docContents.substring(i + 1, j);
StringTokenizer tokenizer = new StringTokenizer(insideParentesisTok, ",");
while (tokenizer.hasMoreTokens()) {
String tok = tokenizer.nextToken();
String trimmed = tok.split("=")[0].trim();
trimmed = trimmed.replaceAll("\\(", "");
trimmed = trimmed.replaceAll("\\)", "");
if (!addSelf && trimmed.equals("self")) {
// don't add self...
} else if(trimmed.length() > 0){
l.add(trimmed);
}
}
return new Tuple<List<String>, Integer>(l, j);
}
/**
* This function replaces all the contents in the current line before the cursor for the contents passed
* as parameter
*/
public void replaceLineContentsToSelection(String newContents) throws BadLocationException {
int lineOfOffset = getDoc().getLineOfOffset(getAbsoluteCursorOffset());
IRegion lineInformation = getDoc().getLineInformation(lineOfOffset);
getDoc().replace(lineInformation.getOffset(), getAbsoluteCursorOffset() - lineInformation.getOffset(), newContents);
}
public static final String[] TOKENS_BEFORE_ELSE = new String[]{
"if ", "if(", "for ", "for(", "except:", "except(", "while ", "while(", "elif ", "elif:"
};
public static final String[] TOKENS_BEFORE_EXCEPT = new String[]{
"try:"
};
public static final String[] TOKENS_BEFORE_FINALLY = new String[]{
"try:", "except:", "except("
};
/**
* This function goes backward in the document searching for an 'if' and returns the line that has it.
*
* May return null if it was not found.
*/
public String getPreviousLineThatStartsWithToken(String[] tokens) {
DocIterator iterator = new DocIterator(false, this);
while(iterator.hasNext()){
String line = (String) iterator.next();
String trimmed = line.trim();
for(String prefix:tokens){
if(trimmed.startsWith(prefix)){
return line;
}
}
}
return null;
}
public Tuple3<String, String, String> getPreviousLineThatStartsScope() {
return getPreviousLineThatStartsScope(PySelection.INDENT_TOKENS, true);
}
/**
* @return a tuple with:
* - the line that starts the new scope
* - a String with the line where some dedent token was found while looking for that scope.
* - a string with the lowest indent (null if none was found)
*/
public Tuple3<String, String, String> getPreviousLineThatStartsScope(String [] indentTokens, boolean considerCurrentLine) {
DocIterator iterator = new DocIterator(false, this);
if(considerCurrentLine){
iterator = new DocIterator(false, this);
}else{
iterator = new DocIterator(false, this, getCursorLine()-1, false);
}
String foundDedent = null;
int lowest = Integer.MAX_VALUE;
String lowestStr = null;
while(iterator.hasNext()){
String line = (String) iterator.next();
String trimmed = line.trim();
for (String dedent : indentTokens) {
if(trimmed.startsWith(dedent)){
if(isCompleteToken(trimmed, dedent)){
return new Tuple3<String, String, String>(line, foundDedent, lowestStr);
}
}
}
//we have to check for the first condition (if a dedent is found, but we already found
//one with a first char, the dedent should not be taken into consideration... and vice-versa).
if(lowestStr == null && foundDedent == null && startsWithDedentToken(trimmed)){
foundDedent = line;
}else if(foundDedent == null && trimmed.length() > 0){
int firstCharPosition = getFirstCharPosition(line);
if(firstCharPosition < lowest){
lowest = firstCharPosition;
lowestStr = line;
}
}
}
return null;
}
/**
* @param theDoc
* @param documentOffset
* @return
* @throws BadLocationException
*/
public static int eatFuncCall(IDocument theDoc, int documentOffset) throws BadLocationException {
String c = theDoc.get(documentOffset, 1);
if(c.equals(")") == false){
throw new AssertionError("Expecting ) to eat callable. Received: "+c);
}
while(documentOffset > 0 && theDoc.get(documentOffset, 1).equals("(") == false){
documentOffset -= 1;
}
return documentOffset;
}
/**
* Checks if the activationToken ends with some char from cs.
*/
public static boolean endsWithSomeChar(char cs[], String activationToken) {
for (int i = 0; i < cs.length; i++) {
if (activationToken.endsWith(cs[i] + "")) {
return true;
}
}
return false;
}
public static List<Integer> getLineStartOffsets(String replacementString) {
ArrayList<Integer> ret = new ArrayList<Integer>();
ret.add(0);//there is always a starting one at 0
//we may have line breaks with \r\n, or only \n or \r
for (int i = 0; i < replacementString.length(); i++) {
char c = replacementString.charAt(i);
if(c == '\r'){
i++;
int foundAt = i;
if(i < replacementString.length()){
c = replacementString.charAt(i);
if(c == '\n'){
// i++;
foundAt = i+1;
}
}
ret.add(foundAt);
}else if(c == '\n'){
ret.add(i+1);
}
}
return ret;
}
public static List<Integer> getLineBreakOffsets(String replacementString) {
ArrayList<Integer> ret = new ArrayList<Integer>();
int lineBreaks = 0;
int ignoreNextNAt = -1;
//we may have line breaks with \r\n, or only \n or \r
for (int i = 0; i < replacementString.length(); i++) {
char c = replacementString.charAt(i);
if(c == '\r'){
lineBreaks++;
ret.add(i);
ignoreNextNAt = i + 1;
}else if(c == '\n'){
if(ignoreNextNAt != i){
ret.add(i);
lineBreaks++;
}
}
}
return ret;
}
public static int countLineBreaks(String replacementString) {
int lineBreaks = 0;
int ignoreNextNAt = -1;
//we may have line breaks with \r\n, or only \n or \r
for (int i = 0; i < replacementString.length(); i++) {
char c = replacementString.charAt(i);
if(c == '\r'){
lineBreaks++;
ignoreNextNAt = i + 1;
}else if(c == '\n'){
if(ignoreNextNAt != i){
lineBreaks++;
}
}
}
return lineBreaks;
}
public static class ActivationTokenAndQual{
public ActivationTokenAndQual(String activationToken, String qualifier, boolean changedForCalltip, boolean alreadyHasParams) {
this.activationToken = activationToken;
this.qualifier = qualifier;
this.changedForCalltip = changedForCalltip;
this.alreadyHasParams = alreadyHasParams;
}
public String activationToken;
public String qualifier;
public boolean changedForCalltip;
public boolean alreadyHasParams;
}
/**
* Shortcut
*/
public String [] getActivationTokenAndQual(boolean getFullQualifier) {
return getActivationTokenAndQual(doc, getAbsoluteCursorOffset(), getFullQualifier);
}
/**
* Shortcut
*/
public ActivationTokenAndQual getActivationTokenAndQual(boolean getFullQualifier, boolean handleForCalltips) {
return getActivationTokenAndQual(doc, getAbsoluteCursorOffset(), getFullQualifier, handleForCalltips);
}
/**
* Shortcut
*/
public static String [] getActivationTokenAndQual(IDocument theDoc, int documentOffset, boolean getFullQualifier) {
ActivationTokenAndQual ret = getActivationTokenAndQual(theDoc, documentOffset, getFullQualifier, false);
return new String[]{ret.activationToken, ret.qualifier}; //will never be changed for the calltip, as we didn't request it
}
/**
* Returns the activation token.
*
* @param documentOffset the current cursor offset (we may have to change it if getFullQualifier is true)
* @param handleForCalltips if true, it will take into account that we may be looking for the activation token and
* qualifier for a calltip, in which case we should return the activation token and qualifier before a parentesis (if we're
* just after a '(' or ',' ).
*
* @return the activation token and the qualifier.
*/
public static ActivationTokenAndQual getActivationTokenAndQual(IDocument doc, int documentOffset, boolean getFullQualifier, boolean handleForCalltips) {
boolean changedForCalltip = false;
boolean alreadyHasParams = false; //only useful if we're in a calltip
int parOffset = -1;
if(handleForCalltips){
int calltipOffset = documentOffset-1;
//ok, in this case, we have to check if we're just after a ( or ,
if(calltipOffset > 0 && calltipOffset < doc.getLength()){
try {
char c = doc.getChar(calltipOffset);
while(Character.isWhitespace(c) && calltipOffset > 0){
calltipOffset--;
c = doc.getChar(calltipOffset);
}
if(c == '(' || c == ','){
//ok, we're just after a parentesis or comma, so, we have to get the
//activation token and qualifier as if we were just before the last parentesis
//(that is, if we're in a function call and not inside a list, string or dict declaration)
parOffset = calltipOffset;
calltipOffset = getBeforeParentesisCall(doc, calltipOffset);
if(calltipOffset != -1){
documentOffset = calltipOffset;
changedForCalltip = true;
}
}
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
}
if(parOffset != -1){
//ok, let's see if there's something inside the parentesis
try {
char c = doc.getChar(parOffset);
if(c == '('){ //only do it
parOffset++;
while(parOffset < doc.getLength()){
c = doc.getChar(parOffset);
if(c == ')'){
break; //finished the parentesis
}
if(!Character.isWhitespace(c)){
alreadyHasParams = true;
break;
}
parOffset++;
}
}else{
//we're after a comma, so, there surely is some parameter already
alreadyHasParams = true;
}
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
Tuple<String, Integer> tupPrefix = extractActivationToken(doc, documentOffset, getFullQualifier);
if(getFullQualifier == true){
//may have changed
documentOffset = tupPrefix.o2;
}
String activationToken = tupPrefix.o1;
documentOffset = documentOffset-activationToken.length()-1;
try {
while(documentOffset >= 0 && documentOffset < doc.getLength() && doc.get(documentOffset, 1).equals(".")){
String tok = extractActivationToken(doc, documentOffset, false).o1;
String c = doc.get(documentOffset-1, 1);
if(c.equals("]")){
activationToken = "list."+activationToken;
break;
}else if(c.equals("}")){
activationToken = "dict."+activationToken;
break;
}else if(c.equals("'") || c.equals("\"")){
activationToken = "str."+activationToken;
break;
}else if(c.equals(")")){
documentOffset = eatFuncCall(doc, documentOffset-1);
tok = extractActivationToken(doc, documentOffset, false).o1;
activationToken = tok+"()."+activationToken;
documentOffset = documentOffset-tok.length()-1;
}else if(tok.length() > 0){
activationToken = tok+"."+activationToken;
documentOffset = documentOffset-tok.length()-1;
}else{
break;
}
}
} catch (BadLocationException e) {
System.out.println("documentOffset "+documentOffset);
System.out.println("theDoc.getLength() "+doc.getLength());
e.printStackTrace();
}
String qualifier = "";
//we complete on '.' and '('.
//' ' gets globals
//and any other char gets globals on token and templates.
//we have to get the qualifier. e.g. bla.foo = foo is the qualifier.
if (activationToken.indexOf('.') != -1) {
while (endsWithSomeChar(new char[] { '.','[' }, activationToken) == false
&& activationToken.length() > 0) {
qualifier = activationToken.charAt(activationToken.length() - 1) + qualifier;
activationToken = activationToken.substring(0, activationToken.length() - 1);
}
} else { //everything is a part of the qualifier.
qualifier = activationToken.trim();
activationToken = "";
}
return new ActivationTokenAndQual(activationToken, qualifier, changedForCalltip, alreadyHasParams);
}
/**
* This function will look for a the offset of a method call before the current offset
*
* @param doc: an IDocument, String, StringBuffer or char[]
* @param calltipOffset the offset we should start looking for it
* @return the offset that points the location just after the activation token and qualifier.
*
* @throws BadLocationException
*/
public static int getBeforeParentesisCall(Object doc, int calltipOffset) {
char c = ParsingUtils.charAt(doc, calltipOffset);
while(calltipOffset > 0 && c != '('){
calltipOffset --;
c = ParsingUtils.charAt(doc, calltipOffset);
}
if(c == '('){
while(calltipOffset > 0 && Character.isWhitespace(c)){
calltipOffset --;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -