Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ Examples:
showing a bookmark dialog is suppressed.
- `map r reload hard` maps the r key to reloading the page, and also includes the "hard" option to
hard-reload the page.
- `mapkey ы s` maps one key to another.
- `langmap фыва;asdf,aAbBzZ,cC,dD` maps multiple keys with `from_keys;to_keys` or `fT` pairs, separated by comma.
- `unmap <c-d>` removes any mapping for ctrl+d and restores Chrome's default behavior.
- `unmap r` removes any mapping for the r key.

Expand Down
88 changes: 77 additions & 11 deletions background_scripts/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,53 @@ const KeyMappingsParser = {
}
};

const mapCharacter = (from, to) => {
const fromChar = this.parseKeySequence(from);
const toChar = this.parseKeySequence(to);
const isValid = fromChar.length == toChar.length && toChar.length === 1;
if (isValid) {
mapKeyRegistry[fromChar[0]] = toChar[0];
} else {
errors.push(
`mapkey/langmap only support mapping keys which are single characters`,
);
}
};

const parseLangmap = (langmap) => {
let escape = false;
let current = [];
let left = [];
for (const c of langmap) {
if (escape) {
current.push(c);
escape = false;
continue;
}
if (c === ";") {
left = current;
current = [];
continue;
}
current.push(c);
}
if (left.length > 0) {
if (left.length !== current.length) {
errors.push(`Incorrect usage for langmap in the line: ${line}`);
return;
}
for (let i = 0; i < left.length; i++) {
mapCharacter(left[i], current[i]);
}
} else if (current.length % 2 === 0) {
for (let i = 0; i < current.length - 1; i += 2) {
mapCharacter(current[i], current[i + 1]);
}
} else {
errors.push(`Incorrect usage for langmap in the line: ${line}`);
}
};

for (const line of configLines) {
const tokens = line.split(/\s+/);
const action = tokens[0].toLowerCase();
Expand Down Expand Up @@ -173,17 +220,36 @@ const KeyMappingsParser = {
errors.push(`Incorrect usage for mapKey in the line: ${line}`);
continue;
}
const fromChar = this.parseKeySequence(tokens[1]);
const toChar = this.parseKeySequence(tokens[2]);
// NOTE(philc): I'm not sure why we enforce that the fromChar and toChar have to be
// length one. It's been that way since this feature was introduced in 6596e30.
const isValid = fromChar.length == toChar.length && toChar.length === 1;
if (isValid) {
mapKeyRegistry[fromChar[0]] = toChar[0];
} else {
errors.push(
`mapkey only supports mapping keys which are single characters. Line: ${line}`,
);
mapCharacter(tokens[1], tokens[2]);
break;
}
case "langmap": {
if (tokens.length !== 2) {
errors.push(`Incorrect usage for langmap in the line: ${line}`);
continue;
}
const langmap = tokens[1];
let escape = false;
let current = [];
for (const c of langmap) {
if (escape) {
current.push(c);
escape = false;
continue;
}
if (c === ",") {
parseLangmap(current);
current = [];
continue;
}
if (c === "\\") {
escape = true;
continue;
}
current.push(c);
}
if (current.length > 0) {
parseLangmap(current);
}
break;
}
Expand Down
2 changes: 2 additions & 0 deletions pages/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ <h2>Custom key mappings</h2>
>
map j scrollDown
map z2 setZoom level=2
mapkey я z
langmap aA,йцу;qwe
unmap j
unmapAll
" this is a comment
Expand Down
5 changes: 5 additions & 0 deletions tests/unit_tests/commands_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ context("KeyMappingsParser", () => {
assert.equal({ "a": "b" }, keyToMappedKey);
});

should("handle langmap statements", () => {
const { keyToMappedKey } = KeyMappingsParser.parse("langmap фы;as,a\\bAB");
assert.equal({ "ф": "a", "ы": "s", "a": "b", "A": "B" }, keyToMappedKey);
});

should("handle unmap statements", () => {
const input = "mapkey a b \n unmap a";
const { keyToMappedKey } = KeyMappingsParser.parse(input);
Expand Down