Skip to content

Commit

Permalink
Backspace should work as regular if it is the first line with no chil…
Browse files Browse the repository at this point in the history
…dren
  • Loading branch information
vslinko committed Apr 14, 2021
1 parent 9aefe03 commit 253eaec
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 52 deletions.
117 changes: 67 additions & 50 deletions src/features/DeleteShouldIgnoreBulletsFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Plugin_2 } from "obsidian";
import { EditorUtils } from "src/editor_utils";
import { IFeature } from "src/feature";
import { ListUtils } from "src/list_utils";
import { Root } from "src/root";
import { Settings } from "src/settings";

export class DeleteShouldIgnoreBulletsFeature implements IFeature {
Expand All @@ -28,7 +29,11 @@ export class DeleteShouldIgnoreBulletsFeature implements IFeature {
cm: CodeMirror.Editor,
changeObj: CodeMirror.EditorChangeCancellable
) => {
if (changeObj.origin !== "+delete" || !this.settings.stickCursor) {
if (
changeObj.origin !== "+delete" ||
!this.settings.stickCursor ||
!this.editorUtils.containsSingleCursor(cm)
) {
return;
}

Expand All @@ -42,75 +47,86 @@ export class DeleteShouldIgnoreBulletsFeature implements IFeature {
const listContentStartCh = list.getContentStartCh();
const listContentEndCh = list.getContentEndCh();

const sameLine = changeObj.from.line === changeObj.to.line;
const nextLine = changeObj.from.line + 1 === changeObj.to.line;
if (this.isBackspaceOnContentStart(changeObj, listContentStartCh)) {
this.deleteItemAndMergeContentWithPreviousLine(cm, root, changeObj);
} else if (this.isDeletionIncludesBullet(changeObj, listContentStartCh)) {
this.limitDeleteRangeToContentRange(changeObj, listContentStartCh);
} else if (this.isDeleteOnLineEnd(changeObj, listContentEndCh)) {
this.deleteNextItemAndMergeContentWithCurrentLine(cm, root, changeObj);
}
};

if (
sameLine &&
changeObj.from.ch === listContentStartCh - 1 &&
changeObj.to.ch === listContentStartCh
) {
changeObj.cancel();
this.backspace(cm);
} else if (sameLine && changeObj.from.ch < listContentStartCh) {
const from = {
line: changeObj.from.line,
ch: listContentStartCh,
};
changeObj.update(from, changeObj.to, changeObj.text);
} else if (
nextLine &&
private isDeleteOnLineEnd(
changeObj: CodeMirror.EditorChangeCancellable,
listContentEndCh: number
) {
return (
changeObj.from.line + 1 === changeObj.to.line &&
changeObj.from.ch === listContentEndCh &&
changeObj.to.ch === 0
) {
changeObj.cancel();
this.delete(cm);
}
};
);
}

private backspace(editor: CodeMirror.Editor) {
if (!this.editorUtils.containsSingleCursor(editor)) {
return false;
}
private isDeletionIncludesBullet(
changeObj: CodeMirror.EditorChangeCancellable,
listContentStartCh: number
) {
return (
changeObj.from.line === changeObj.to.line &&
changeObj.from.ch < listContentStartCh
);
}

const root = this.listsUtils.parseList(editor);
private isBackspaceOnContentStart(
changeObj: CodeMirror.EditorChangeCancellable,
listContentStartCh: number
) {
return (
changeObj.from.line === changeObj.to.line &&
changeObj.from.ch === listContentStartCh - 1 &&
changeObj.to.ch === listContentStartCh
);
}

if (!root) {
return false;
}
private limitDeleteRangeToContentRange(
changeObj: CodeMirror.EditorChangeCancellable,
listContentStartCh: number
) {
const from = {
line: changeObj.from.line,
ch: listContentStartCh,
};
changeObj.update(from, changeObj.to, changeObj.text);
}

private deleteItemAndMergeContentWithPreviousLine(
editor: CodeMirror.Editor,
root: Root,
changeObj: CodeMirror.EditorChangeCancellable
) {
const list = root.getListUnderCursor();
if (
root.getTotalLines() === 1 &&
root.getChildren()[0].getContent().length === 0
root.getListStartPosition().line === root.getLineNumberOf(list) &&
list.getChildren().length === 0
) {
editor.replaceRange(
"",
root.getListStartPosition(),
root.getListEndPosition()
);
return true;
return false;
}

const res = root.deleteAndMergeWithPrevious();

if (res) {
changeObj.cancel();
this.listsUtils.applyChanges(editor, root);
}

return res;
}

private delete(editor: CodeMirror.Editor) {
if (!this.editorUtils.containsSingleCursor(editor)) {
return false;
}

const root = this.listsUtils.parseList(editor);

if (!root) {
return false;
}

private deleteNextItemAndMergeContentWithCurrentLine(
editor: CodeMirror.Editor,
root: Root,
changeObj: CodeMirror.EditorChangeCancellable
) {
const list = root.getListUnderCursor();
const nextLineNo = root.getCursor().line + 1;
const nextList = root.getListUnderLine(nextLineNo);
Expand All @@ -128,6 +144,7 @@ export class DeleteShouldIgnoreBulletsFeature implements IFeature {
const reallyChanged = root.getCursor().line !== nextLineNo;

if (reallyChanged) {
changeObj.cancel();
this.listsUtils.applyChanges(editor, root);
}

Expand Down
28 changes: 26 additions & 2 deletions tests/features/DeleteShouldIgnoreBulletsFeature.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
import type ObsidianOutlinerPluginWithTests from "../../test";

export default {
"backspace should remove line if it's last empty line": (plugin) => {
"backspace should work as regular if it's last empty line": (plugin) => {
// arrange
plugin.applyState(["- |"]);

// act
plugin.simulateKeydown("Backspace");

// assert
plugin.assertCurrentState(["|"]);
plugin.assertCurrentState(["-|"]);
},
"backspace should work as regular if it's first line without children": (
plugin
) => {
// arrange
plugin.applyState(["- |one", "- two"]);

// act
plugin.simulateKeydown("Backspace");

// assert
plugin.assertCurrentState(["-|one", "- two"]);
},
"backspace should do nothing if it's first line but with children": (
plugin
) => {
// arrange
plugin.applyState(["- |one", "\t- two"]);

// act
plugin.simulateKeydown("Backspace");

// assert
plugin.assertCurrentState(["- |one", "\t- two"]);
},
"backspace should remove symbol if it isn't empty line": (plugin) => {
// arrange
Expand Down

0 comments on commit 253eaec

Please sign in to comment.