aboutsummaryrefslogtreecommitdiff
path: root/docs/try.html
blob: 764a18a4442e90695c735e5566f92834dcdc1971 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <title>BQN online REPL</title>
  <link href="style.css" rel="stylesheet"/>
  <style>
    * { box-sizing: border-box; }
    li { margin:0.7em 0; }
    #code { width:100%; outline:none; }
    #run, #perm { float:right; }
    #perm { font-size:0.7em; margin:-0.2em 1.6em 0 0; }
    .cont { margin:1.3em 0; }
    #rslt { border:none; background:none; min-height:8em; }
    #rslt.err { color:#d11; }
    #kb { line-height:1.5; width:100%; padding:0.3em 0; background:inherit; }
    #kb span { cursor:default; padding:1px; }
    #kb span:hover { background-color:#bce; }
    #kb.backslash  { background-color:#cee; }
    @media (prefers-color-scheme:dark) {
      #kb span:hover { background-color:#237; }
      #kb.backslash  { background-color:#1e2430; }
    }
  </style>
</head>
<body>
  <a href="https://mlochbaum.github.io/BQN/" title='BQN homepage'>BQN</a>
  <div class="cont">
    <div id="kb" class="bqn"></div>
    <textarea id="code" class="bqn" rows="8" autofocus></textarea>
    <input id="run" type="submit" value="Run (or shift-enter)">
    <a id="perm" href="#" title="Link with the code above embedded">permalink</a>
  </div>
  <pre id="rslt"></pre>
  <p>
    Notes:
    <ul>
      <li>You can type special characters with a back<em>slash</em> prefix, as shown by hovering over the character bar above. Documentation links for primitives are found <a href="https://mlochbaum.github.io/BQN/index.html#built-in-operations">here</a>.</li>
      <li>Any modifier with enter will execute (not just shift).</li>
      <li>BQN uses <code class="Ligature"></code> (backslash-space) for stranding, and not juxtaposition. If you don't know what went wrong, check for this first!</li>
      <li>This implementation is still WIP, and in particular I am improving error checking and messages now. Support for function headers and multiple bodies is missing, and Under (<code class="Modifier2"></code>) only works for a small class of structural functions. Performance is bad.</li>
    </ul>
  </p>

<script src="bqn.js"></script>
<script>
let body = document.body;
let doc={}; // html elements with an id
body.querySelectorAll('[id]').forEach(e=>doc[e.id]=e);
let repl = ()=>{
  try {
    let s=doc.code.value;
    doc.rslt.classList.remove('err');
    doc.rslt.textContent=fmt(bqn(s));
  } catch(e) {
  //if (console&&console.error) console.error(e.stack);
    doc.rslt.classList.add('err');
    doc.rslt.textContent=e;
  }
}
doc.run.onclick = repl;

let keymode=0; // 1 for backslash
doc.code.onkeydown = ev => {
  let k = ev.which;
  if (16<=k && k<=20) {
    return;
  } if (k==13 && (ev.shiftKey||ev.ctrlKey||ev.altKey||ev.metaKey)) { // *-enter
    repl(); return false;
  } if (keymode) {
    keymode = 0;
    doc.kb.classList.remove('backslash');
    let c = keys[ev.key];
    if (c) return typeChar(ev.target, c, ev);
  } else if (k===220) { // \
    keymode = 1;
    doc.kb.classList.add('backslash');
    ev.preventDefault();
  }
}
let typeChar = (t, c, ev) => {
  ev.preventDefault();
  let v = t.value;
  let i = t.selectionStart;
  t.value = v.slice(0,i)+c+v.slice(t.selectionEnd);
  t.selectionStart = t.selectionEnd = i+c.length;
  return false;
}

let syncls={ v:"Value", f:"Function", m:"Modifier", d:"Modifier2", n:"Number", g:"Gets", p:"Paren", b:"Bracket", k:"Brace", l:"Ligature", n:"Nothing", s:"Separator", c:"Comment" };
let keydesc='f+Conjugate;Add_f-Negate;Subtract_f×Sign;Multiply_f÷Reciprocal;Divide_f⋆Exponential;Power_f√Square Root;Root_f⌊Floor;Minimum_f⌈Ceiling;Maximum_f∧Sort Up;And_f∨Sort Down;Or_f¬Not;Span_f|Absolute Value;Modulus_f≤Less Than or Equal to_f<Enclose;Less Than_f>Merge;Greater Than_f≥Greater Than or Equal to_f=Rank;Equals_f≠Length;Not Equals_f≡Depth;Match_f≢Shape;Not Match_f⊣Identity;Left_f⊢Identity;Right_f⥊Deshape;Reshape_f∾Join;Join to_f≍Solo;Couple_f↑Prefixes;Take_f↓Suffixes;Drop_f↕Range;Windows_f⌽Reverse;Rotate_f⍉Transpose;Reorder axes_f/Indices;Replicate_f⍋Grade Up;Bins Up_f⍒Grade Down;Bins Down_f⊏First Cell;Select_f⊑First;Pick_f⊐Index of_f⊒Occurrence Count;Progressive Index of_f∊Unique Mask;Member of_f⍷Deduplicate;Find_f⊔Group Indices;Group_f!Assert;Assert with message_m˜Self/Swap_d∘Atop_d○Over_d⊸Before/Bind_d⟜After/Bind_d⌾Under_d⊘Valences_d◶Choose_d⎉Rank_m˘Cells_d⚇Depth_m¨Each_m⌜Table_d⍟Repeat_m⁼Undo_m´Fold_m˝Insert_m`Scan_b←Define_b↩Change_b→Return_s⋄Separator_s,Separator_p(Begin expression_p)End expression_k{Begin block_k}End block_b⟨Begin list_b⟩End list_l‿Strand_n·Nothing_v•System_v𝕨Left argument_f𝕎Left argument (as function)_v𝕩Right argument_f𝕏Right argument (as function)_v𝕗Modifier left operand (as subject)_f𝔽Modifier left operand_v𝕘2-modifier right operand (as subject)_f𝔾2-modifier right operand_v𝕤Current function (as subject)_f𝕊Current function_m𝕣Current modifier_n¯Minus_nπPi_n∞Infinity_c#Comment'.split(/[\n_]/);
let kk=Array.from('`123456890-=~!@#$%^&*()_+qwertuiop[]QWERTIOP{}asdfghjkl;ASFGK:"zxcvbm,./XVBM<> \'');
let kv=Array.from('˜˘¨⁼⌜´˝∞¯•÷׬⎉⚇⍟◶⊘⎊⍎⍕⟨⟩√⋆⌽𝕨∊↑∧⊔⊏⊐π←→↙𝕎⍷𝕣⍋⊑⊒⍳⊣⊢⍉𝕤↕𝕗𝕘⊸∘○⟜⋄↖𝕊𝔽𝔾⌾·˙⥊𝕩↓∨⌊≡∾≍≠𝕏⍒⌈≢≤≥‿↩');
let keys={}, revkeys={};
kk.map((k,i)=>{keys[k]=kv[i];revkeys[kv[i]]=k;});
doc.kb.innerHTML = keydesc.map(d=>{
  let s = syncls[d[0]];
  let c = Array.from(d)[1];
  let t = d.slice(1+c.length).replace(';','\n');
  let k = revkeys[c]; if (k) t += '\n\\ '+k;
  return '<span title="'+t+'" class="'+s+'">'+c+'</span>'
}).join("&#8203;"); // zero-width space
doc.kb.onmousedown = ev => {
  let t = ev.target;
  if (t.nodeName === 'SPAN') {
    return typeChar(doc.code, t.textContent, ev);
  }
}

doc.perm.onmouseover = doc.perm.onfocus = () => {
  doc.perm.href='#code='+escape(doc.code.value)
}

if (location.hash) {
  let hp={};
  location.hash.substring(1).split(',').map(s=>{
    let[k,v]=s.split('=');hp[k]=unescape(v)
  });
  doc.code.value = hp.code||'';
  if (hp.run) repl();
}
doc.code.focus();
</script>
</body>
</html>