Commits

Anonymous committed b2d74e8

Indenting on tab did not work correctly. It still doesn't work correctly if line before was inside a string.

  • Participants
  • Parent commits a85f82f

Comments (0)

Files changed (10)

File org.lispdev.editor/src/org/lispdev/editor/actions/IndentAction.java

 package org.lispdev.editor.actions;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.IRegion;
 import org.lispdev.log.Log;
 import org.lispdev.parser.nodes.Hidden;
 import org.lispdev.parser.nodes.Node;
+import org.lispdev.parser.nodes.Sexp;
+import org.lispdev.parser.nodes.SexpInfo;
 import org.lispdev.parser.nodes.TreeRoot;
+import org.lispdev.parser.nodes.TreeWalker;
 
 public class IndentAction extends LispAction
 {
   public IndentAction()
-  {
-  }
+  {}
 
   public IndentAction(LispEditor editor)
   {
     this.editor = editor;
   }
 
+  private static String getLine(IDocument doc, IRegion lineInfo)
+  {
+    try
+    {
+      return doc.get(lineInfo.getOffset(),lineInfo.getLength());
+    }
+    catch(BadLocationException e)
+    {
+      return null;
+    }
+  }
+
   /**
-   * @param str
-   * @return number of white spaces in front of string
+   * @return number of white spaces in front of line
    */
-  private static int getIndent(String str)
+  private static int getIndent(IDocument doc, IRegion lineInfo)
   {
+    String str = getLine(doc,lineInfo);
     int i = 0;
     while( i < str.length() && Character.isWhitespace(str.charAt(i)) )
     {
     return i;
   }
 
+  static String getLineIndent(IDocument doc, TreeRoot ast, int offset,
+      List<String> indents)
+  {
+    if( offset < 0 || offset > doc.getLength() ) return "";
 
+    Assert.isNotNull(ast);
+    Sexp s0 = ast.getIndentSexp(offset-1);
+    if( s0 == null ) return IndentOnEnter.getNaturalIndent(offset, doc);
+    SexpInfo s0info = TreeWalker.getInfo(s0);
+    if( s0info.offset + s0info.length <= offset )
+    {
+      if( !s0.hasError() )
+      {
+        if( s0.parent() instanceof TreeRoot )
+        {
+          return "";
+        }
+        else
+        {
+          s0 = (Sexp)s0.parent();
+          s0info = TreeWalker.getInfo(s0);
+        }
+      }
+    }
+
+    try
+    {
+      final int funcLine = doc.getLineOfOffset(s0info.offset);
+      final int funcLineOffset = doc.getLineOffset(funcLine);
+      final int endlOffset = doc.getLineLength(funcLine) + funcLineOffset;
+      final int currentLine = doc.getLineOfOffset(offset);
+
+      String indent = indents.get(indents.size() + funcLine - currentLine);
+
+      return IndentOnEnter.getIndent(doc, offset, s0, s0info, funcLine,
+          funcLineOffset, endlOffset, indent.toString());
+    }
+    catch(BadLocationException e)
+    {
+      Log.logException(e);
+      return "";
+    }
+
+  }
 
   /**
    * Changes indents of lines containing specified range.
     int newOffsetLength = length;
     int newi0Offset = i0;
     int i0length = i0 - offset;
+    TreeRoot ast = EditorPlugin.get().getAst(doc);
+    if( ast == null ) return null;
 
     try
     {
+      // make sure that selection and caret positions are maintained
       final int firstLine = doc.getLineOfOffset(offset);
       IRegion firstLineInfo = doc.getLineInformation(firstLine);
       final int i0Line = doc.getLineOfOffset(i0);
       final int lastLine = doc.getLineOfOffset(offset + length);
       IRegion lastLineInfo = doc.getLineInformation(lastLine);
 
-      // get first line trimmed position - i.e. look at offset
-      // and find what it would be relative to beginning of the line
-      // if old indenting is removed
+      // get the first line trimmed position relative to offset
       final int firstTrimedOffset =
-        Math.max(0, offset - firstLineInfo.getOffset() -
-            getIndent(doc.get(firstLineInfo.getOffset(),firstLineInfo.getLength())));
+        Math.max(0, offset - firstLineInfo.getOffset()
+            - getIndent(doc,firstLineInfo));
 
       // get i0 line trimmed position
       final int i0TrimedOffset =
         Math.max(0, offset + i0length - i0LineInfo.getOffset() -
-            getIndent(doc.get(i0LineInfo.getOffset(), i0LineInfo.getLength())));
+            getIndent(doc,i0LineInfo));
 
       int newi0LineOffset = i0LineInfo.getOffset();
 
       // get last line trimmed position
       final int lastTrimedOffset =
         Math.max(0, offset + length - lastLineInfo.getOffset() -
-            getIndent(doc.get(lastLineInfo.getOffset(), lastLineInfo.getLength())));
+            getIndent(doc,lastLineInfo));
 
       int newLastLineOffset = lastLineInfo.getOffset();
 
       int lastIndentNew = 0;
       int i0IndentNew = 0;
       StringBuilder sb = new StringBuilder();
-      TreeRoot ast = EditorPlugin.get().getAst(doc);
       int endoffset = firstLineInfo.getOffset();
+      List<String> indents = new ArrayList<String>(lastLine - firstLine + 1);
       for(int funcLine = firstLine; funcLine <= lastLine; ++funcLine)
       {
         IRegion lineInfo = doc.getLineInformation(funcLine);
           {
             sb.append(doc.get(endoffset, lineInfo.getOffset() - endoffset));
           }
-          String indent =
-            IndentOnEnter.getIndent(lineInfo.getOffset(), doc);
+          endoffset = lineInfo.getOffset();
+
+          String indent = getLineIndent(doc, ast, endoffset, indents);
+          indents.add(indent);
+
           sb.append(indent);
-          int indentOld =
-            getIndent(doc.get(lineInfo.getOffset(), lineInfo.getLength()));
+          int indentOld = getIndent(doc,lineInfo);
           sb.append(doc.get(lineInfo.getOffset()+indentOld,
               lineInfo.getLength()-indentOld));
-          endoffset = lineInfo.getOffset() + lineInfo.getLength();
+          endoffset += lineInfo.getLength();
           if( funcLine == firstLine )
           {
             firstIndentNew = indent.length();

File org.lispdev.editor/src/org/lispdev/editor/autoedits/IndentOnEnter.java

 import java.util.HashSet;
 import java.util.Set;
 
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.DocumentCommand;
 import org.eclipse.jface.text.IAutoEditStrategy;
 import org.lispdev.parser.nodes.SexpInfo;
 import org.lispdev.parser.nodes.TreeRoot;
 import org.lispdev.parser.nodes.TreeWalker;
-import org.lispdev.parser.tokens.ParseType;
 
 public class IndentOnEnter implements IAutoEditStrategy
 {
   }
 
   /**
-   * Find sexp to use to figure out indent
-   * @param offset character offset before caret
-   * @param ast parsed tree
-   */
-  private static Sexp getIndentSexp(int offset, IDocument doc)
-  {
-    TreeRoot ast = EditorPlugin.get().getAst(doc);
-    if( ast == null ) return null;
-    Node n = ast.getNodeAtOffset(offset);
-    if( n == null ) return null;
-    Sexp s0 = ( n.firstToken().parseType() == ParseType.OPEN_PAREN
-        ? (Sexp)n : TreeWalker.getSexp(n) );
-    return s0;
-
-  }
-
-  /**
    * @return indent of current line
    */
-  static String getNaturalIndent(int offset, IDocument doc)
+  public static String getNaturalIndent(int offset, IDocument doc)
   {
     StringBuilder res = new StringBuilder();
     try
       		"multiple-value-bind with-slot").split(" "))
   );
 
-  /**
-   * Calculates number of spaces for the indent of string containing
-   * offset. (relative to previous string)
-   * @param offset
-   * @param doc
-   * @return
-   */
-  public static String getIndent(int offset, IDocument doc)
+  public static String getIndent(IDocument doc, int offset, Sexp s0,
+      SexpInfo s0info, int funcLine, int funcLineOffset, int endlOffset,
+      String indent0)
   {
-    if( offset < 0 || offset > doc.getLength() ) return "";
-
-    Sexp s0 = getIndentSexp(offset-1,doc);
-    if( s0 == null ) return getNaturalIndent(offset, doc);
-    SexpInfo s0info = TreeWalker.getInfo(s0);
-    if( s0info.offset + s0info.length <= offset )
-    {
-      if( !s0.hasError() )
-      {
-        if( s0.parent() instanceof TreeRoot )
-        {
-          return "";
-        }
-        else
-        {
-          s0 = (Sexp)s0.parent();
-          s0info = TreeWalker.getInfo(s0);
-        }
-      }
-    }
-
     try
     {
-      final int funcLine = doc.getLineOfOffset(s0info.offset);
-      final int funcLineOffset = doc.getLineOffset(funcLine);
-      final int endlOffset = doc.getLineLength(funcLine) + funcLineOffset;
-
-      StringBuilder indent = new StringBuilder();
-
-      // initialize indent to start of s0
-      for (int i = funcLineOffset; i < s0info.offset; ++i)
-      {
-        indent.append(doc.getChar(i) == '\t' ? '\t' : ' ');
-      }
+      StringBuilder indent = new StringBuilder(indent0);
 
       indent.append(' '); //first token (i.e. opening paren) indent
       final int firstTokenSize = s0.firstToken().text().length();
         indent.append(' ');
       }
 
-      // get indent to first element if it is on the same line
+      // get indent to the first element if it is on the same line
       // as '(' and if it exist
       if( s0info.elements != null && s0info.elements.size() > 0 )
       {
         }
 
       }
+    }
+    catch(BadLocationException e)
+    {
+      return indent0;
+    }
+  }
 
+  /**
+   * Calculates number of spaces for the indent of string containing
+   * offset. (relative to previous string)
+   * @param offset
+   * @param doc
+   * @return
+   */
+  public static String getIndent(int offset, IDocument doc)
+  {
+    if( offset < 0 || offset > doc.getLength() ) return "";
+
+    TreeRoot ast = EditorPlugin.get().getAst(doc);
+    Assert.isNotNull(ast);
+    Sexp s0 = ast.getIndentSexp(offset-1);
+    if( s0 == null ) return getNaturalIndent(offset, doc);
+    SexpInfo s0info = TreeWalker.getInfo(s0);
+    if( s0info.offset + s0info.length <= offset )
+    {
+      if( !s0.hasError() )
+      {
+        if( s0.parent() instanceof TreeRoot )
+        {
+          return "";
+        }
+        else
+        {
+          s0 = (Sexp)s0.parent();
+          s0info = TreeWalker.getInfo(s0);
+        }
+      }
+    }
+
+    try
+    {
+      final int funcLine = doc.getLineOfOffset(s0info.offset);
+      final int funcLineOffset = doc.getLineOffset(funcLine);
+      final int endlOffset = doc.getLineLength(funcLine) + funcLineOffset;
+
+      StringBuilder indent = new StringBuilder();
+
+      // initialize indent to start of s0
+      for (int i = funcLineOffset; i < s0info.offset; ++i)
+      {
+        indent.append(doc.getChar(i) == '\t' ? '\t' : ' ');
+      }
+
+      return getIndent(doc, offset, s0, s0info, funcLine,
+          funcLineOffset, endlOffset, indent.toString());
     }
     catch(BadLocationException e)
     {

File org.lispdev.parser/src/org/lispdev/parser/nodes/Hidden.java

 
 
 /**
- * Hidden node contains space characters.
+ * Hidden node contains space characters and comments (but not outline comments)
  */
 public class Hidden extends Node
 {

File org.lispdev.parser/src/org/lispdev/parser/nodes/TreeRoot.java

   }
 
   /**
-   * @param root root of the tree
    * @param offset look for node containing this offset
    * @return smallest node containing this offset, if the node is a bracket
    * then its parent (which is a list) is returned
     }
     return res;
   }
+
+  /**
+   * Find sexp to use to figure out indent
+   * @param offset character offset before caret
+   */
+  public Sexp getIndentSexp(int offset)
+  {
+    Node n = getNodeAtOffset(offset);
+    if( n == null ) return null;
+    Sexp s0 = ( n.firstToken().parseType() == ParseType.OPEN_PAREN
+        ? (Sexp)n : TreeWalker.getSexp(n) );
+    return s0;
+  }
 }

File org.lispdev.parser/src/org/lispdev/parser/tokens/ParseType.java

 package org.lispdev.parser.tokens;
 
+import org.lispdev.parser.nodes.Hidden;
+
 /**
  * Type of token. Parser decisions on tree construction are based on ParseType
  * of a token. Mutually exclusive types. There are additional property
 
   /**
    * All such tokens are put into hidden nodes, which are then ignored by
-   * tree walkers that analyze tree.
+   * tree walkers that analyze tree. See {@link Hidden}
    */
   HIDDEN,
 

File org.lispdev.parser/src/org/lispdev/parser/tokens/TokenMLC.java

 
 import org.lispdev.parser.ParseError;
 
+/**
+ * Multi line comment
+ */
 public class TokenMLC extends Token
 {
   public TokenMLC(int offset, String text, ParseError error, int EOLcount)

File org.lispdev.parser/src/org/lispdev/parser/tokens/TokenOutline.java

 package org.lispdev.parser.tokens;
 
 
+/**
+ * Outline token (single line comment with number of ';' in front >= 4
+ */
 public class TokenOutline extends Token
 {
-  final int lvl; // number of ; in front
+  /**
+   * number of ';' in front
+   */
+  final int lvl;
   final ParseType parseType;
   public TokenOutline(int offset, String text, int lvl,
       boolean isHidden, int EOLcount)

File org.lispdev.parser/src/org/lispdev/parser/tokens/TokenSLC.java

 package org.lispdev.parser.tokens;
 
 
+/**
+ * Single line comment
+ */
 public class TokenSLC extends Token
 {
   final int lvl; // number of ; in front

File org.lispdev.parser/src/org/lispdev/parser/tokens/TokenString.java

 
 import org.lispdev.parser.ParseError;
 
+/**
+ * String token
+ */
 public class TokenString extends Token
 {
   public TokenString(int offset, String text, ParseError error, int EOLcount)

File org.lispdev.replview/src/org/lispdev/replview/ReplConsolePage.java

 
   @Override
   public void setActionBars(IActionBars actionBars)
-  {
-  }
+  {}
 
   @Override
   public void setFocus()