takker99/ScrapBindings-settings
takker99/ScrapBindingsのtakker.icon用設定ファイル
table:目次
popup操作 takker99/ScrapBindings-settings#665427ca1280f00000c9d8d8
ページ遷移 takker99/ScrapBindings-settings#6654197b1280f00000c9d6e4
cursor移動 takker99/ScrapBindings-settings#6654197b1280f00000c9d6f7
テキスト編集 takker99/ScrapBindings-settings#6654197b1280f00000c9d71e
scrapbox-timestamp takker99/ScrapBindings-settings#6654197b1280f00000c9d738
タスク用 takker99/ScrapBindings-settings#6654197b1280f00000c9d772
$ deno check -r=https://scrapbox.io --remote https://scrapbox.io/api/code/takker/takker99%2FScrapBindings-settings/config.ts
code:config.ts
/// <reference lib="dom.iterable" />
import {
caret, getCharDOM, getLineDOM, press, insertText,
goHeadLine, goLastLine,
scrollUp, scrollDown,
useStatusBar,
} from "../scrapbox-userscript-std/dom.ts";
import { setDebugMode } from "../takker99%2FScrapBindings/mod.ts";
code:config.ts
const pd = (e: Event) => e.preventDefault();
const sp = (e: Event) => e.stopPropagation();
popup操作
Popup Menuに独自のkeyboard shortcutを割り当てるUserScriptを参考に作る
code:config.ts
import { popupMenu } from "../scrapbox-userscript-std/dom.ts";
const clickPopup = (e: KeyboardEvent, buttonName: string | RegExp): void => {
const buttons = popupMenu()?.getElementsByClassName?.("button");
if (!buttons) return;
const button = ...buttons.find(
(button) => buttonName instanceof RegExp ?
buttonName.test(button.textContent ?? "") :
button.textContent === buttonName
);
if (!(button instanceof HTMLDivElement)) return;
if (e.target !== document.activeElement) return;
pd(e);sp(e);
button.click();
};
const popup = {
// 複数行打ち消し線
"-": (e: KeyboardEvent) => clickPopup(e, "\uf0cc"),
// リンクを外す
"]": (e: KeyboardEvent) => clickPopup(e, "\uf127"),
"c": (e: KeyboardEvent) => clickPopup(e, "Copy plain"),
// 数式記法にする
"$": (e: KeyboardEvent) => clickPopup(e, "\uf698"),
// takker-books用
"{": (e: KeyboardEvent) => clickPopup(e, /{{c\d+}}/),
"}": (e: KeyboardEvent) => clickPopup(e, "reset cloze"),
"n": (e: KeyboardEvent) => clickPopup(e, "make note"),
};
ページ遷移
code:config.ts
const navigation = {
// リンクを踏む
"<C-]>": (e: KeyboardEvent) => {
const { position: { line, char } } = caret();
const a = getCharDOM(line, char)?.closest("a.page-link")
// なかったらその行の中で一番先頭のリンクを踏む
?? getLineDOM(line)?.querySelector?.("a.page-link");
if (!(a instanceof HTMLAnchorElement)) return;
pd(e);sp(e);
a.click();
},
"<C-o>": (e: KeyboardEvent) => { pd(e);sp(e);history.back(); },
};
cursor移動
code:config.ts
const motion = {
"<C-home>": (e: KeyboardEvent) => { pd(e);sp(e);goHeadLine(); },
"<C-end>": (e: KeyboardEvent) => { pd(e);sp(e);goLastLine(); },
};
テキスト編集
custom-new-page
for-custom-new-page
物理キーボード用拡張shortcut keyを導入するScrapBindingsの設定はdefaultで有効にする
iは実装しない
scrapbox側が同じコマンドを<C-e>で用意しているため
code:config.ts
import { makeNewPage } from "../custom-new-page/mod.ts";
import {
newPageHook,
splittedLinkHook,
taskLineHook,
} from "../for-custom-new-page/mod.ts";
import {
outdentLines, downLines, upLines, indentLines,
outdentBlocks, downBlocks, upBlocks, indentBlocks,
} from "../scrapbox-userscript-std/dom.ts";
import { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
declare const scrapbox: Scrapbox;
const hooks = taskLineHook, newPageHook, splittedLinkHook;
const edit = {
"<C-X>": (e: KeyboardEvent) => {
const project = window.prompt("Create a new page at", scrapbox.Project.name);
if (!project) return;
pd(e);sp(e);
makeNewPage({ project, mode: "self", hooks })?.();
},
"<C-D>": (e: KeyboardEvent) => {
const project = window.prompt("Create a new page at", scrapbox.Project.name);
if (!project) return;
pd(e);sp(e);
makeNewPage({ project, mode: "noopen", hooks })?.();
},
"<C-h>": (e: KeyboardEvent) => { pd(e);sp(e);outdentLines(); },
"<C-j>": (e: KeyboardEvent) => { pd(e);sp(e);downLines(); },
"<C-k>": (e: KeyboardEvent) => { pd(e);sp(e);upLines(); },
"<C-l>": (e: KeyboardEvent) => { pd(e);sp(e);indentLines(); },
"<A-h>": (e: KeyboardEvent) => { pd(e);sp(e);outdentBlocks(); },
"<A-j>": (e: KeyboardEvent) => { pd(e);sp(e);downBlocks(); },
"<A-k>": (e: KeyboardEvent) => { pd(e);sp(e);upBlocks(); },
"<A-l>": (e: KeyboardEvent) => { pd(e);sp(e);indentBlocks(); },
};
scrapbox-timestamp
cf. /scrapboxlab/タイムスタンプを削除する
code:config.ts
import { lightFormat, addDays } from "../date-fns/mod.ts";
// timestampを無効化する
// alt+tの誤動作を防止する
// @ts-ignore scrapbox-jp/typesのバグ
scrapbox.TimeStamp.removeAllFormats();
const timestamp = {
"<A-t><A-t>": (e: KeyboardEvent) => {
pd(e);sp(e);
insertText(lightFormat(new Date(), '#yyyy-MM-dd HH:mm:ss '));
},
"<A-t><A-j>": (e: KeyboardEvent) => {
pd(e);sp(e);
insertText(lightFormat(new Date(), 'yyyy-MM-dd HH:mm:ss '));
},
"<A-t><A-k>": (e: KeyboardEvent) => {
pd(e);sp(e);
insertText(lightFormat(new Date(), 'HH:mm:ss '));
},
"<A-t><A-l>": (e: KeyboardEvent) => {
pd(e);sp(e);
insertText(lightFormat(new Date(), 'yyyy-MM-dd'));
},
};
code:config.ts
import { taskCommon } from "./task-common.ts";
export { task } from "./task.ts";
export const config = {
...popup,
...navigation,
...motion,
...edit,
...timestamp,
...taskCommon,
};
takker99/takker-scheduler用
bundlerを介さないと実行できないので注意
任意のprojectから使いたいもの
takker99/takker-scheduler/mobileにも同じコード有り
予定タスク以外は現在日付で展開させたいかも
code:task-common.ts
import {
transport, createTask, toString
} from "../takker99%2Ftakker-scheduler/deps.ts";
import {
parse, toTaskLine
} from "../takker99%2Ftakker-scheduler/workflow.ts";
import {
caret, getLines, replaceLines
} from "../scrapbox-userscript-std/dom.ts";
import { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
import { isErr, unwrapOk } from "npm:option-t@51/plain_result";
declare const scrapbox: Scrapbox;
const pd = (e: Event) => e.preventDefault();
const sp = (e: Event) => e.stopPropagation();
export const taskCommon = {
"<A-a><A-t>": async (e: KeyboardEvent) => {
pd(e);sp(e);
const start, end = getLineRange();
const text = getLines().slice(start, end + 1).map((line) => {
const text = line.text;
const link = line.text.match(/\[(^\]+)\]/)?.1;
if (!link) return text;
const result = parse(link);
if (!result || isErr(result)) return text;
const task = unwrapOk(result);
if (task.freshness?.status === "done") return text;
const taskLine = toTaskLine(task, new Date());
if (!taskLine) return text;
taskLine.title = [${link}];
return toString(taskLine);
}).join("\n");
await replaceLines(start, end, text);
await createTask();
},
"<A-a><A-m>": (e: KeyboardEvent) => {
if (scrapbox.Layout !== "page") return;
pd(e);sp(e);
transport({
from: {
project: scrapbox.Project.name,
title: scrapbox.Page.title,
},
to: "takker-memex",
});
},
};
/** 選択範囲に含まれる行かカーソルがいる行を返す
*
* ported from https://github.com/takker99/takker-scheduler/blob/0.7.6/commands/getLineRange.ts
*/
const getLineRange = (): readonly number, number => {
const { selectionRange: { start, end }, selectedText, position } = caret();
return selectedText === ""
? position.line, position.line
: start.line > end.line
? end.line, start.line
: start.line, end.line as const;
};
/takker-memexだけで使うもの
$ deno check -r=https://scrapbox.io --remote https://scrapbox.io/api/code/takker/takker99%2FScrapBindings-settings/task.ts
code:task.ts
import {
addTask, startTask, endTask, posterioriEndTask,
walkDay, moveToday, format
} from "../takker99%2Ftakker-scheduler/deps.ts";
import { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
declare const scrapbox: Scrapbox;
const pd = (e: Event) => e.preventDefault();
const sp = (e: Event) => e.stopPropagation();
export const task = {
"<A-a><A-a>": (e: KeyboardEvent) => { pd(e);sp(e);addTask(); },
"<A-a><A-s>": (e: KeyboardEvent) => { pd(e);sp(e);startTask(); },
"<A-a><A-e>": (e: KeyboardEvent) => { pd(e);sp(e);endTask(); },
"<A-a><A-0>": (e: KeyboardEvent) => { pd(e);sp(e);posterioriEndTask(); },
"<A-a><A-1>": (e: KeyboardEvent) => { pd(e);sp(e);walkDay(1); },
"<A-a><A-t>": (e: KeyboardEvent) => { pd(e);sp(e);moveToday(); },
"<A-a><A-S>": (e: KeyboardEvent) => {
if (scrapbox.Layout !== "page") return;
pd(e);sp(e);
format(scrapbox.Project.name, scrapbox.Page.title);
},
};
#2024-05-27 14:47:12