Identation

Questions on using RSyntaxTextArea should go here.

Moderator: robert

Identation

Postby jorgebonafe » Mon Jun 21, 2010 1:55 pm

I have a question about identation. Suposing I made a file to use RSTA with a new language, and I wanted to make an auto-identation code for something different then { }, like pascal, for instance:
Code: Select all
begin
   etc...
   etc...
end


Do you know which files or functions should I look for to make that possible?
jorgebonafe
 
Posts: 6
Joined: Fri Jun 18, 2010 7:15 pm

Re: Identation

Postby robert » Mon Jun 21, 2010 5:35 pm

RSTA currently only supports automatic auto-indentation based on curly braces. For languages that don't use C-style indentation rules, you would have to roll your own indentation support. This would probably involve just overriding the Action in the text area's ActionMap corresponding to "DefaultEditorKit.insertBreakAction" with your own Action that scanned the tokens on the previous line (or earlier lines if necessary) to make the ultimate decision.

I've considered allowing TokenMakers to register handlers for the newline action in the past. This would allow for any language to implement auto-indentation however they want. The problem would be that it would be difficult/impossible to handle auto-indenting the "closing" token (such as '}' or "end") this way, since it would be just a newline-based approach. The most robust solution, of course, is to have each TokenMaker able to arbitrarily manipulate the InputMap/ActionMap of the parent RSyntaxTextArea. If you'd like to see something like this implemented in the future, please fill out a feature request on the project's SourceForge page.

For the time being though, your best bet is to simply modify the text area's ActionMap yourself.
User avatar
robert
 
Posts: 639
Joined: Sat May 10, 2008 5:16 pm

Re: Identation

Postby jorgebonafe » Mon Jun 21, 2010 7:39 pm

Thanks for the reply. I found a way to do this... Not very pretty, but its works just fine for now...
I'll put the code here in case anyone is interested. I just altered the RSyntaxTextAreaEditorKit class. Right after possiblyCloseCurlyBrace I added possiblyCloseTokens(sta, leadingWS); , and then added some functions. The strings are for open and closing tokens.

Code: Select all
      private void possiblyCloseTokens(RSyntaxTextArea textArea,String leadingWS) {
         RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument();

         int line = textArea.getCaretLineNumber();
         Token t = doc.getTokenListForLine(line-1);
         t = t.getLastNonCommentNonWhitespaceToken();

         if (t!=null && t.getLexeme().equalsIgnoreCase("por favor")) {
            if (getOpenTokenCount(doc,"por favor","obrigado")>0) {
               StringBuffer sb = new StringBuffer();
               if (line==textArea.getLineCount()-1) {
                  sb.append('\n');
               }
               if (leadingWS!=null) {
                  sb.append(leadingWS);
               }
               sb.append("Obrigado\n");
               int dot = textArea.getCaretPosition();
               int end = textArea.getLineEndOffsetOfCurrentLine();
               textArea.insert(sb.toString(), end);
               textArea.setCaretPosition(dot);
            }
         }
         else if (t!=null && t.getLexeme().equalsIgnoreCase("[")) {
            if (getOpenTokenCount(doc,"[","]")>0) {
               StringBuffer sb = new StringBuffer();
               if (line==textArea.getLineCount()-1) {
                  sb.append('\n');
               }
               if (leadingWS!=null) {
                  sb.append(leadingWS);
               }
               sb.append("]\n");
               int dot = textArea.getCaretPosition();
               int end = textArea.getLineEndOffsetOfCurrentLine();
               textArea.insert(sb.toString(), end);
               textArea.setCaretPosition(dot);
            }
         }
      }

      private static final int getOpenTokenCount(RSyntaxDocument doc, String s1, String s2) {
         int openCount = 0;
         int size1 = s1.length();
         int size2 = s2.length();
         Element root = doc.getDefaultRootElement();
         int lineCount = root.getElementCount();
         for (int i=0; i<lineCount; i++) {
            Token t = doc.getTokenListForLine(i);
            while (t!=null && t.isPaintable()) {
               if (t.textCount==size1) {
                  String aux = t.getLexeme();
                  if (aux.equalsIgnoreCase(s1)) {
                     openCount++;
                  }
                  else if (size1==size2) {
                     if (aux.equalsIgnoreCase(s2))
                        openCount--;
                  }
               }
               else if (t.textCount==size2) {
                  String aux = t.getLexeme();
                  if (aux.equalsIgnoreCase(s2))
                     openCount--;
               }
               t = t.getNextToken();
            }
         }
         return openCount;
      }

I also edited the TokenMaker class for my language:
Code: Select all
   public boolean getShouldIndentNextLineAfter(Token t) {
      if (t!=null) {
         if (t.textCount==1) {
            char ch = t.text[t.textOffset];
            return ch=='[';
         }
         if (t.textCount>1) {
            return t.getLexeme().equalsIgnoreCase("por favor");            
         }
      }
      return false;
   }
jorgebonafe
 
Posts: 6
Joined: Fri Jun 18, 2010 7:15 pm


Return to Help

Who is online

Users browsing this forum: Google [Bot] and 0 guests

cron