Skip to content

Commit

Permalink
F Added indent and outdent
Browse files Browse the repository at this point in the history
  • Loading branch information
cmstead committed Aug 18, 2021
1 parent 812690e commit e09be9f
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 19 deletions.
12 changes: 10 additions & 2 deletions extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ function activate(context) {
const formatDocument = () =>
vscode.commands.executeCommand("editor.action.formatDocument");

let disposable = vscode.commands.registerCommand('cmstead.snipkit.indent', function () {
let disposable1 = vscode.commands.registerCommand('cmstead.snipkit.indent', function () {
require('./modules/commands/indent/indent-action')
.indent()
.then(formatDocument);
});

context.subscriptions.push(disposable);
context.subscriptions.push(disposable1);

let disposable2 = vscode.commands.registerCommand('cmstead.snipkit.outdent', function () {
require('./modules/commands/outdent/outdent-action')
.outdent()
.then(formatDocument);
});

context.subscriptions.push(disposable2);
}

function deactivate() { }
Expand Down
22 changes: 15 additions & 7 deletions modules/action-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@ const { buildSelectionPath } = require('./selection-path');
const { parseSource } = require('./parser/parser');
const { transformSelectionToPosition } = require('./transforms/selection-to-position');

const vscode = require('./vscode-service').getVsCode();
const vscode = require('./vscode-service').getVscode();

function actionSetup() {

const activeTextEditor = vscode.window.activeTextEditor;
const location = transformSelectionToPosition(activeTextEditor.selection);
const source = activeTextEditor.document.getText();
const ast = parseSource(source);
const selectionPath = buildSelectionPath(ast.child, location);

return {
source,
ast,
selectionPath
try {
const ast = parseSource(source);
const selectionPath = buildSelectionPath(ast.child, location);

return {
activeTextEditor,
source,

location,
ast,
selectionPath
}
} catch (_) {
throw new Error('Unable to interpret JSON source; SnipKit cannot start')
}
}

Expand Down
38 changes: 35 additions & 3 deletions modules/commands/indent/indent-action.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
const { asyncActionSetup } = require("../../action-setup");
const { getNewSourceEdit } = require("../../edit-utils/SourceEdit");
const { transformLocationToRange } = require("../../edit-utils/textEditTransforms");
const { getSourceSelection } = require("../../source-utilities");
const { validateUserInput } = require("../../validatorService");

function indent() {
let actionSetup = null;
let sourceSelection = null;
let indentedSelection = null;
return asyncActionSetup()
.then(({selectionPath}) => {
console.log(selectionPath);
.then((newActionSetup) => {
actionSetup = newActionSetup;
})

.catch(function(error){
.then(() => getSourceSelection(actionSetup.source, actionSetup.location))
.then((sourceSelection) => validateUserInput({
value: sourceSelection,
validator: sourceSelection =>
sourceSelection
.split(/\r?\n/g)
.reduce((result, line) =>
result && /^\s*"?/.test(line)),
message: "Invalid body selection: not all lines begin with an open quote"
}))
.then((newSourceSelection) => sourceSelection = newSourceSelection)

.then(() => indentedSelection = sourceSelection
.split(/\r?\n/g)
.map((line) => line.replace(/^(\s*)"/, '$1\"\\t'))
.join('\n'))

.then(() => {
const replacementRange = transformLocationToRange(actionSetup.location);

return getNewSourceEdit()
.addReplacementEdit(replacementRange, indentedSelection)
.applyEdit()
})

.catch(function (error) {
console.log(error);
});
}
Expand Down
48 changes: 48 additions & 0 deletions modules/commands/outdent/outdent-action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const { asyncActionSetup } = require("../../action-setup");
const { getNewSourceEdit } = require("../../edit-utils/SourceEdit");
const { transformLocationToRange } = require("../../edit-utils/textEditTransforms");
const { getSourceSelection } = require("../../source-utilities");
const { validateUserInput } = require("../../validatorService");

function outdent() {
let actionSetup = null;
let sourceSelection = null;
let indentedSelection = null;
return asyncActionSetup()
.then((newActionSetup) => {
actionSetup = newActionSetup;
})

.then(() => getSourceSelection(actionSetup.source, actionSetup.location))
.then((sourceSelection) => validateUserInput({
value: sourceSelection,
validator: sourceSelection =>
sourceSelection
.split(/\r?\n/g)
.reduce((result, line) =>
result && /^\s*(")?/.test(line)),
message: "Invalid body selection: not all lines begin with an open quote"
}))
.then((newSourceSelection) => sourceSelection = newSourceSelection)

.then(() => indentedSelection = sourceSelection
.split(/\r?\n/g)
.map((line) => line.replace(/^(\s*)("\\t)/, '$1\"'))
.join('\n'))

.then(() => {
const replacementRange = transformLocationToRange(actionSetup.location);

return getNewSourceEdit()
.addReplacementEdit(replacementRange, indentedSelection)
.applyEdit()
})

.catch(function (error) {
console.log(error);
});
}

module.exports = {
outdent
};
33 changes: 33 additions & 0 deletions modules/edit-utils/SourceEdit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { WorkspaceEdit, window, workspace } = require("../vscode-service").getVscode();

class SourceEdit{
constructor(){
this.workspaceEdit = new WorkspaceEdit();
this.uri = window.activeTextEditor.document.uri;
}

addInsertEdit(insertPosition, textToInsert) {
this.workspaceEdit.insert(this.uri, insertPosition, textToInsert);

return this;
}

addReplacementEdit(replacementRange, replacementText) {
this.workspaceEdit.replace(this.uri, replacementRange, replacementText);

return this;
}

applyEdit(){
return workspace.applyEdit(this.workspaceEdit);
}
}

function getNewSourceEdit() {
return new SourceEdit();
}

module.exports = {
getNewSourceEdit,
SourceEdit
};
30 changes: 30 additions & 0 deletions modules/edit-utils/code-range-transforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function transformSelectionToLocation(selection) {
return {
start: {
line: selection.start.line + 1,
column: selection.start.character
},
end: {
line: selection.end.line + 1,
column: selection.end.character
}
};
}

function transformLocationToSelection(location) {
return {
start: {
line: location.start.line - 1,
character: location.start.column
},
end: {
line: location.end.line - 1,
character: location.end.column
}
};
}

module.exports = {
transformLocationToSelection,
transformSelectionToLocation
};
40 changes: 40 additions & 0 deletions modules/edit-utils/textEditTransforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const vscodeService = require('../vscode-service');

const {
Position,
Range,
} = vscodeService.getVscode();


function transformLocationPartToPosition({ line, column }) {
return new Position(line - 1, column);
}


function transformLocationToRange({ start, end }) {
return new Range(
transformLocationPartToPosition(start),
transformLocationPartToPosition(end)
);
}


function buildEditLocations({
actionSetup: { location: selectionLocation },
extractionLocation
}) {
const extractionLocationStart = extractionLocation.start;

return {
extractionPosition: transformLocationPartToPosition(extractionLocationStart),
replacementRange: transformLocationToRange(selectionLocation)
}

}


module.exports = {
buildEditLocations,
transformLocationPartToPosition,
transformLocationToRange
};
36 changes: 36 additions & 0 deletions modules/source-utilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
function locationToSourceSelection({ start, end }) {
return {
startLine: start.line - 1,
endLine: end.line - 1,
startColumn: start.column,
endColumn: end.column
};
}

function getSourceSelection(sourceCode, location) {
const {
startLine,
endLine,
startColumn,
endColumn
} = locationToSourceSelection(location);

const selectedLines = sourceCode.split('\n').slice(startLine, endLine + 1);

if (selectedLines.length === 1) {
return selectedLines[0].slice(startColumn, endColumn)
} else {
const lastIndex = selectedLines.length - 1;

selectedLines[0] = selectedLines[0].slice(startColumn);
selectedLines[lastIndex] = selectedLines[lastIndex].slice(0, endColumn);

return selectedLines.join('\n');
}

}

module.exports = {
getSourceSelection,
locationToSourceSelection
};
4 changes: 2 additions & 2 deletions modules/transforms/selection-to-position.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
function transformSelectionToPosition(selection) {
return {
start: {
line: selection.start.line,
line: selection.start.line + 1,
column: selection.start.character + 1
},
end: {
line: selection.end.line,
line: selection.end.line + 1,
column: selection.end.character + 1
}
};
Expand Down
15 changes: 15 additions & 0 deletions modules/validatorService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function validateUserInput({
value,
validator = () => false,
message = 'Unable to validate user input'
}) {
if (typeof value === 'undefined' || !validator(value)) {
throw new Error(message);
}

return value;
}

module.exports = {
validateUserInput
};
19 changes: 15 additions & 4 deletions modules/vscode-service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
function getVsCode() {
return require('vscode');
let vscode = null;

function setVscodeInstance(vscodeInstance) {
vscode = vscodeInstance;
}

function getVscode() {
if(vscode === null) {
vscode = require('vscode');
}

return vscode;
}

module.exports = {
getVsCode
}
setVscodeInstance,
getVscode
};
22 changes: 21 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,34 @@
},
"public": true,
"activationEvents": [
"onCommand:cmstead.snipkit.indent"
"onCommand:cmstead.snipkit.indent",
"onCommand:cmstead.snipkit.outdent"
],
"contributes": {
"commands": [
{
"command": "cmstead.snipkit.indent",
"title": "SnipKit: Indent Lines",
"description": "Indent selected body lines"
},
{
"command": "cmstead.snipkit.outdent",
"title": "SnipKit: Outdent Lines",
"description": "Outdent selected body lines"
}
],
"keybindings": [
{
"command": "cmstead.snipkit.indent",
"key": "ctrl+alt+]",
"mac": "cmd+alt+]",
"when": "editorHasSelection"
},
{
"command": "cmstead.snipkit.outdent",
"key": "ctrl+alt+[",
"mac": "cmd+alt+[",
"when": "editorHasSelection"
}
],
"snippets": [
Expand Down

0 comments on commit e09be9f

Please sign in to comment.