ScrapCalc (古い方法)

ScrapCalc (古い方法)

ScrapCalcの実装方式を変えたのだけれど古いバージョン(このページ)をしばらく残しておく
Scrapbox上でうまくバージョン管理できるといいのだけど

Scrapboxのテキスト中の式を計算/表示できるようにしてみた。ショートカットキーを押すと [= 式] の中の式を順番に評価して計算結果を表示し、もう一度押すと元に戻る。式の中に = が有るときは式の評価だけ行ない結果は表示しない。

Ctrl-Cで表示をトグルしているところ

サンプル
家計簿
= 預金1 = 100万円, = 預金2 = 200万円, 預金総額 = = 預金1 + 預金2万円
簡単な計算
= a = 10 = b = 20 = = a * b
= = Math.sqrt(2)
= = Math.atan(1) * 4
東京オリンピックまで = Math.floor((new Date('2021-7-23') - Date.now()) / (24 * 60 * 60 * 1000))
レポート採点
= 成績評価 = function(平均){ return 平均 > 90 ? 'S' : 平均 > 80 ? 'A' : 平均 > 70 ? 'B' : 'C'};
山田: = レポート1 = 90 = レポート2 = 80 = 平均 = (レポート1+レポート2)/2 成績: = 成績評価(平均)
佐藤: = レポート1 = 70 = レポート2 = 50 = 平均 = (レポート1+レポート2)/2 成績: = 成績評価(平均)

導入
以下のUserCSSとUserScriptを自分のページに貼ると使える
ScrapScript
Copied!
code:script.js
import '/api/code/masui/ScrapCalc/script.js'
code:style.css
@import '/api/code/masui/ScrapCalc/style.css';
下のコードを自分のページにコピーしてカスタマイズした方が良いかも

参考文献
ScrapCalcはBoomborg計算にインスパイヤされたものです
Jupyterにも少し似てるかも?

注意
変数名に日本語は使えますが 100円玉 みたいに数字ではじまる名前は使えません
JavaScriptで変数名として利用できる文字を使ってください
Ctrl-Cは良くないかも
WindowsやChromeOSでは困りそう
Scrapboxシステムが新しくなったわけではありません。UserScriptで無理矢理実現したものです。

感想
無理矢理だけど動くところが興味深い
家計簿とか採点とかにすぐ使えるけど、思わぬ応用もあるかも
グラフも描きたくなったりして
p5.js で小さなキャンバス作って配置する?

style.css
Copied!
.deco-\= {
color: #111;
background-color: #ffddff;
padding: 0.1em 0.2em 0.1em 0.2em;
}
.scrapcalc_result {
font-style:italic;
font-weight:bold;
background-color:yellow;
}

strict の制限を回避するため、StackOverflowで紹介されていた方法を利用している
script.js
Copied!
function scrapcalc_commands(){
const commands = [];
let count = 0;
for(let expr of document.querySelectorAll('.scrapcalc_result')){
expr.remove();
}
for(let expr of document.querySelectorAll('.deco-\\=')){
let text = expr.innerText;
// 全角カギカッコを配列などで使えるようにする苦しい工夫
let decoded = decodeURI(text).replaceAll('[','[').replaceAll(']',']')
if(text.match(/=/)){
commands.push(decoded + ';');
}
else {
let id = `scrapcalc_element_id_${count}`;
var span = document.createElement('span');
span.id = id;
span.classList.add("scrapcalc_result");
expr.parentNode.appendChild(span)
expr.classList.add("scrapcalc_exp")
expr.style.display = 'none';
commands.push(`document.getElementById("${id}").innerText = ${decoded};`);
count += 1;
}
}
return commands.join("\n");
}

script.js
Copied!
function scrapcalc_reset(){
for(let expr of document.querySelectorAll('.scrapcalc_result')){
expr.remove();
}
for(let expr of document.querySelectorAll('.scrapcalc_exp')){
expr.style.display = 'inline';
}
}
document.addEventListener('keypress', e => {
if (e.key == 'c' && e.ctrlKey){
if(document.querySelectorAll('.scrapcalc_result').length == 0){
const scrapcalc_func = Function(`(() => {${scrapcalc_commands()}})();`);
scrapcalc_func();
}
else {
scrapcalc_reset();
}
}
})
// 何かクリックしたら元に戻す場合
// document.addEventListener('click', e => {
// scrapcalc_reset();
//})
Powered by Helpfeel