draivin / hsnips

HyperSnips: a powerful snippet engine for VS Code, inspired by vim's UltiSnips
MIT License
154 stars 25 forks source link

a built-in variable representing first operand #149

Open anonymousALLDAY opened 1 year ago

anonymousALLDAY commented 1 year ago

erwerwq

global
   function deleteText(startline, startchar, endline, endchar) {
      let editor = vscode.window.activeTextEditor;
      let range = new vscode.Range(startline, startchar, endline, endchar);
      editor.edit(editBuilder => {
         editBuilder.delete(range);
      });
   }

   function keepText(line, char) {
      let doc = vscode.window.activeTextEditor.document;
      let pos = new vscode.Range(line, char-2, line, char-1);
      let text = doc.getText(pos);
      let more = 0;
      if (text!=')') {
         for (i=2; i<char; i++) {
            let pos = new vscode.Range(line, char-(i+1), line, char-(i+1)+1);
            let text = doc.getText(pos);
            if ( (text == ' ') || (i == (char-1)) ) {
               if (text == ' ') {
                  let range = new vscode.Range(line, char-(i+1)+1, line, char-1);
                  let text = doc.getText(range);
                  return [text, more];
               } else {
                  let range = new vscode.Range(line, 0, line, char-1);
                  let text = doc.getText(range);
                  return [text, more];
               }
            }
         }
      } else {
         let count = 0;
         for (i=1; i<char; i++) {
            let pos = new vscode.Range(line, char-(i+1), line, char-(i+1)+1);
            let text = vscode.window.activeTextEditor.document.getText(pos);
            if (text ==')') {
               count += 1;
            } else if( text =='(' ) {
               count -= 1;
            }
            if (count == 0) {
               more = 2;
               let range = new vscode.Range(line, char-(i+1)+1, line, char-2);
               let text = vscode.window.activeTextEditor.document.getText(range);
               return [text, more];
            }
         }
      }
   }

   function firstOperand(name) {
   let len = nameLength(name);
   let pos = vscode.window.activeTextEditor.selection.active;
   let text = keepText(pos.line, pos.character-(len-1));
   deleteText(pos.line, pos.character-(len-1)-(text[0].length+1+text[1]), pos.line, pos.character+1);
   return text[0];
   }

endglobal
snippet choose "binomial" A
``
let first = firstOperand('choose');
rv='{'+first;
`` \choose$1}
endsnippet

snippet over "fraction" A
``
let first = firstOperand('over');
rv='{'+first;
`` \over$1}
endsnippet

I've hardcoded it myself to get the first operands, where a in a operator b for example.

word seperator is whitespace or parenthesis.

I guess many people would want this feature because

  1. people prefer to say a over b rather than frac a b (though \frac has more variations like \dfrac, \tfrac)

  2. people prefer to say theta hat rather than hat theta

and there are many cases where we need to handle the first operand.

I'm not good at coding, have no background knowledge much over JS or vscode API, so there might be a more elegant way to implement this feature and I hope to see it!

p.s. code above doesn't work properly when there are trailing spaces after snippet trigger text. I can't fix it because the position of cursor is always fixed to the starting position of trigger text and the value of rv appears on there. the cursor position is changed only when there's no trailing space.