How to check if inside comment?


#1

I want to check if the cursor is inside a comment. So instead of doing it myself using complex regular expression or parsing I thought let’s use the built-in syntax highlighting but when using:
editor.getTokenTypeAt(editor.getCursor())==="comment"

in the red area’s it gives null or undefined. For all other cursor positions inside the block comment it returns “comment”.

Also using getTokenAt doesn’t work. See my (by myself unfairly?) closed issue https://github.com/codemirror/CodeMirror/issues/4755
What am I doing wrong? Is there some other easy way to check if inside comment?


#2

That’s probably a bug in the SQL mode, which first skips whitespace and only then checks whether it is inside a multiline comment.

It gets you the token before or around the given position. If you pass it a position at the start of the line, there is no token there. The same goes for empty lines – CodeMirror defines tokens as spanning a given range of text. Where there is no text, there is no token.


#3

Is it usefull that I reopen above ticket or make a new one or is this post for you enough info to (fingers cross) fix this small(?) bug. The code in mode/sql.js scares the shit out of me :slight_smile:


#4

See this patch.


#5

Better, top red area works now BUT if the line is empty like in the second red area still undefined is returned by GetTokenAt or GetTokenTypeAt which sounds logical since there is no token.

So question remains: Is there another way to check if my cursor is in a multiline comment like below where line 2 is empty:


#6

Made a funky workaround/hack function to check if inside blockcomment when cursor is at empty line:

//is line inside a blockcomment?
function insideBlockComment(line){
  line--;
  while (line>=0) {
    var tokens=editor.getLineTokens(line,true);
    if (tokens.length>0) { //no empty line?
      //check each token on the line, is it a BLOCK(!)comment?
      for (var i=tokens.length-1;i>=0;i--) {
        if (tokens[i].type=="comment") {
          if (tokens[i].string.substr(0,2)=="/*") return true;
          //continue
        }
        else return false;
      }
    }
    line--;
  }
  return false;
}

#7

Even if there is no token, there is tokenizer state, which we can use to ask “what token would we get if there was some text here?”. The following works for me:

cursor = editor.getCursor();
type = editor.getTokenTypeAt(cursor);
if(type === undefined) {
  state = editor.getTokenAt(cursor).state;
  type = editor.getMode().token(new CodeMirror.StringStream("x"), state);
}

@marijn token() mutates the state — is that OK on state recieved via getTokenAt / getStateAfter, or should it be copied first?

[EDITED: corrected state.tokenize(), which is internal function in SQL mode, to editor.getMode().token() which should work with any mode.]


The way I view it, the special status of empty lines is an artifact of the fact CodeMirror tokenizes for styling, and there is nothing to style (not quite true now that modes can return line-foo to add line classes; btw, can blankLine() do this?).
But to the API user, they’re a corner case requiring extra code :frowning:
Do you have any plans how to make the API more regular in this respect? Perhaps a way to pretend empty lines contain an "" or "\n" token?