📄 pyautoindentstrategy.java
字号:
String ifIndent = PySelection.getIndentationFromLine(previousIfLine);
String lineIndent = PySelection.getIndentationFromLine(lineContents);
String indent = prefs.getIndentationString();
if(lineIndent.length() == ifIndent.length()+indent.length()){
Tuple<String,Integer> dedented = removeFirstIndent(lineContents);
ps.replaceLineContentsToSelection(dedented.o1);
command.offset = command.offset - dedented.o2;
return dedented;
}
}
}
}
return null;
}
public Tuple<String, Integer> autoDedentAfterColon(IDocument document, DocumentCommand command) throws BadLocationException {
Tuple<String, Integer> ret = null;
if((ret = autoDedentAfterColon(document, command, "else", PySelection.TOKENS_BEFORE_ELSE)) != null){
return ret;
}
if((ret = autoDedentAfterColon(document, command, "except", PySelection.TOKENS_BEFORE_EXCEPT)) != null){
return ret;
}
if((ret = autoDedentAfterColon(document, command, "finally", PySelection.TOKENS_BEFORE_FINALLY)) != null){
return ret;
}
return null;
}
/**
* This function makes the else auto-dedent (if available)
* @return the new indent and the number of chars it has been dedented (so, that has to be considered as a shift to the left
* on subsequent things).
*/
public Tuple<String, Integer> autoDedentElif(IDocument document, DocumentCommand command) throws BadLocationException {
return autoDedentAfterColon(document, command, "elif", PySelection.TOKENS_BEFORE_ELSE);
}
/**
* Create the indentation string after comma and a newline.
*
* @param document
* @param text
* @param offset
* @param selection
* @return Indentation String
* @throws BadLocationException
*/
private String makeSmartIndent(String text, int smartIndent)
throws BadLocationException {
if (smartIndent > 0) {
String initial = text;
// Discard everything but the newline from initial, since we'll
// build the smart indent from scratch anyway.
initial = getCharsBeforeNewLine(initial);
// Create the actual indentation string
String indentationString = prefs.getIndentationString();
int indentationSteps = smartIndent / prefs.getTabWidth();
int spaceSteps = smartIndent % prefs.getTabWidth();
StringBuffer b = new StringBuffer(smartIndent);
while (indentationSteps > 0){
indentationSteps -= 1;
b.append(indentationString);
}
if(prefs.getUseSpaces()){
while (spaceSteps >= 0){
spaceSteps -= 1;
b.append(" ");
}
}
return initial + b.toString();
}
return text;
}
/**
* @param initial
* @return
*/
private String getCharsBeforeNewLine(String initial) {
int initialLength = initial.length();
for (int i = 0; i < initialLength; i++) {
char theChar = initial.charAt(i);
// This covers all cases I know of, but if there is any platform
// with weird newline then this would need to be smarter.
if (theChar != '\r' && theChar != '\n') {
if (i > 0) {
initial = initial.substring(0, i);
}
break;
}
}
return initial;
}
/**
* Private function which is called when a colon is the command.
*
* The following code will auto-replace colons in function declaractions
* e.g., def something(self): ^ cursor before the end colon
*
* Typing another colon (i.e, ':') at that position will not insert another
* colon
*
* @param document
* @param command
* @throws BadLocationException
*/
private void performColonReplacement(IDocument document, DocumentCommand command) {
PySelection ps = new PySelection(document, command.offset);
int absoluteOffset = ps.getAbsoluteCursorOffset();
int documentLength = ps.getDoc().getLength();
// need to check whether whether we're at the very end of the document
if (absoluteOffset < documentLength) {
try {
char currentCharacter = document.getChar(absoluteOffset);
if (currentCharacter == ':') {
command.text = DocUtils.EMPTY_STRING;
command.caretOffset = command.offset + 1;
}
} catch (BadLocationException e) {
// should never happen because I just checked the length
throw new RuntimeException(e);
}
}
}
/**
* Private function to call to perform any replacement of braces.
*
* The Eclipse Java editor does this by default, and it is very useful. If
* you try to insert some kind of pair, be it a parenthesis or bracket in
* Java, the character will not insert and instead the editor just puts your
* cursor at the next position.
*
* This function performs the equivalent for the Python editor.
*
* @param document
* @param command if the command does not contain a brace, this function does nothing.
* @throws BadLocationException
*/
private void performPairReplacement(IDocument document, DocumentCommand command) throws BadLocationException {
PySelection ps = new PySelection(document, command.offset);
char c = ps.getCharAtCurrentOffset();
char peer = DocUtils.getPeer(c);
StringBuffer doc = new StringBuffer(document.get());
//it is not enough just counting the chars, we have to ignore those that are within comments or literals.
ParsingUtils.removeCommentsWhitespacesAndLiterals(doc);
int chars = PyAction.countChars(c, doc);
int peers = PyAction.countChars(peer, doc);
if( chars == peers){
//if we have the same number of peers, we want to eat the char
command.text = DocUtils.EMPTY_STRING;
command.caretOffset = command.offset + 1;
}
}
/**
* @param ps
* @param c the char to close
* @return
* @throws BadLocationException
*/
private boolean shouldClose(PySelection ps, char c) throws BadLocationException {
String line = ps.getLine();
String lineContentsFromCursor = ps.getLineContentsFromCursor();
for (int i = 0; i < lineContentsFromCursor.length(); i++) {
if (!Character.isWhitespace(lineContentsFromCursor.charAt(i))) {
return false;
}
}
int i = PyAction.countChars(c, line);
int j = PyAction.countChars(c, line);
if (j > i) {
return false;
}
return true;
}
/**
* Return smart indent amount for new line. This should be done for
* multiline structures like function parameters, tuples, lists and
* dictionaries.
*
* Example:
*
* a=foo(1, #
*
* We would return the indentation needed to place the caret at the #
* position.
*
* @param document The document
* @param offset The document offset of the last character on the previous line
* @param ps
* @return indent, or -1 if smart indent could not be determined (fall back to default)
* and a boolean indicating if we're inside a parenthesis
*/
public static Tuple<Integer,Boolean> determineSmartIndent(int offset, PySelection ps, IIndentPrefs prefs)
throws BadLocationException {
IDocument document = ps.getDoc();
PythonPairMatcher matcher = new PythonPairMatcher(DocUtils.BRACKETS);
int openingPeerOffset = matcher.searchForAnyOpeningPeer(offset, document);
if(openingPeerOffset == -1){
return new Tuple<Integer,Boolean>(-1, false);
}
//ok, now, if the opening peer is not on the line we're currently, we do not want to make
//an 'auto-indent', but keep the current indentation level
final IRegion lineInformationOfOffset = document.getLineInformationOfOffset(openingPeerOffset);
if(!PySelection.isInside(offset, lineInformationOfOffset)){
return new Tuple<Integer,Boolean>(-1, true);
}
int len = -1;
String contents = "";
if(prefs.getIndentToParLevel()){
//now, there's a little catch here, if we are in a line with an opening peer,
//we have to choose whether to indent to the opening peer or a little further
//e.g.: if the line is
//method( self <<- a new line here should indent to the start of the self and not
//to the opening peer.
if(openingPeerOffset < offset){
String fromParToCursor = document.get(openingPeerOffset, offset-openingPeerOffset);
if(fromParToCursor.length() > 0 && fromParToCursor.charAt(0) == '('){
fromParToCursor = fromParToCursor.substring(1);
if(!PySelection.containsOnlyWhitespaces(fromParToCursor)){
final int firstCharPosition = PySelection.getFirstCharPosition(fromParToCursor);
openingPeerOffset += firstCharPosition;
}
}
}
int openingPeerLineOffset = lineInformationOfOffset.getOffset();
len = openingPeerOffset - openingPeerLineOffset;
contents = document.get(openingPeerLineOffset, len);
}else{
//ok, we have to get the
int line = document.getLineOfOffset(openingPeerOffset);
final String indent = prefs.getIndentationString();
contents = PySelection.getLine(document, line);
contents = PySelection.getIndentationFromLine(contents);
contents += indent.substring(0, indent.length()-1); //we have to make it -1 (that's what the smartindent expects)
len = contents.length();
}
//add more spaces for each tab
for(int i = 0; i<contents.length(); i++){
if(contents.charAt(i) == '\t'){
len += prefs.getTabWidth() - 1;
}
}
return new Tuple<Integer,Boolean>(len, true);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -