Permalink
Browse files

Add marks.

  • Loading branch information...
1 parent 7c3f054 commit 661f4e4ef10168a0f57a5a0d1ef1f71e4ea8a643 @georgebrock georgebrock committed Dec 10, 2012
Showing with 146 additions and 20 deletions.
  1. +6 −0 README.md
  2. +1 −0 index.html
  3. +1 −0 js/base.js
  4. +2 −2 js/command.js
  5. +2 −2 js/demo.js
  6. +3 −1 js/normal_mode.js
  7. +69 −0 js/normal_mode/marks.js
  8. +6 −4 js/normal_mode/operators.js
  9. +2 −2 js/operation.js
  10. +4 −1 js/range.js
  11. +2 −0 test.html
  12. +38 −0 tests/acceptance/marks.js
  13. +6 −5 tests/unit/command.js
  14. +4 −3 tests/unit/operation.js
View
@@ -25,6 +25,12 @@ subset of normal mode commands, and an insert mode.
* <kbd>+</kbd> or <kbd>Return</kbd>: Move to the start of the next line (after leading whitespace)
* <kbd>-</kbd>: Move to the start of the previous line (after leading whitespace)
+### Marks
+
+* <kbd>m</kbd>: Create a mark
+* <kbd>\`</kbd>: Move to a given mark
+* <kbd>'</kbd>: Move to the line containing a given mark
+
### Insertion
* <kbd>a</kbd>: Append text after the cursor
View
@@ -25,6 +25,7 @@
<script src='js/text_objects.js'></script>
<script src='js/normal_mode.js'></script>
<script src='js/normal_mode/motions.js'></script>
+ <script src='js/normal_mode/marks.js'></script>
<script src='js/normal_mode/insertion.js'></script>
<script src='js/normal_mode/edits.js'></script>
<script src='js/normal_mode/line_search.js'></script>
View
@@ -18,6 +18,7 @@
this.cursor = {row: 0, col: 0};
this.lines = this.textContainer.text().split('\n');
this.registers = {};
+ this.marks = {};
this.render();
View
@@ -7,9 +7,9 @@
this.repeatable = options.repeatable || false;
if (typeof options.description === "function") {
- this.description = function (count, arg) {
+ this.description = function (count, arg, vim) {
count = count === null ? this.defaultCount : count;
- return options.description(count, arg);
+ return options.description(count, arg, vim);
};
} else {
this.description = function () {
View
@@ -11,13 +11,13 @@
Vimulator.Base.prototype.render.apply(vim);
}, this.delay);
- if (op && op.description()) {
+ if (op && op.description(this)) {
li = this.commandList.find("li:first");
if (li.length === 0 || li.hasClass("complete")) {
li = $("<li></li>").prependTo(this.commandList);
}
- li.html(op.description())
+ li.html(op.description(this))
.toggleClass("complete", op.complete() || op.cancelled);
}
};
View
@@ -26,7 +26,9 @@
Vimulator.NormalMode.Edits,
Vimulator.NormalMode.LineSearch,
Vimulator.NormalMode.Operators,
- Vimulator.NormalMode.Repeat
+ Vimulator.NormalMode.Repeat,
+ Vimulator.NormalMode.Marks,
+ Vimulator.NormalMode.MarkMotions
);
return this.commands;
};
@@ -0,0 +1,69 @@
+(function () {
+ var C = Vimulator.Command,
+ U = Vimulator.Utils,
+ CR = Vimulator.CharacterRange,
+ LR = Vimulator.LineRange;
+
+ Vimulator.NormalMode.Marks = {
+ 'm': new C({
+ argument: "literal",
+ callback: function (vim, count, name) {
+ vim.marks[name] = vim.cursorCopy();
+ },
+ description: function (count, name) {
+ return "Create a mark at the cursor called " +
+ U.literalArgDescription(name);
+ }
+ })
+ };
+
+ Vimulator.NormalMode.MarkMotions = {
+ '`': new C({
+ argument: "literal",
+ callback: CR.captureExclusive(function (vim, count, name) {
+ var mark = vim.marks[name];
+ if (mark) {
+ vim.moveCursor(mark.row, mark.col);
+ }
+ }),
+ description: function (count, name, vim) {
+ var mark, desc;
+
+ mark = vim.marks[name];
+ desc = "Move to mark " + U.literalArgDescription(name);
+ if (name && mark) {
+ desc += " (line " + (mark.row + 1) +
+ ", column " + (mark.col + 1) + ")";
+ } else if (name) {
+ desc += " (No such mark is set, use <kbd>m</kbd> " +
+ U.literalArgDescription(name) + " first)";
+ }
+ return desc;
+ }
+ }),
+ "'": new C({
+ argument: "literal",
+ callback: LR.capture(function (vim, count, name) {
+ var mark = vim.marks[name];
+ if (mark) {
+ vim.moveCursor(mark.row, '^');
+ }
+ }),
+ description: function (count, name, vim) {
+ var mark, desc;
+
+ mark = vim.marks[name];
+ desc = "Move to the line containing mark " +
+ U.literalArgDescription(name);
+
+ if (name && mark) {
+ desc += " (line " + (mark.row + 1) + ")";
+ } else if (name) {
+ desc += " (No such mark is set, use <kbd>m</kbd> " +
+ U.literalArgDescription(name) + " first)";
+ }
+ return desc;
+ }
+ })
+ };
+}());
@@ -51,12 +51,13 @@
deleteSubCommands,
Vimulator.NormalMode.Motions,
Vimulator.NormalMode.LineSearch,
+ Vimulator.NormalMode.MarkMotions,
Vimulator.TextObject.Commands
),
- description: function (count, motion) {
+ description: function (count, motion, vim) {
var desc = "Delete ";
if (motion) {
- return desc + motion.description();
+ return desc + motion.description(vim);
} else {
return desc + "<b>&hellip;</b>";
}
@@ -85,12 +86,13 @@
changeSubCommands,
Vimulator.NormalMode.Motions,
Vimulator.NormalMode.LineSearch,
+ Vimulator.NormalMode.MarkMotions,
Vimulator.TextObject.Commands
),
- description: function (count, motion) {
+ description: function (count, motion, vim) {
var desc = "Change ";
if (motion) {
- return desc + motion.description();
+ return desc + motion.description(vim);
} else {
return desc + "<b>&hellip;</b>";
}
View
@@ -91,7 +91,7 @@
return factor * (this.multiplier || 1);
};
- Vimulator.Operation.prototype.description = function () {
+ Vimulator.Operation.prototype.description = function (vim) {
var desc, keys, multiplier;
keys = function (str) {
@@ -114,7 +114,7 @@
if (this.command) {
multiplier = this.multiplier ? ~~this.multiplier : null;
- desc += this.command.description(multiplier, this.argument);
+ desc += this.command.description(multiplier, this.argument, vim);
} else if (!this.cancelled) {
desc += '<b>&hellip;</b>';
}
View
@@ -1,5 +1,8 @@
(function () {
function assignOrdered(subject, start, end) {
+ subject.originalStart = start;
+ subject.originalEnd = end;
+
if (start.row < end.row || start.row == end.row && start.col < end.col) {
subject.start = start;
subject.end = end;
@@ -50,7 +53,7 @@
};
Vimulator.CharacterRange.prototype.toEOL = function (buffer) {
- return this.end.col === buffer.lines[this.end.row].length - 1;
+ return this.originalEnd.col === buffer.lines[this.originalEnd.row].length - 1;
};
View
@@ -27,6 +27,7 @@
<script src='js/text_objects.js'></script>
<script src='js/normal_mode.js'></script>
<script src='js/normal_mode/motions.js'></script>
+ <script src='js/normal_mode/marks.js'></script>
<script src='js/normal_mode/insertion.js'></script>
<script src='js/normal_mode/edits.js'></script>
<script src='js/normal_mode/line_search.js'></script>
@@ -61,6 +62,7 @@
<script src='tests/acceptance/change.js'></script>
<script src='tests/acceptance/repeat.js'></script>
<script src='tests/acceptance/text_objects.js'></script>
+ <script src='tests/acceptance/marks.js'></script>
<script>
(function () {
@@ -0,0 +1,38 @@
+describe("Marks", function () {
+ beforeEach(function () {
+ reset("def greet\n puts 'Hello world'\nend");
+ pressKeys("w" + "mm" + "jf'" + "ms" + "G$" + "me");
+ });
+
+ describe("jumping to a mark with `", function () {
+ it("moves the cursor to a mark", function () {
+ pressKeys("`m");
+ expect(cursorPosition()).toEqual({row: 0, col: 4});
+ pressKeys("`e");
+ expect(cursorPosition()).toEqual({row: 2, col: 2});
+ pressKeys("`s");
+ expect(cursorPosition()).toEqual({row: 1, col: 7});
+ });
+
+ it("can be used as an operator motion", function () {
+ pressKeys("2G$c`s" + "'Hi there" + ESC);
+ expect(currentText()).toBe("def greet\n puts 'Hi there'\nend");
+ });
+ });
+
+ describe("jumping to a mark with '", function () {
+ it("moves the cursor to the line containing a mark", function () {
+ pressKeys("'m");
+ expect(cursorPosition()).toEqual({row: 0, col: 0});
+ pressKeys("'e");
+ expect(cursorPosition()).toEqual({row: 2, col: 0});
+ pressKeys("'s");
+ expect(cursorPosition()).toEqual({row: 1, col: 2});
+ });
+
+ it("can be used as a line-wise operator motion", function () {
+ pressKeys("ggd's");
+ expect(currentText()).toBe("end");
+ });
+ });
+});
View
@@ -102,14 +102,15 @@ describe("Command", function () {
});
it("recieves the default count", function () {
- var desc, cmd;
+ var desc, cmd, vim;
desc = jasmine.createSpy();
cmd = new Vimulator.Command({description: desc});
+ vim = {};
- cmd.description(null, "foo");
- expect(desc).toHaveBeenCalledWith(1, "foo");
- cmd.description(7, "foo");
- expect(desc).toHaveBeenCalledWith(7, "foo");
+ cmd.description(null, "foo", vim);
+ expect(desc).toHaveBeenCalledWith(1, "foo", vim);
+ cmd.description(7, "foo", vim);
+ expect(desc).toHaveBeenCalledWith(7, "foo", vim);
});
});
});
@@ -387,13 +387,14 @@ describe("Operation", function () {
});
it("passes the multiplier & argument to the command", function () {
- var cmd = mockCommand("literal", "Replace");
+ var cmd = mockCommand("literal", "Replace"),
+ vim = {};
op.multiplier = 4;
op.setCommand(cmd, "r");
op.argument = "p";
- expect(op.description()).toBe("<kbd>4</kbd> <kbd>r</kbd> Replace");
- expect(cmd.description).toHaveBeenCalledWith(4, "p");
+ expect(op.description(vim)).toBe("<kbd>4</kbd> <kbd>r</kbd> Replace");
+ expect(cmd.description).toHaveBeenCalledWith(4, "p", vim);
});
});

0 comments on commit 661f4e4

Please sign in to comment.