Skip to content

Commit

Permalink
Added table commands
Browse files Browse the repository at this point in the history
Moved icons and gifs into common folder
Restructured code
  • Loading branch information
mdickin committed Nov 8, 2016
1 parent d5980c2 commit 10680c4
Show file tree
Hide file tree
Showing 27 changed files with 223 additions and 102 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
Handy shortcuts for editing Markdown (`.md`, `.markdown`) files. Now with title and context menu integration!

**Quickly toggle bullet points**
![](https://raw.githubusercontent.com/mdickin/vscode-markdown-shortcuts/master/gifs/bullets.gif)
![](https://raw.githubusercontent.com/mdickin/vscode-markdown-shortcuts/master/media/demo/bullets.gif)

**Easily generate URLs**
![](https://raw.githubusercontent.com/mdickin/vscode-markdown-shortcuts/master/gifs/urls.gif)
![](https://raw.githubusercontent.com/mdickin/vscode-markdown-shortcuts/master/media/demo/urls.gif)

**Convert tabular data to tables**
![](https://raw.githubusercontent.com/mdickin/vscode-markdown-shortcuts/master/media/demo/table_with_header.gif)


**Context and title menu integration**
![](https://raw.githubusercontent.com/mdickin/vscode-markdown-shortcuts/master/media/demo/shortcut_menu.png)

**Note**: extension will override a few default VS Code key bindings (ctrl+B, ctrl+I, ctrl+L), but only when editing Markdown files.

Expand All @@ -28,12 +35,14 @@ Handy shortcuts for editing Markdown (`.md`, `.markdown`) files. Now with title
| md-shortcut.toggleTitleH4 | Toggle #### H4 title | |
| md-shortcut.toggleTitleH5 | Toggle ##### H5 title | |
| md-shortcut.toggleTitleH6 | Toggle ###### H6 title | |
| md-shortcut.addTable | Add Tabular values | |
| md-shortcut.addTableWithHeader | Add Tabular values with header | |

## Changelog

**v0.4.0**
* Added title and context menu shortcuts. Menu icons taken from material.io/icons
* Added checkbox command. Thanks to [@wenbaofu](https://github.com/wenbaofu) for the recommendation!
* Added title and context menu shortcuts. Menu icons taken from http://material.io/icons
* Added checkbox and table commands. Thanks to [@wenbaofu](https://github.com/wenbaofu) for the recommendations!

**v0.3.0**
* Added header shortcuts. Thanks to [@alebaffa](https://github.com/alebaffa) for the contribution!
2 changes: 1 addition & 1 deletion extension.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var commands = require('./commands');
var commands = require('./lib/commands');

function activate(context) {

Expand Down
116 changes: 34 additions & 82 deletions commands.js → lib/commands.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
var vscode = require("vscode")
var editorHelpers = require("./editorHelpers");
var tables = require("./tables");

module.exports = {
register: register
}
Expand All @@ -18,7 +21,9 @@ var _commands = [
new Command('toggleTitleH4', toggleTitleH4, 'Toggle title H4', '#### Title', true),
new Command('toggleTitleH5', toggleTitleH5, 'Toggle title H5', '##### Title', true),
new Command('toggleTitleH6', toggleTitleH6, 'Toggle title H6', '###### Title', true),
new Command('toggleCheckboxes', toggleCheckboxes, 'Toggle checkboxes', '- [x] Checkbox item', true)
new Command('toggleCheckboxes', toggleCheckboxes, 'Toggle checkboxes', '- [x] Checkbox item', true),
new Command('addTable', tables.addTable, 'Add table', 'Tabular | values', true),
new Command('addTableWithHeader', tables.addTableWithHeader, 'Add table (with header)', 'Tabular | values', true)
]

function register(context) {
Expand All @@ -40,77 +45,77 @@ function showCommandPalette() {
}

function toggleBold() {
surroundSelection('**')
editorHelpers.surroundSelection('**')
}

function toggleItalic() {
surroundSelection('_')
editorHelpers.surroundSelection('_')
}

function toggleCodeBlock() {
surroundSelection('```\n', '\n```')
editorHelpers.surroundSelection('```\n', '\n```')
}

function toggleInlineCode() {
surroundSelection('`')
editorHelpers.surroundSelection('`')
}

function toggleTitleH1() {
surroundSelection('# ','')
editorHelpers.surroundSelection('# ','')
}

function toggleTitleH2() {
surroundSelection('## ','')
editorHelpers.surroundSelection('## ','')
}

function toggleTitleH3() {
surroundSelection('### ','')
editorHelpers.surroundSelection('### ','')
}

function toggleTitleH4() {
surroundSelection('#### ','')
editorHelpers.surroundSelection('#### ','')
}

function toggleTitleH5() {
surroundSelection('##### ','')
editorHelpers.surroundSelection('##### ','')
}

function toggleTitleH6() {
surroundSelection('###### ','')
editorHelpers.surroundSelection('###### ','')
}

var HasBullets = /^(\s*)\* (.*)$/gm
var AddBullets = /^(\s*)(.+)$/gm
function toggleBullets() {

if (!isAnythingSelected()) {
surroundSelection("* ", "")
if (!editorHelpers.isAnythingSelected()) {
editorHelpers.surroundSelection("* ", "")
return;
}

if (isMatch(HasBullets)) {
replaceSelection((text) => text.replace(HasBullets, "$1$2"))
if (editorHelpers.isMatch(HasBullets)) {
editorHelpers.replaceSelection((text) => text.replace(HasBullets, "$1$2"))
}
else {
replaceSelection((text) => text.replace(AddBullets, "$1* $2"))
editorHelpers.replaceSelection((text) => text.replace(AddBullets, "$1* $2"))
}
}

var HasNumbers = /^(\s*)[0-9]\.+ (.*)$/gm
var AddNumbers = /^(\s*)(.+)$/gm
function toggleNumberList() {

if (!isAnythingSelected()) {
surroundSelection("1. ", "")
if (!editorHelpers.isAnythingSelected()) {
editorHelpers.surroundSelection("1. ", "")
return;
}

if (isMatch(HasNumbers)) {
replaceSelection((text) => text.replace(HasNumbers, "$1$2"))
if (editorHelpers.isMatch(HasNumbers)) {
editorHelpers.replaceSelection((text) => text.replace(HasNumbers, "$1$2"))
}
else {
var lineNums = {};
replaceSelection((text) => text.replace(AddNumbers, (match, whitespace, line) => {
editorHelpers.replaceSelection((text) => text.replace(AddNumbers, (match, whitespace, line) => {
if (!lineNums[whitespace]) {
lineNums[whitespace] = 1
}
Expand All @@ -123,23 +128,23 @@ var HasCheckboxes = /^(\s*)- \[[ x]{1}\] (.*)$/gm
var AddCheckboxes = /^(\s*)(.+)$/gm
function toggleCheckboxes() {

if (!isAnythingSelected()) {
surroundSelection("- [ ]", "")
if (!editorHelpers.isAnythingSelected()) {
editorHelpers.surroundSelection("- [ ]", "")
return;
}

if (isMatch(HasCheckboxes)) {
replaceSelection((text) => text.replace(HasCheckboxes, "$1$2"))
if (editorHelpers.isMatch(HasCheckboxes)) {
editorHelpers.replaceSelection((text) => text.replace(HasCheckboxes, "$1$2"))
}
else {
replaceSelection((text) => text.replace(AddCheckboxes, "$1- [ ] $2"))
editorHelpers.replaceSelection((text) => text.replace(AddCheckboxes, "$1- [ ] $2"))
}
}

function toggleLink() {

if (isMatch(/^\[.+\]\(.+\)$/i)) {
replaceSelection((text) => text.match(/\[(.+)\]/)[1])
if (editorHelpers.isMatch(/^\[.+\]\(.+\)$/i)) {
editorHelpers.replaceSelection((text) => text.match(/\[(.+)\]/)[1])
return;
}
else {
Expand Down Expand Up @@ -175,63 +180,10 @@ function toggleLink() {
function addTags(options) {
if (!options || !options.url) return;

surroundSelection("[" + options.text, "](" + options.url + ")")
}
}

function surroundSelection(startPattern, endPattern)
{
if (endPattern == undefined || endPattern == null) endPattern = startPattern;

var editor = vscode.window.activeTextEditor;
var selection = editor.selection;

if (!isAnythingSelected()) {
var position = selection.active;
var newPosition = position.with(position.line, position.character + startPattern.length)
editor.edit((edit) => {
edit.insert(selection.start, startPattern + endPattern);
}).then(() => {
editor.selection = new vscode.Selection(newPosition, newPosition)
})
}
else {
if (isMatch(startPattern, endPattern)) {
replaceSelection((text) => text.substr(startPattern.length, text.length - startPattern.length - endPattern.length))
}
else {
replaceSelection((text) => startPattern + text + endPattern)
}
editorHelpers.surroundSelection("[" + options.text, "](" + options.url + ")")
}
}

function isAnythingSelected() {
return !vscode.window.activeTextEditor.selection.isEmpty;
}

function isMatch(startPattern, endPattern) {

var editor = vscode.window.activeTextEditor;
var selection = editor.selection;

var text = editor.document.getText(selection)
if (startPattern.constructor === RegExp) {
return startPattern.test(text);
}

return text.startsWith(startPattern) && text.endsWith(endPattern)
}

function replaceSelection(replaceFunc) {
var editor = vscode.window.activeTextEditor;
var selection = editor.selection;

var newText = replaceFunc(editor.document.getText(selection));
editor.edit((edit) => {
edit.replace(selection, newText)
})
}

function Command(command, callback, label, description, showInCommandPalette) {
this.command = command;
this.callback = callback;
Expand Down
61 changes: 61 additions & 0 deletions lib/editorHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
var vscode = require("vscode");

module.exports = {
isAnythingSelected: isAnythingSelected,
replaceSelection: replaceSelection,
surroundSelection: surroundSelection,
isMatch: isMatch
}

function replaceSelection(replaceFunc) {
var editor = vscode.window.activeTextEditor;
var selection = editor.selection;

var newText = replaceFunc(editor.document.getText(selection));
return editor.edit((edit) => {
edit.replace(selection, newText)
})
}

function isAnythingSelected() {
return !vscode.window.activeTextEditor.selection.isEmpty;
}

function surroundSelection(startPattern, endPattern)
{
if (endPattern == undefined || endPattern == null) endPattern = startPattern;

var editor = vscode.window.activeTextEditor;
var selection = editor.selection;

if (!isAnythingSelected()) {
var position = selection.active;
var newPosition = position.with(position.line, position.character + startPattern.length)
editor.edit((edit) => {
edit.insert(selection.start, startPattern + endPattern);
}).then(() => {
editor.selection = new vscode.Selection(newPosition, newPosition)
})
}
else {
if (isMatch(startPattern, endPattern)) {
replaceSelection((text) => text.substr(startPattern.length, text.length - startPattern.length - endPattern.length))
}
else {
replaceSelection((text) => startPattern + text + endPattern)
}
}
}

function isMatch(startPattern, endPattern) {

var editor = vscode.window.activeTextEditor;
var selection = editor.selection;

var text = editor.document.getText(selection)
if (startPattern.constructor === RegExp) {
return startPattern.test(text);
}

return text.startsWith(startPattern) && text.endsWith(endPattern)
}
58 changes: 58 additions & 0 deletions lib/tables.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
var vscode = require("vscode");
var editorHelpers = require("./editorHelpers");

module.exports = {
addTable: () => addTable(false),
addTableWithHeader: () => addTable(true)
};

var sampleTable = [
"",
"Column A | Column B | Column C",
"---------|----------|---------",
" A1 | B1 | C1",
" A2 | B2 | C2",
" A3 | B3 | C3"
].join("\r\n");

function addTable(addHeader) {
//var editor = vscode.window.activeTextEditor;

var editFunc;
if (!editorHelpers.isAnythingSelected()) {
editFunc = () => sampleTable;
}
else if (addHeader) {
editFunc = convertToTableWithHeader;
}
else {
editFunc = convertToTableWithoutHeader;
}
editorHelpers.replaceSelection(editFunc);
}

var tableColumnSeparator = /([ ]{2,}|[\t])/gi;
function convertToTableWithoutHeader(text) {
var firstRow = text.match(/.+/);

var columnSeparators = firstRow == null ? null : firstRow[0].match(tableColumnSeparator);
var columnCount = columnSeparators == null ? 0 : columnSeparators.length;
var line1 = [];
for (var i = 0; i < columnCount + 1; i++) {
line1.push("column" + i);
}
var tableHeader = line1.join(" | ") + "\r\n";
tableHeader = tableHeader + tableHeader.replace(/[a-z0-9]/gi, "-");

return tableHeader + text.replace(tableColumnSeparator, " | ");
}

function convertToTableWithHeader(text) {
var textAsTable = text.replace(tableColumnSeparator, " | ");

var firstRow = textAsTable.match(/.+/)[0];

var headerLine = firstRow.replace(/[^\|]/gi, "-");

return firstRow + "\r\n" + headerLine + textAsTable.substring(firstRow.length);
}
Binary file added media/demo/bullets.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/demo/shortcut_menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/demo/table_with_header.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/demo/urls.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
4 changes: 4 additions & 0 deletions media/icons/grid_black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions media/icons/grid_white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Loading

0 comments on commit 10680c4

Please sign in to comment.