0

I use Visual Studio Code to edit Markdown and Latex files. I added the following entries to my keybindings.json file to make the selected text either italic or bold:

    // Markdown Bold Text when Editor has Selection
    {
        "key": "cmd+b",
        "command": "editor.action.insertSnippet",
        "when": "editorHasSelection && editorLangId != 'latex'",
        "args": {
            "snippet": "**${TM_SELECTED_TEXT}**"
        }
    },
    // Latex Bold Text when Editor has Selection
    {
        "key": "cmd+b",
        "command": "editor.action.insertSnippet",
        "when": "editorHasSelection && editorLangId == 'latex'",
        "args": {
            "snippet": "\\textbf{${TM_SELECTED_TEXT}}"
        }
    },
    // Markdown Italic Text when Editor has Selection
    {
        "key": "cmd+i",
        "command": "editor.action.insertSnippet",
        "when": "editorHasSelection && editorLangId != 'latex'",
        "args": {
            "snippet": "*${TM_SELECTED_TEXT}*"
        }
    },
    // Latex Italic Text when Editor has Selection
    {
        "key": "cmd+i",
        "command": "editor.action.insertSnippet",
        "when": "editorHasSelection && editorLangId == 'latex'",
        "args": {
            "snippet": "\\emph{${TM_SELECTED_TEXT}}"
        }
    }

Now my question is if it is possible to create a snippet and assign a keybinding to it that reverts these operations, i.e. transform selected italic or bold text to normal text.

I have looked into incorporating regular expressions into VSCode snippets that strip off the stars in case of Markdown or keep everything inside the curly braces in case of Latex, but could not find any approaches that are transferable to the use case above.


Edit:

The solution provided by @rioV8 is even better than what I hoped for. Instead of selecting the italic/bold text first, you can simply position the cursor somewhere inside the markup text and press the keybinding to transform it back to normal text.

The corresponding entries in keybindings.json now look like this:

{
    // Revert Markdown Bold Text
    {
        "key": "cmd+shift+b",
        "command": "extension.multiCommand.execute",
        "when": "editorLangId != 'latex'",
        "args": {
            "sequence": [
                {
                    "command": "selectby.regex",
                    "args": {
                        "surround": "\\*\\*.*?\\*\\*"
                    }
                },
                {
                    "command": "editor.action.insertSnippet",
                    "args": {
                        "snippet": "${TM_SELECTED_TEXT/\\*\\*(.*?)\\*\\*/$1/}"
                    }
                }
            ]
        }
    },
    // Revert Latex Bold Text
    {
        "key": "cmd+shift+b",
        "command": "extension.multiCommand.execute",
        "when": "editorLangId == 'latex'",
        "args": {
            "sequence": [
                {
                    "command": "selectby.regex",
                    "args": {
                        "surround": "\\\\textbf{.*?}"
                    }
                },
                {
                    "command": "editor.action.insertSnippet",
                    "args": {
                        "snippet": "${TM_SELECTED_TEXT/\\\\textbf{(.*?)}/$1/}"
                    }
                }
            ]
        }
    },
    // Revert Markdown Italic Text
    {
        "key": "cmd+shift+i",
        "command": "extension.multiCommand.execute",
        "when": "editorLangId != 'latex'",
        "args": {
            "sequence": [
                {
                    "command": "selectby.regex",
                    "args": {
                        "surround": "\\*.*?\\*"
                    }
                },
                {
                    "command": "editor.action.insertSnippet",
                    "args": {
                        "snippet": "${TM_SELECTED_TEXT/\\*(.*?)\\*/$1/}"
                    }
                }
            ]
        }
    },
    // Revert Latex Italic Text
    {
        "key": "cmd+shift+i",
        "command": "extension.multiCommand.execute",
        "when": "editorLangId == 'latex'",
        "args": {
            "sequence": [
                {
                    "command": "selectby.regex",
                    "args": {
                        "surround": "\\\\emph{.*?}"
                    }
                },
                {
                    "command": "editor.action.insertSnippet",
                    "args": {
                        "snippet": "${TM_SELECTED_TEXT/\\\\emph{(.*?)}/$1/}"
                    }
                }
            ]
        }
    }
}
Joel Beck
  • 318
  • 2
  • 6

3 Answers3

1

with the extension Select By and the command selectby.regex there is the option to create a selection around the cursor given a regular expression.

And with the extension multi-command you can combine this with a snippet that transforms the selected text.

For Markdown Bold it would be something like

{
    "key": "cmd+shift+b",
    "command": "extension.multiCommand.execute",
    "when": "editorHasSelection && editorLangId != 'latex'",
    "args": { 
        "sequence": [
            { "command": "selectby.regex",
              "args": { "surround": "\\*\\*.*?\\*\\*" } },
            { "command": "editor.action.insertSnippet",
              "args": { "snippet": "${TM_SELECTED_TEXT/\\*\\*(.*?)\\*\\*/$1/}" } }
        ]
    }
}
rioV8
  • 24,506
  • 3
  • 32
  • 49
0

I spent too long figuring this out for LaTeX. For those who want the keybindings for keybindings.json, here is what I ended with:

{
    "key": "ctrl+B",
    "command": "extension.multiCommand.execute",
    "when": "editorTextFocus && editorLangId == 'latex'",
    "args": {
      "sequence": [
        {
          "command": "selectby.regex",
          "args": { "surround": "[a-zA-Z0-9]+" }
        },
        {
          "command": "editor.action.insertSnippet",
          "args": { "snippet": "\\textbf{${TM_SELECTED_TEXT}$0}" }
        }
      ]
    }
  },
  {
    "key": "ctrl+shift+B",
    "command": "extension.multiCommand.execute",
    "when": "editorTextFocus && editorLangId == 'latex'",
    "args": {
      "sequence": [
        {
          "command": "selectby.regex",
          "args": { "surround": "[^ \na-zA-Z0-9]textbf{.*?}" }
        },
        {
          "command": "editor.action.insertSnippet",
          "args": {
            "snippet": "$0${TM_SELECTED_TEXT/[^ \na-zA-Z0-9]textbf{(.*?)}/$1/}"
          }
        }
      ]
    }
  },


  {
    "key": "ctrl+I",
    "command": "extension.multiCommand.execute",
    "when": "editorTextFocus && editorLangId == 'latex'",
    "args": {
      "sequence": [
        {
          "command": "selectby.regex",
          "args": { "surround": "[a-zA-Z0-9]+" }
        },
        {
          "command": "editor.action.insertSnippet",
          "args": { "snippet": "\\textit{${TM_SELECTED_TEXT}$0}" }
        }
      ]
    }
  },
  {
    "key": "ctrl+shift+I",
    "command": "extension.multiCommand.execute",
    "when": "editorTextFocus && editorLangId == 'latex'",
    "args": {
      "sequence": [
        {
          "command": "selectby.regex",
          "args": { "surround": "[^ \na-zA-Z0-9]textit{.*?}" }
        },
        {
          "command": "editor.action.insertSnippet",
          "args": {
            "snippet": "$0${TM_SELECTED_TEXT/[^ \na-zA-Z0-9]textit{(.*?)}/$1/}"
          }
        }
      ]
    }
  },


  {
    "key": "ctrl+U",
    "command": "extension.multiCommand.execute",
    "when": "editorTextFocus && editorLangId == 'latex'",
    "args": {
      "sequence": [
        {
          "command": "selectby.regex",
          "args": { "surround": "[a-zA-Z0-9]+" }
        },
        {
          "command": "editor.action.insertSnippet",
          "args": { "snippet": "\\underline{${TM_SELECTED_TEXT}$0}" }
        }
      ]
    }
  },
  {
    "key": "ctrl+Y",
    "command": "extension.multiCommand.execute",
    "when": "editorTextFocus && editorLangId == 'latex'",
    "args": {
      "sequence": [
        {
          "command": "selectby.regex",
          "args": { "surround": "[^ \na-zA-Z0-9]underline{.*?}" }
        },
        {
          "command": "editor.action.insertSnippet",
          "args": {
            "snippet": "$0${TM_SELECTED_TEXT/[^ \na-zA-Z0-9]underline{(.*?)}/$1/}"
          }
        }
      ]
    }
  },

Note1: This relies on the "Select By" and "multi-command" extensions, cited by @rioV8

Note2: ctrl+shift+_ is "undo _". Also, undo underline is "ctrl+y" because "ctrl+shift+U" would not work on my machine. If anyone has insight as to how I could change this, please let me know.

mojo37
  • 1
0

Here is a pretty simple solution - one keybinding, one extension. You do not need to select anything.

Using an extension I wrote, Find and Transform, make this keybinding (in your keybindings.json):

{
  "key": "alt+r",                    // whatever keybinding you want
  "command": "findInCurrentFile",
  "args": {
    
    "find": "(\\*\\*|\\\\textbf{|\\*|\\\\emph{)(.+?)([*}]+)",
    "replace": "$2",                // replace find match with capture group 2
    "isRegex": true,
    "restrictFind": "nextSelect"    // replace next occurrence and select the result 

    // demo below uses "nextSelect" just to make it easy to see
  }
}

Other options:

    "restrictFind": "once"        // replace next occurrence in that line 
    "restrictFind": "next"        // replace next occurrence anywhere in the document
    "restrictFind": "line"        // replace All occurrences on the current line
    "restrictFind": "document"    // replace all occurrences in the entire document
    // and more, see the README on "restrictFind"

latex and markdown revert styling


If you wanted to make individual keybindings for each case, the regex's would be very simple.

Mark
  • 143,421
  • 24
  • 428
  • 436