Mudar cor do texto (highlight) de palavras-chave

Hey guys!

Eu estava criando um projeto, uma IDE pra um “teaser” de uma linguagem de programação nova que estou criando (ela infelizmente terá de ser feita em C, mas eu estou criando esse projeto em Java pra já ir tendo conhecimento do que vai ser legal ou não e tal), ela é parecida com basic, mas ao mesmo tempo muito diferente.

Enfim, indo direto pro problema: eu queria mudar a cor do texto (ou seja, highlight do texto) das palavras-chave da linguagem, mas não estou vendo como. Eu vi na internet algumas coisas de bibliotecas e tal, mas elas são pra linguagens pré-definidas, mas a que eu vou usar não existe ainda, então não dá. Eu tentei umas coisas com StyleContext, DefaultStyledDocument, Style e umas coisas assim, mas não deu, e agora eu estou tentando criar um StyledEditorKit, mas não tem nenhum método pra mudar a cor do texto de palavras específicas.

Caso vá ajudar, posso mandar um pedaço do código pra vocês analisarem.

Antes de mais nada, tenho que perguntar:

Vc está criando um compilador (ou interpretador) pra sua linguagem ou apenas um editor de código capaz de colorir uma linguagem ficticia?

Do jeito que falou, parece que está focado em criar apenas um editor, mas este deveria ser a ultima das suas preocupações.

Se for mesmo por esse caminho, sugiro dar uma olhada neste projeto:

http://bobbylight.github.io/RSyntaxTextArea/

Segundo o site, ele extende o JTextComponent e suporta syntax highlight de mais de 40 linguagens e permite adicionar outras linguagens.

Vale lembrar que, para colorir sua linguagem num editor, vc não precisa criar um do zero. Vc pode criar o syntax highlight pra um editor já existente como, por exemplo, o Notepad++, veja aqui: http://docs.notepad-plus-plus.org/index.php/User_Defined_Languages

Ou pro Sublime Text: https://www.sublimetext.com/docs/3/syntax.html

Ou pro Atom: https://flight-manual.atom.io/hacking-atom/sections/creating-a-grammar/

Bons estudos.

Exemplo:

import java.awt.Color;
import java.util.Arrays;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;

public class HighlighEditor extends JFrame {

    private class MeuStyledDocument extends DefaultStyledDocument {

        private final AttributeSet palavraReservada;
        private final AttributeSet palavraNormal;

        public MeuStyledDocument() {
            final StyleContext context = StyleContext.getDefaultStyleContext();
            palavraReservada = context.addAttribute(context.getEmptySet(), StyleConstants.Foreground, Color.BLUE);
            palavraNormal = context.addAttribute(context.getEmptySet(), StyleConstants.Foreground, Color.BLACK);
        }

        @Override
        public void insertString(int offset, String str, AttributeSet a) throws BadLocationException {
            super.insertString(offset, str, a);
            highlight();
        }

        @Override
        public void remove(int offs, int len) throws BadLocationException {
            super.remove(offs, len);
            highlight();
        }

        private void highlight() throws BadLocationException {
            String text = getText(0, getLength());
            String[] palavras = text.split("\\W");
            int inicio = 0;
            int fim = 0;
            for (String palavra : palavras) {
                inicio = text.indexOf(palavra, inicio);
                fim = inicio + palavra.length();
                AttributeSet estilo = RESERVADAS.contains(palavra) ? palavraReservada : palavraNormal;
                setCharacterAttributes(inicio, fim, estilo, false);
                inicio = fim + 1;
            }
        }
    }

    private static final List<String> RESERVADAS = Arrays.asList(
            new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false",
                    "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected",
                    "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" });

    public static void main(String args[]) {
        try {
            HighlighEditor editor = new HighlighEditor();
            editor.setVisible(true);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public HighlighEditor() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(400, 400);
        setLocationRelativeTo(null);
        MeuStyledDocument document = new MeuStyledDocument();
        JTextPane textPane = new JTextPane(document);
        add(new JScrollPane(textPane));
    }
}

O bom de desenvolver isso e’ que agente aprende muita coisa interessante. E’ bom mesmo por as mãos na massa e logo surgirão novos desafios e necessidades. E não ficar dependente de APIS de terceiros pode ser interesssante em termos de qualidade e personificação.

@wldomiciano eu vi antes de criar a thread aqui esse RSyntaxTextArea, mas eu acho que eu vi alguma coisa no github que pra adicionar novas linguagens precisa de uma biblioteca que tem suas próprias linguagens pré-definidas ou alguma coisa assim. E vai ser uma IDE mesmo, ela vai editar, compilar, executar e também fazer o debug, e vai ter algumas outras funcionalidades extras também.

@staroski acho que eu não tinha pensado em criar uma classe filha de StyledDocument, eu vou tentar isso.

1 curtida