Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature request]: Support for function extension snippets #16

Closed
windily-cloud opened this issue May 13, 2022 · 11 comments · Fixed by #241
Closed

[feature request]: Support for function extension snippets #16

windily-cloud opened this issue May 13, 2022 · 11 comments · Fixed by #241
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@windily-cloud
Copy link

This plugin works well enough and very elegantly allows me to edit latex formulas.

If it could support function fragments, it would be perfect! My thoughts are as follows.

mxi(3) outputs a 3x3 unit matrix and mxi(6) outputs a 6x6 unit matrix.I can also customize h(3) to output three-level headings.

Also, it would be easier to debug and backup if the configuration file could be separated into an md file.

Thanks for any replies, I really love this plugin!

@artisticat1
Copy link
Owner

mxi(3) outputs a 3x3 unit matrix and mxi(6) outputs a 6x6 unit matrix.I can also customize h(3) to output three-level headings.

I'll need to put some thought into how to achieve this. I guess the goal is to allow executing code within a snippet, right?

Also, it would be easier to debug and backup if the configuration file could be separated into an md file.

Good idea! I could add a button to export the user's snippets to a .txt or .md file, and a button to load snippets from a .txt / .md file. Would that work for you?

Your plugin settings (including snippets) should be backed up by git / any sync service you're using, btw.

Thanks for any replies, I really love this plugin!

Glad you enjoy it!

@windily-cloud
Copy link
Author

I'll need to put some thought into how to achieve this. I guess the goal is to allow executing code within a snippet, right?
I'm not quite sure there's a better way to implement this feature. My idea is to type the function name and parameters, then output the snippet returned by the function.

I've seen people implement it like this(I forget exactly where it came from, I retrieved it from last year's photo gallery😂):

{9CF982E7-D6C5-FCEF-058A-18C449468135}

I guess his idea is to use regular expressions to extract the function name and parameters, and then output the snippets returned by the function if it matches the preconfigured function.This avoids the case of entering more parentheses, and I don't know if there are any side effects.

image

Of course, this is just an idea, we can have a more elegant approach. This method of his has to manually modify the code optimization himself when dealing with multiple parameters or when the parameters are arrays.

Anyway, I'm convinced you can handle this gracefully because you made this plugin to make me feel graceful, haha😆!If I can be of any help, just ask, I'm happy to do so. For example, manually testing the functionality and stability of new features.

Thanks again!

@artisticat1
Copy link
Owner

Anyway, I'm convinced you can handle this gracefully because you made this plugin to make me feel graceful, haha😆!If I can be of any help, just ask, I'm happy to do so. For example, manually testing the functionality and stability of new features.

Haha, thank you! I'd be happy to have help with testing. I'll let you know when I have things ready.

So, I've come up with an idea for how to achieve this. To achieve your example with "a33pmx" above, here's what it would look like.

We can use the regular expression

([A-Za-z])([0-9])([0-9])pmx

to match the string "a33pmx". This regex captures the groups "a", "3", and "3". I assume these are the symbol of the matrix, the number of rows, and the number of columns.

Then we can write a function in javascript that takes the inputs "a", "3", and "3" as parameters and generates the corresponding matrix output in LaTeX. The plugin will pass in the capture groups to the function as an array.

function genMatrix(captureGroups) {
  const [symbol, rows, columns] = captureGroups;

  let arr = [];
  for(let j = 0; j < rows; j++) {
      arr[j] = [];

      for(let i = 0; i < columns; i++) {
          arr[j][i] = `${symbol}_{${j+1}${i+1}}`;
      }
  }

  let output = arr.map(el => el.join(" & ")).join(" \\\\\n");
  output = `\\begin{pmatrix}\n${output}\n\\end{pmatrix}`;

  return output;
}

image

Finally, we put all this together in a snippet that we can run by typing "a33pmxTab".

{trigger: "([A-Za-z])([0-9])([0-9])pmx", replacement: `

function genMatrix(captureGroups) {
  const [symbol, rows, columns] = captureGroups;

  let arr = [];
  for(let j = 0; j < rows; j++) {
      arr[j] = [];

      for(let i = 0; i < columns; i++) {
          arr[j][i] = \`\${symbol}_{\${j+1}\${i+1}}\`;
      }
  }

  let output = arr.map(el => el.join(" & ")).join(" \\\\\n");
  output = \`\\begin{pmatrix}\n\${output}\n\\end{pmatrix}\`;

  return output;
}

`, options: "rmx"}

Similarly, we can create a snippet for unit matrices, as you suggested in your first post.

image

{trigger: "mxi([0-9])", replacement: `

function genMatrix(captureGroups) {
  const [N] = captureGroups;

  let arr = [];
  for(let j = 0; j < N; j++) {
      arr[j] = [];

      for(let i = 0; i < N; i++) {
          arr[j][i] = (i === j) ? 1 : 0;
      }
  }

  let output = arr.map(el => el.join(" & ")).join(" \\\\\n");
  output = \`\\begin{pmatrix}\n\${output}\n\\end{pmatrix}\`;

  return output;
}

`, options: "rmx"}

Here typing "mxi6Tab" will create a 6x6 unit matrix.

How does this sound?

@windily-cloud
Copy link
Author

Wow, that's great, I was confused about function names and passing parameters, and you've solved it elegantly. This allows me to customize the trigger keyword without worrying about the function name on the one hand, and to pass precise parameters on the other.

Excited, excited, or excited!I can't wait to try this feature, provided you don't work too hard.

@artisticat1
Copy link
Owner

Great! ❤️ I am currently busy, so I'm not sure exactly when I can start working on it, but hopefully within the next few weeks or so.

@TimothyBesada
Copy link

I just wanted to check if you're still thinking of implementing this? I think your idea of being able to run some code in the replacement options is a really good way of doing this.

@artisticat1
Copy link
Owner

It's in the backlog at the moment, but any PRs to implement this would be welcome.

@yfzhao20
Copy link

Looking foward to this function!

Previously I found a similar extension in VS Code: draivin.hsnips. global function was implemented in this extension and may provide some inspiration.

global
// JavaScript code
endglobal

@mayurankv
Copy link

If I understand correctly, the x option would indicate a function being evaluated. So what would need to be done in a PR would be identifying if the x option is present, and if so running the javascript function and returning the output? Am I correct in thinking that except for adding the x option as a possibility to settings etc., all the changes would occur in run_snippet.ts? Sorry, I'm not very familiar making PRs but happy to give it a go!

@artisticat1
Copy link
Owner

If I understand correctly, the x option would indicate a function being evaluated. So what would need to be done in a PR would be identifying if the x option is present, and if so running the javascript function and returning the output? Am I correct in thinking that except for adding the x option as a possibility to settings etc., all the changes would occur in run_snippet.ts? Sorry, I'm not very familiar making PRs but happy to give it a go!

Yes, exactly. However, I now realise a cleaner solution than adding an x option may be to simply allow the replacement of a snippet to be a string or a function. Then snippets could look something like

{trigger: "mxi([0-9])", replacement: (result: RegExpMatchArray) => {
  const N = result[1];

  const arr = [];
  for(let j = 0; j < N; j++) {
      arr[j] = [];

      for(let i = 0; i < N; i++) {
          arr[j][i] = (i === j) ? 1 : 0;
      }
  }

  const output = arr.map(el => el.join(" & ")).join(" \\\\\n");
  return `\\begin{pmatrix}\n\${output}\n\\end{pmatrix}`;

}, options: "rm"}

So you'd need to modify the definition of a Snippet to give the replacement the type string | ((result: RegExpMatchArray) => string), and modify run_snippets.ts as you mention.

However, snippets are currently parsed using json5, which does not allow parsing functions - so we would probably need to switch to using a javascript parser for parsing snippets as well.

Feel free to have a go if you are still interested!

@artisticat1
Copy link
Owner

Added in 1.9.0 (see the docs here).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants