package flow.netbeans.markdown.typinghooks; import flow.netbeans.markdown.csl.MarkdownLanguageConfig; import flow.netbeans.markdown.highlighter.MarkdownTokenId; import flow.netbeans.markdown.options.MarkdownGlobalOptions; import flow.netbeans.markdown.utils.MarkdownDocUtil; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import org.netbeans.api.editor.mimelookup.MimePath; import org.netbeans.api.editor.mimelookup.MimeRegistration; import org.netbeans.api.lexer.Token; import org.netbeans.api.lexer.TokenSequence; import org.netbeans.spi.editor.typinghooks.DeletedTextInterceptor; /** * * @author junichi11 */ public class MarkdownDeletedTextInterceptor implements DeletedTextInterceptor { @Override public boolean beforeRemove(Context context) throws BadLocationException { if (!isEnabled()) { return false; } char ch = context.getText().charAt(0); if (ch != '.' && ch != ' ') { // NOI18N return false; } Document document = context.getDocument(); int caretOffset = context.getOffset(); TokenSequence<MarkdownTokenId> ts = MarkdownDocUtil.getTokenSequence(document); ts.move(caretOffset); if (ch == ' ') { // NOI18N ts.movePrevious(); Token<MarkdownTokenId> token = ts.token(); if (caretOffset != ts.offset() + token.length()) { return false; } } else { ts.moveNext(); } Token<MarkdownTokenId> token = ts.token(); if (token == null || token.id() != MarkdownTokenId.ORDEREDLIST) { return false; } String tokenText = token.text().toString(); // may text is ' ' if (tokenText.matches("\\d+\\.")) { // NOI18N return false; } // compute offset and length for removing int removeStartOffset = ts.offset(); int removeLength = tokenText.length(); if (ts.movePrevious()) { Token<MarkdownTokenId> previousToken = ts.token(); if (previousToken != null) { String previousText = previousToken.text().toString(); int lastIndexOfNewLine = previousText.lastIndexOf('\n'); // NOI18N if (lastIndexOfNewLine != -1) { removeStartOffset = ts.offset() + lastIndexOfNewLine; int indent = previousToken.length() - lastIndexOfNewLine; removeLength = removeLength + indent; } } } // reorder OrderedListReorderer reorderer = new OrderedListReorderer(context.getComponent(), document, caretOffset); reorderer.reorder(false, removeStartOffset, removeLength); return true; } @Override public void remove(Context context) throws BadLocationException { } @Override public void afterRemove(Context context) throws BadLocationException { } @Override public void cancelled(Context context) { } private boolean isEnabled() { return MarkdownGlobalOptions.getInstance().isTypingHooks(); } @MimeRegistration(mimeType = MarkdownLanguageConfig.MIME_TYPE, service = DeletedTextInterceptor.Factory.class) public static class Factory implements DeletedTextInterceptor.Factory { @Override public DeletedTextInterceptor createDeletedTextInterceptor(MimePath mimePath) { return new MarkdownDeletedTextInterceptor(); } } }