├── .gitignore
├── APLSource
├── ahk_shifts
│ ├── Alt.apla
│ ├── Ctrl.apla
│ ├── LAlt.apla
│ ├── LCtrl.apla
│ ├── RAlt.apla
│ ├── RCtrl.apla
│ ├── LWin.apla
│ ├── RWin.apla
│ └── CapsLock.apla
├── version.apla
├── OutFile.aplf
├── GUI
│ ├── IsClassicInterpreter.aplf
│ ├── Send.aplf
│ ├── Shifts.aplf
│ ├── Suspend.aplf
│ ├── Run.aplf
│ ├── HandleHTTPRequest.aplf
│ └── HandleWSReceive.aplf
├── DevSetup.aplf
├── SaveScript.aplf
├── ReplaceForBoth.aplo
├── AddGroups.aplf
├── LoadSnippets.aplf
├── LoadTSV.aplf
├── LoadKeymaps.aplf
├── Run.aplf
├── MakeScript.aplf
├── LoadGUI.aplf
├── OutPath.aplf
├── Suspend.aplf
├── Prefix.aplf
├── HotKey.aplf
├── LocateClassicExes.aplf
├── StartupFolder.aplf
├── Make.aplf
├── GenerateScript.aplf
└── RunTests.aplf
├── packages
├── apl-dependencies.txt
└── apl-buildlist.json
├── CI
├── Build.aplf
├── publish_release.ps1
└── Inject-Version.sh
├── scripts
├── prefix.ahk
├── tmp.ahk
├── DE-Alt.ahk
├── APL-de_DE-Ctrl.ahk
└── CapsLock-en_UK.ahk
├── docs
└── index.md
├── APLAutoHotKey.dyalogbuild
├── snippets
└── suspend.ahk
├── GUI
├── classic.html
├── app.css
├── app.js
└── app.html
├── keymaps
├── da_DK.tsv
├── de_DE.tsv
├── en_GB.tsv
├── en_US.tsv
├── es_ES.tsv
├── fi_FI.tsv
├── fr_FR.tsv
├── it_IT.tsv
├── sv_SE.tsv
└── keymaps.md
├── LICENSE
├── cider.config
├── README.md
└── apl-packages
├── APLTreeUtils2.aplc
└── WinReg.aplc
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | packages/*/
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/Alt.apla:
--------------------------------------------------------------------------------
1 | ('!'⋄)
2 |
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/Ctrl.apla:
--------------------------------------------------------------------------------
1 | ('^'⋄)
2 |
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/LAlt.apla:
--------------------------------------------------------------------------------
1 | '!'
2 |
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/RCtrl.apla:
--------------------------------------------------------------------------------
1 | '>^'
2 |
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/LWin.apla:
--------------------------------------------------------------------------------
1 | 'LWin & '
2 |
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/RWin.apla:
--------------------------------------------------------------------------------
1 | 'RWin & '
2 |
--------------------------------------------------------------------------------
/APLSource/version.apla:
--------------------------------------------------------------------------------
1 | '1.0.0/DEVELOPMENT'
2 |
--------------------------------------------------------------------------------
/APLSource/ahk_shifts/CapsLock.apla:
--------------------------------------------------------------------------------
1 | 'CapsLock & '
2 |
--------------------------------------------------------------------------------
/packages/apl-dependencies.txt:
--------------------------------------------------------------------------------
1 | aplteam-WinReg-5.0.4
2 |
--------------------------------------------------------------------------------
/APLSource/OutFile.aplf:
--------------------------------------------------------------------------------
1 | OutFile←{ 'APL-',⍵.locale,'-',(⊃,/⍵.shift),'.ahk' }
2 |
--------------------------------------------------------------------------------
/APLSource/GUI/IsClassicInterpreter.aplf:
--------------------------------------------------------------------------------
1 | r←IsClassicInterpreter
2 | r←82≡⎕DR''
3 |
--------------------------------------------------------------------------------
/CI/Build.aplf:
--------------------------------------------------------------------------------
1 | Build
2 | ⎕SE.UCMD'DBuild APLAutoHotKey.dyalogbuild -save'
3 | ⎕OFF
4 |
--------------------------------------------------------------------------------
/APLSource/DevSetup.aplf:
--------------------------------------------------------------------------------
1 | DevSetup dir
2 | LoadGUI dir
3 | LoadKeymaps dir
4 | LoadSnippets dir
5 |
--------------------------------------------------------------------------------
/APLSource/SaveScript.aplf:
--------------------------------------------------------------------------------
1 | size←script SaveScript path;overwrite
2 | overwrite←1
3 | size←script ⎕NPUT path overwrite
4 |
--------------------------------------------------------------------------------
/APLSource/ReplaceForBoth.aplo:
--------------------------------------------------------------------------------
1 | ReplaceForBoth←{
2 | ⍝ Replace ⍵⍵ in ⍵ with ⍺⍺ if both of ⍵⍵ found in ⍵
3 | opts←⍵⍵ ⋄ Rmv←~∘opts ⋄ Add←⍺⍺∘(,⍥⊆) ⋄ both←∧/⍵⍵∊⍵
4 | (Add⍤Rmv⍣both)⍵
5 | }
6 |
--------------------------------------------------------------------------------
/APLSource/AddGroups.aplf:
--------------------------------------------------------------------------------
1 | AddGroups←{
2 | ⍝ ⍵: vtv paths to dyalog exes
3 | ⍝ ←: char vec GroupAdd lines
4 | newline←⎕UCS 10
5 | ⊃,/'GroupAdd "Classic", "ahk_exe '∘,¨⍵,¨⊂'"',⎕UCS 10
6 | }
7 |
--------------------------------------------------------------------------------
/APLSource/GUI/Send.aplf:
--------------------------------------------------------------------------------
1 | Send←{
2 | ⍝ Send WebSocket message ⍵ to HTMLRenderer with ID ⍺
3 | _←hr.WebSocketSend ⍺ ⍵ 1 1 ⍝ Shy result to prevent the workspace application from opening the APL session
4 | }
5 |
--------------------------------------------------------------------------------
/packages/apl-buildlist.json:
--------------------------------------------------------------------------------
1 | {
packageID: [
"aplteam-WinReg-5.0.4",
"aplteam-APLTreeUtils2-1.1.3",
],
principal: [
1,
0,
],
url: [
"https://tatin.dev/",
"https://tatin.dev/",
],
}
2 |
--------------------------------------------------------------------------------
/APLSource/GUI/Shifts.aplf:
--------------------------------------------------------------------------------
1 | Shifts←{
2 | ⍝ ⍵: options namespace
3 | ⍝ ←: options namespace with API-ready shifts
4 | 0=⍵.⎕NC'shift':'Please select at least 1 shifting key'⎕SIGNAL 400
5 | ⍵.shift←⍵.shift.⎕NL ¯2
6 | ⍵
7 | }
8 |
--------------------------------------------------------------------------------
/APLSource/LoadSnippets.aplf:
--------------------------------------------------------------------------------
1 | LoadSnippets dir;file;name;root;sp
2 | 'snippets'⎕NS ⍬
3 | root←dir,'/snippets/'
4 | sp←⊃(⎕NINFO ⎕OPT'Wildcard' 1)root,'/*'
5 | (name file)←↓⍉↑{(2⊃⌽⎕NPARTS ⍵)(⍵)}¨sp
6 | ⍎¨name{'snippets.',⍺,'←⊃⎕NGET ''',⍵,''''}¨file
7 |
--------------------------------------------------------------------------------
/APLSource/LoadTSV.aplf:
--------------------------------------------------------------------------------
1 | LoadTSV←{
2 | 82≡⎕DR'':0 2⍴'' ⍝ Cannot use Unicode characters with Classic interpreter, but still need to build on it
3 | opts←⊂'Separator'(⎕UCS 9)
4 | opts,←⊂'EscapeChar' '\'
5 | (⎕CSV ⎕OPT opts)⍵
6 | }
7 |
--------------------------------------------------------------------------------
/APLSource/LoadKeymaps.aplf:
--------------------------------------------------------------------------------
1 | LoadKeymaps dir;km;root
2 | ⍝ ⍵: project root directory
3 | 'keymaps'⎕NS ⍬
4 | root←dir,'/keymaps/'
5 | km←'en_GB' 'en_US' 'da_DK' 'de_DE' 'es_ES' 'fr_FR' 'it_IT' 'fi_FI' 'sv_SE'
6 | ⍎¨{'keymaps.',⍵,'←LoadTSV ''',root,⍵,'.tsv'''}¨km
7 |
--------------------------------------------------------------------------------
/scripts/prefix.ahk:
--------------------------------------------------------------------------------
1 | `::
2 | {
3 | ih := InputHook("L1 M")
4 | ih.Start()
5 | ih.Wait()
6 | Switch ih.Input {
7 | Case "a":
8 | Send "á"
9 | Case "e":
10 | Send "ŕe"
11 | Case "A":
12 | Send "Á"
13 | }
14 | }
15 | <^>!a::Send "ayyy"
16 |
--------------------------------------------------------------------------------
/APLSource/Run.aplf:
--------------------------------------------------------------------------------
1 | Run dev
2 | ⍝ dev 0=production, 1=trap expected events, 2=do not trap events
3 | :If dev>0
4 | DevSetup CiderConfig.HOME
5 | GUI.dev←2-dev
6 | GUI.Run
7 | :Else
8 | GUI.dev←0
9 | GUI.Run
10 | ⎕OFF
11 | :EndIf
12 |
--------------------------------------------------------------------------------
/APLSource/GUI/Suspend.aplf:
--------------------------------------------------------------------------------
1 | Suspend←{
2 | ⍝ ⍵: options namespace
3 | ⍝ ←: options namespace with API-ready suspend option
4 | 0=⍵.⎕NC'suspend':⍵
5 | 2<≢sus←⍵.suspend.⎕NL ¯2:'Maximum of 2 keys allowed in suspend shortcut'⎕SIGNAL 400
6 | ⍵.suspend←sus
7 | ⍵
8 | }
9 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ## Escape special characters
2 | Some characters have meaning in AutoHotKey scripts and must be treated specially:
3 |
4 | **TODO:** different when denoting output (Send "") vs input?
5 |
6 | |Key|Literal|
7 | |---|---|
8 | |`\``|`VKDC`|
9 | |`!`|`{!}`|
10 | |`;`|`\`;`|
11 |
--------------------------------------------------------------------------------
/APLSource/MakeScript.aplf:
--------------------------------------------------------------------------------
1 | MakeScript←{
2 | ⍝ ⍵ ←→ Options JSON Object
3 | ⍝ ← ←→ (Error number)(Error message)
4 |
5 | script←GenerateScript ⍵
6 | b←script∘SaveScript¨⊆⍵.outfile
7 | Saved←{'Saved: ',⍵,' (',(⍕⍺),' bytes)
'}
8 | 0(⊃(⊣,'
',⊢)/b Saved¨⊆⍵.outfile)
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/APLSource/LoadGUI.aplf:
--------------------------------------------------------------------------------
1 | LoadGUI dir
2 | span←''
3 | vspan←'v',version,''
4 | GUI.app_html←(span ⎕R vspan)⊃⎕NGET dir,'/GUI/app.html'
5 | GUI.app_css ←⊃⎕NGET dir,'/GUI/app.css'
6 | GUI.app_js ←⊃⎕NGET dir,'/GUI/app.js'
7 | GUI.classic ←⊃⎕NGET dir,'/GUI/classic.html'
8 |
--------------------------------------------------------------------------------
/APLSource/GUI/Run.aplf:
--------------------------------------------------------------------------------
1 | Run;hr;html
2 | hr←⎕NEW⊂'HTMLRenderer'
3 | hr.onWebSocketReceive←'HandleWSReceive'
4 | hr.onHTTPRequest←'HandleHTTPRequest'
5 | hr.InterceptedURLs⍪←↑('/app.css' 1)('/app.js' 1)
6 | html←(1+IsClassicInterpreter)⊃(app_html classic)
7 | hr.HTML←html
8 | hr.(Posn Size)←(1 10)(95 45)
9 | ⎕DQ'hr'
10 |
--------------------------------------------------------------------------------
/APLAutoHotKey.dyalogbuild:
--------------------------------------------------------------------------------
1 | DYALOGBUILD : 1.80.0
2 | EXEC : db←1⊃⎕RSI ⍝ DBuild's home
3 | EXEC : ⎕SE.Link.Import 'APLAutoHotKey' (db.path,'APLSource')
4 | EXEC : ⎕SE.Link.Import 'APLAutoHotKey' (db.path,'apl-packages')
5 | EXEC : APLAutoHotKey.DevSetup db.path
6 | EXEC : ⎕EX'db'
7 | LX : APLAutoHotKey.Run 0
8 | TARGET : build/APLAutoHotKey.dws
9 |
--------------------------------------------------------------------------------
/APLSource/OutPath.aplf:
--------------------------------------------------------------------------------
1 | OutPath←{
2 | ⍝ ⍺: char vec :: directory path
3 | ⍝ ⍵: options namespace
4 | ⍝ ←: options namespace with .ahk outfile fully qualified file path
5 | dir←'\',⍨⍣(~'\/'∊⍨⊃⌽⍺)⊢⍺
6 | of←('/'⎕R'\\') dir,OutFile ⍵
7 | 0=⍵.⎕NC'outfile':of{⍵.outfile←⊂⍺ ⋄ ⍵}⍵ ⍝ Create outfile if not exists
8 | ⍵.outfile,←⊂of ⍝ Otherwise append outfile
9 | ⍵
10 | }
11 |
--------------------------------------------------------------------------------
/APLSource/GUI/HandleHTTPRequest.aplf:
--------------------------------------------------------------------------------
1 | res ← HandleHTTPRequest (hr evt pr update code msg mime url headers body method);root;http_code;http_msg;mime_type
2 | root ← 'http://dyalog_root/'
3 | body ← ⍎⊃(⎕NL ¯2)∩⊂('_'@('.'∘=))(≢root)↓url
4 | http_code ← 200 ⋄ http_msg ← 'OK'
5 | mime_type ← 'text/javascript' 'text/css' 'text/plain'⊃⍨'.js' '.css'⍳⊢/⎕nparts url
6 | update ← 1
7 | res ← hr evt pr update http_code http_msg mime_type url headers body method
8 |
--------------------------------------------------------------------------------
/APLSource/Suspend.aplf:
--------------------------------------------------------------------------------
1 | Suspend←{
2 | ⍝ ⍵: options namespace
3 | ⍝ ←: snippet to suspend hotkeys with user's hotkey or when classic interpreter window in focus
4 | 0=⍵.⎕NC'suspend':snippets.suspend
5 | txt←snippets.suspend
6 | Esc←('&'⎕R'\\&') ⋄ Join←{⊃(⊣,⍺⍺,⊢)/⍵}
7 | sus←Esc' & 'Join ⍵.suspend
8 | Replace←'%SUSPENDKEYS%'⎕R sus
9 | UnComment←~∘(';'/⍨''≢⍵.suspend)
10 | UnComment Replace snippets.suspend
11 | }
12 |
--------------------------------------------------------------------------------
/CI/publish_release.ps1:
--------------------------------------------------------------------------------
1 | # Inject patch number into version
2 | $majmin=cat "APLSource/version.apla"
3 | $patch=git rev-list --count HEAD
4 | $version=$majmin.replace('DEVELOPMENT',$patch)
5 | echo $version | Out-File "APLSource/version.apla"
6 | echo "Building workspace for APLAutoHotKey v$version"
7 | # Build workspace
8 | $env:LOAD = 'CI/Build.aplf'; &"C:\Program Files\Dyalog\Dyalog APL-64 18.2 Unicode\dyalog.exe"
9 | # Publish draft release
10 |
--------------------------------------------------------------------------------
/APLSource/Prefix.aplf:
--------------------------------------------------------------------------------
1 | Prefix←{
2 | map←⍵
3 | pk←⍺
4 | nl←⎕UCS 10
5 | r←pk,'::',nl
6 | r,←'{',nl
7 | r,←' ih := InputHook("L1 M")',nl
8 | r,←' uh.Start()',nl
9 | r,←' ih.Wait()',nl
10 | r,←' Switch ih.Input {',nl
11 |
12 | Compose←{
13 | (k a s)←⍵
14 | r←' Case "',k,'":',nl
15 | r,←' Send "',a,'":',nl
16 | }
17 |
18 | r,←,(Compose⍤1)map
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/snippets/suspend.ahk:
--------------------------------------------------------------------------------
1 |
2 | Check() {
3 | if WinActive("ahk_group Classic") || user_suspend {
4 | Suspend True
5 | } else {
6 | Suspend False
7 | }
8 | }
9 | ToggleSuspend() {
10 | global user_suspend
11 | if user_suspend {
12 | user_suspend := False
13 | } else {
14 | user_suspend := True
15 | }
16 | }
17 |
18 | SetTimer Check, 500
19 |
20 | ;#SuspendExempt
21 | ;%SUSPENDKEYS%::ToggleSuspend
22 | ;#SuspendExempt False
23 |
--------------------------------------------------------------------------------
/APLSource/HotKey.aplf:
--------------------------------------------------------------------------------
1 | HotKey←{
2 | ⍝ ⍵ ←→ kas matrix with columns (Key)(APL Glyph)(Shifted APL Glyph)
3 | ⍝ ← ←→ AutoHotKey script text
4 | nl←⎕UCS 10
5 | Compose←{
6 | (k a s)←⍵
7 | r←⍺,' & ',k,'::',nl
8 | r,←'{ if GetKeyState("Shift","P") {',nl
9 | r,←' Send "',s,'"',nl
10 | r,←'} else {',nl
11 | r,←' Send "',a,'"',nl
12 | r,←'}}',nl
13 | r
14 | }
15 | ,⍺(Compose⍤1)⍵
16 | }
17 |
--------------------------------------------------------------------------------
/GUI/classic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | APLAutoHotKey is not compatible with Dyalog Classic interpreters. 10 |
11 |12 | A standalone executable (.exe) and Unicode-compatible workspace (.dws) are available from https://github.com/Dyalog/APLAutoHotKey/releases. 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /APLSource/LocateClassicExes.aplf: -------------------------------------------------------------------------------- 1 | exe_path←LocateClassicExes;classic;dyalog;installed;reg_path 2 | ⍝ Uses APLTeam WinReg utility https://tatin.dev/v1/packages/major_versions/aplteam-WinReg 3 | dyalog←'SOFTWARE\Dyalog' 4 | :If ~WinReg.DoesKeyExist dyalog 5 | exe_path←'' 6 | :Else 7 | installed←WinReg.GetAllSubKeyNames dyalog 8 | classic←>⌿'Dyalog APL/W' 'Unicode'∘.(∨/⍷)installed ⍝ Is Dyalog APL/W but NOT Unicode 9 | reg_path←dyalog∘,¨'\',¨classic⌿installed 10 | exe_path←0~⍨WinReg.GetValue¨reg_path,¨⊂'\dyalog' 11 | exe_path,¨←⊂'\dyalog.exe' 12 | :EndIf 13 | -------------------------------------------------------------------------------- /APLSource/StartupFolder.aplf: -------------------------------------------------------------------------------- 1 | StartupFolder←{ 2 | ⍝ ⍵: options namespace 3 | ⍝ ←: options namespace with startup folder (or nothing) appended to outfile 4 | ⍝ Uses APLTeam WinReg utility https://tatin.dev/v1/packages/major_versions/aplteam-WinReg 5 | 0=⍵.⎕NC'startup':⍵ 6 | 0∊⍴⍵.startup:⍵ 7 | GetStartupDir←{ 8 | 'user'≡⍵:WinReg.GetValue'HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Startup' 9 | 'all'≡⍵:WinReg.GetValue'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Common Startup' 10 | '' 11 | } 12 | startup←GetStartupDir ⍵.startup 13 | startup OutPath ⍵ 14 | } 15 | -------------------------------------------------------------------------------- /keymaps/da_DK.tsv: -------------------------------------------------------------------------------- 1 | SC029 ⋄ ⌺ 2 | SC002 ¨ ⌶ 3 | SC003 ¯ ⍫ 4 | SC004 < ⍒ 5 | SC005 ≤ ⍋ 6 | SC006 = ⌽ 7 | SC007 ≥ ⍉ 8 | SC008 > ⊖ 9 | SC009 ≠ ⍟ 10 | SC00A ∨ ⍱ 11 | SC00B ∧ ⍲ 12 | SC00C × {!} 13 | SC00D ÷ ⌹ 14 | SC010 ? ⍰ 15 | SC011 ⍵ 16 | SC012 ∊ ⍷ 17 | SC013 ⍴ 18 | SC014 ~ ⍨ 19 | SC015 ↑ 20 | SC016 ↓ 21 | SC017 ⍳ ⍸ 22 | SC018 ○ ⍥ 23 | SC019 * ⍣ 24 | SC01A ← ⍞ 25 | SC01B → ⍬ 26 | SC01E ⍺ 27 | SC01F ⌈ 28 | SC020 ⌊ 29 | SC021 _ ⍛ 30 | SC022 ∇ ⍢ 31 | SC023 ∆ 32 | SC024 ∘ ⍤ 33 | SC025 ' ⌸ 34 | SC026 ⎕ ⌷ 35 | SC027 ⍎ ≡ 36 | SC028 ⍕ ≢ 37 | SC056 ⊢ ⊣ 38 | SC02C ⊂ ⊆ 39 | SC02D ⊃ ⊇ 40 | SC02E ∩ 41 | SC02F ∪ 42 | SC030 ⊥ 43 | SC031 ⊤ ¤ 44 | SC032 | ∥ 45 | SC033 ⍝ ⍪ 46 | SC034 ⍀ ⍙ 47 | SC035 ⌿ ⍠ 48 | -------------------------------------------------------------------------------- /keymaps/de_DE.tsv: -------------------------------------------------------------------------------- 1 | SC029 ⋄ ⌺ 2 | SC002 ¨ ⌶ 3 | SC003 ¯ ⍫ 4 | SC004 < ⍒ 5 | SC005 ≤ ⍋ 6 | SC006 = ⌽ 7 | SC007 ≥ ⍉ 8 | SC008 > ⊖ 9 | SC009 ≠ ⍟ 10 | SC00A ∨ ⍱ 11 | SC00B ∧ ⍲ 12 | SC00C × {!} 13 | SC00D ÷ ⌹ 14 | SC010 ? ⍰ 15 | SC011 ⍵ 16 | SC012 ∊ ⍷ 17 | SC013 ⍴ 18 | SC014 ~ ⍨ 19 | SC015 ↑ 20 | SC016 ↓ 21 | SC017 ⍳ ⍸ 22 | SC018 ○ ⍥ 23 | SC019 * ⍣ 24 | SC01A ← ⍞ 25 | SC01B → ⍬ 26 | SC01E ⍺ 27 | SC01F ⌈ 28 | SC020 ⌊ 29 | SC021 _ ⍛ 30 | SC022 ∇ ⍢ 31 | SC023 ∆ 32 | SC024 ∘ ⍤ 33 | SC025 ' ⌸ 34 | SC026 ⎕ ⌷ 35 | SC027 ⍎ ≡ 36 | SC028 ⍕ ≢ 37 | SC056 ⊢ ⊣ 38 | SC02C ⊂ ⊆ 39 | SC02D ⊃ ⊇ 40 | SC02E ∩ 41 | SC02F ∪ 42 | SC030 ⊥ 43 | SC031 ⊤ ¤ 44 | SC032 | ∥ 45 | SC033 ⍝ ⍪ 46 | SC034 ⍀ ⍙ 47 | SC035 ⌿ ⍠ 48 | -------------------------------------------------------------------------------- /APLSource/GUI/HandleWSReceive.aplf: -------------------------------------------------------------------------------- 1 | req←HandleWSReceive req;gui;evt;data;en;msg;opts;os;as;script;nl;number;message;filename;dir;id;FileName 2 | (gui evt id data en msg)←req 3 | :Trap ∊dev↓0(400 19) 4 | opts←0 ⎕JSON data 5 | as←##.ahk_shifts.⎕NL ¯2 ⍝ Available keys for shift and suspend 6 | opts←as Shifts opts 7 | opts←as Suspend opts 8 | opts←opts.outpath ##.OutPath opts 9 | opts←##.StartupFolder opts 10 | (number message)←##.MakeScript opts 11 | :Case 19 12 | (number message)←1('You do not have permission to write to this directoryGenerate AutoHotKey scripts for APL glyph keyboard input
10 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /scripts/CapsLock-en_UK.ahk: -------------------------------------------------------------------------------- 1 | #SuspendExempt 2 | LControl & Space::Suspend 3 | #SuspendExempt False 4 | *CapsLock::return 5 | CapsLock & Space::Send " " 6 | CapsLock & `:: 7 | { if GetKeyState("Shift","P") { 8 | Send "⌺" 9 | } else { 10 | Send "⋄" 11 | }} 12 | CapsLock & 1:: 13 | { if GetKeyState("Shift","P") { 14 | Send "⌶" 15 | } else { 16 | Send "¨" 17 | }} 18 | CapsLock & 2:: 19 | { if GetKeyState("Shift","P") { 20 | Send "⍫" 21 | } else { 22 | Send "¯" 23 | }} 24 | CapsLock & 3:: 25 | { if GetKeyState("Shift","P") { 26 | Send "⍒" 27 | } else { 28 | Send "<" 29 | }} 30 | CapsLock & 4:: 31 | { if GetKeyState("Shift","P") { 32 | Send "⍋" 33 | } else { 34 | Send "≤" 35 | }} 36 | CapsLock & =:: 37 | { if GetKeyState("Shift","P") { 38 | Send "⌹" 39 | } else { 40 | Send "÷" 41 | }} 42 | CapsLock & 5:: 43 | { if GetKeyState("Shift","P") { 44 | Send "⌽" 45 | } else { 46 | Send "=" 47 | }} 48 | CapsLock & 6:: 49 | { if GetKeyState("Shift","P") { 50 | Send "⍉" 51 | } else { 52 | Send "≥" 53 | }} 54 | CapsLock & 7:: 55 | { if GetKeyState("Shift","P") { 56 | Send "⊖" 57 | } else { 58 | Send ">" 59 | }} 60 | CapsLock & 8:: 61 | { if GetKeyState("Shift","P") { 62 | Send "⍟" 63 | } else { 64 | Send "≠" 65 | }} 66 | CapsLock & 9:: 67 | { if GetKeyState("Shift","P") { 68 | Send "⍱" 69 | } else { 70 | Send "∨" 71 | }} 72 | CapsLock & 0:: 73 | { if GetKeyState("Shift","P") { 74 | Send "⍲" 75 | } else { 76 | Send "∧" 77 | }} 78 | CapsLock & -:: 79 | { if GetKeyState("Shift","P") { 80 | Send "{!}" 81 | } else { 82 | Send "×" 83 | }} 84 | CapsLock & q:: 85 | { if GetKeyState("Shift","P") { 86 | Send "⍰" 87 | } else { 88 | Send "?" 89 | }} 90 | CapsLock & w:: 91 | { if GetKeyState("Shift","P") { 92 | Send "⍹" 93 | } else { 94 | Send "⍵" 95 | }} 96 | CapsLock & e:: 97 | { if GetKeyState("Shift","P") { 98 | Send "⍷" 99 | } else { 100 | Send "∊" 101 | }} 102 | CapsLock & r:: 103 | { if GetKeyState("Shift","P") { 104 | Send " " 105 | } else { 106 | Send "⍴" 107 | }} 108 | CapsLock & t:: 109 | { if GetKeyState("Shift","P") { 110 | Send "⍨" 111 | } else { 112 | Send "~" 113 | }} 114 | CapsLock & y:: 115 | { if GetKeyState("Shift","P") { 116 | Send " " 117 | } else { 118 | Send "↑" 119 | }} 120 | CapsLock & u:: 121 | { if GetKeyState("Shift","P") { 122 | Send " " 123 | } else { 124 | Send "↓" 125 | }} 126 | CapsLock & i:: 127 | { if GetKeyState("Shift","P") { 128 | Send "⍸" 129 | } else { 130 | Send "⍳" 131 | }} 132 | CapsLock & o:: 133 | { if GetKeyState("Shift","P") { 134 | Send "⍥" 135 | } else { 136 | Send "○" 137 | }} 138 | CapsLock & p:: 139 | { if GetKeyState("Shift","P") { 140 | Send "⍣" 141 | } else { 142 | Send "*" 143 | }} 144 | CapsLock & [:: 145 | { if GetKeyState("Shift","P") { 146 | Send "⍞" 147 | } else { 148 | Send "←" 149 | }} 150 | CapsLock & ]:: 151 | { if GetKeyState("Shift","P") { 152 | Send "⍬" 153 | } else { 154 | Send "→" 155 | }} 156 | CapsLock & a:: 157 | { if GetKeyState("Shift","P") { 158 | Send "⍶" 159 | } else { 160 | Send "⍺" 161 | }} 162 | CapsLock & s:: 163 | { if GetKeyState("Shift","P") { 164 | Send " " 165 | } else { 166 | Send "⌈" 167 | }} 168 | CapsLock & d:: 169 | { if GetKeyState("Shift","P") { 170 | Send " " 171 | } else { 172 | Send "⌊" 173 | }} 174 | CapsLock & f:: 175 | { if GetKeyState("Shift","P") { 176 | Send "⍛" 177 | } else { 178 | Send "_" 179 | }} 180 | CapsLock & g:: 181 | { if GetKeyState("Shift","P") { 182 | Send "⍢" 183 | } else { 184 | Send "∇" 185 | }} 186 | CapsLock & h:: 187 | { if GetKeyState("Shift","P") { 188 | Send " " 189 | } else { 190 | Send "∆" 191 | }} 192 | CapsLock & j:: 193 | { if GetKeyState("Shift","P") { 194 | Send "⍤" 195 | } else { 196 | Send "∘" 197 | }} 198 | CapsLock & k:: 199 | { if GetKeyState("Shift","P") { 200 | Send "⌸" 201 | } else { 202 | Send "'" 203 | }} 204 | CapsLock & l:: 205 | { if GetKeyState("Shift","P") { 206 | Send "⌷" 207 | } else { 208 | Send "⎕" 209 | }} 210 | CapsLock & `;:: 211 | { if GetKeyState("Shift","P") { 212 | Send "≡" 213 | } else { 214 | Send "⍎" 215 | }} 216 | CapsLock & ':: 217 | { if GetKeyState("Shift","P") { 218 | Send "≢" 219 | } else { 220 | Send "⍕" 221 | }} 222 | CapsLock & #:: 223 | { if GetKeyState("Shift","P") { 224 | Send "⊣" 225 | } else { 226 | Send "⊢" 227 | }} 228 | CapsLock & \:: 229 | { if GetKeyState("Shift","P") { 230 | Send "⊣" 231 | } else { 232 | Send "⊢" 233 | }} 234 | CapsLock & z:: 235 | { if GetKeyState("Shift","P") { 236 | Send "⊆" 237 | } else { 238 | Send "⊂" 239 | }} 240 | CapsLock & x:: 241 | { if GetKeyState("Shift","P") { 242 | Send "⊇" 243 | } else { 244 | Send "⊃" 245 | }} 246 | CapsLock & c:: 247 | { if GetKeyState("Shift","P") { 248 | Send " " 249 | } else { 250 | Send "∩" 251 | }} 252 | CapsLock & v:: 253 | { if GetKeyState("Shift","P") { 254 | Send " " 255 | } else { 256 | Send "∪" 257 | }} 258 | CapsLock & b:: 259 | { if GetKeyState("Shift","P") { 260 | Send " " 261 | } else { 262 | Send "⊥" 263 | }} 264 | CapsLock & n:: 265 | { if GetKeyState("Shift","P") { 266 | Send "¤" 267 | } else { 268 | Send "⊤" 269 | }} 270 | CapsLock & m:: 271 | { if GetKeyState("Shift","P") { 272 | Send "∥" 273 | } else { 274 | Send "|" 275 | }} 276 | CapsLock & ,:: 277 | { if GetKeyState("Shift","P") { 278 | Send "⍪" 279 | } else { 280 | Send "⍝" 281 | }} 282 | CapsLock & .:: 283 | { if GetKeyState("Shift","P") { 284 | Send "⍙" 285 | } else { 286 | Send "⍀" 287 | }} 288 | CapsLock & /:: 289 | { if GetKeyState("Shift","P") { 290 | Send "⍠" 291 | } else { 292 | Send "⌿" 293 | }} 294 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # APLAutoHotKey 2 | This is an application to generate AutoHotKey scripts to enable keyboard input of APL glyphs on Microsoft Windows. 3 | 4 | [AutoHotKey](https://www.autohotkey.com/) is an automation scripting software for Microsoft Windows. You can map keyboard shortcuts (or "hotkeys") to actions, including the output of characters. This program presents a form of options and generates an AutoHotKey script based on the user's choices. 5 | 6 | > AutoHotKey version 2 must be installed in order to use the scripts generated by APLAutoHotKey. 7 | 8 | - [Usage](#usage) 9 | - [GUI](#gui) 10 | - [API](#api) 11 | - [Options](#options) 12 | - [Layouts](#layouts) 13 | - [Shifting key](#shifting-key) 14 | - [Suspend shortcut](#suspend-shortcut) 15 | - [Launch at startup](#launch-at-startup) 16 | - [Dyalog Classic Edition](#dyalog-classic-edition) 17 | - [Development](#development) 18 | - [Mapping dead keys](#mapping-dead-keys) 19 | 20 | ## Usage 21 | 22 | ### GUI (normal usage) 23 | 1. Download and install [AutoHotKey v2](https://www.autohotkey.com/) 24 | 25 | 2. Download the [latest release workspace](https://github.com/Dyalog/APLAutoHotKey/releases), **APLAutoHotKey.dws**, from the releases page. `)LOAD` or double-click on the workspace file to launch the GUI application. 26 | 27 | 3. Choose your locale/layout, shifting key, optional suspend shortcut and enter the path to the folder in which to save the resulting script. Then click the **Generate Script** button. 28 | 29 | > The script name will be based on the options provided and it will have a file extension of **.ahk**. For example, `APL-en_GB-CapsLockRCtrl.ahk`. 30 | 31 | 4. Double click on or otherwise run the **.ahk** script file to start the script and enable APL keyboard input using your chosen options. 32 | 33 | ### API 34 | The following demonstrates how to use the API to generate scripts programmatically. 35 | 36 | 1. Import APLAutoHotKey: 37 | 38 | ``` 39 | ]Get -u https://github.com/rikedyp/APLAutoHotKey/releases/download/v0.1.0/APLAutoHotKey.dws 40 | ``` 41 | 42 | > `]Get` can accept a local file path or the URL of a released .dws workspace 43 | 44 | 2. Set options 45 | 46 | ``` 47 | opt←⎕NS'' 48 | opt.shift←'CapsLock' 'RAlt' 49 | opt.locale←'en_GB' 50 | opt.outfile←'/tmp/APL-en_GB-CapsLockAlt.ahk' 51 | ``` 52 | 53 | 3. Generate and save the script 54 | 55 | ``` 56 | APLAutoHotKey.MakeScript opt 57 | ┌─┬──────────────────────────────────────────────────┐ 58 | │0│Saved: /tmp/APL-en_GB-CapsLockAlt.ahk (9404 bytes)│ 59 | └─┴──────────────────────────────────────────────────┘ 60 | ``` 61 | 62 | 4. Double click on or otherwise run the **.ahk** script file to start the script and enable APL keyboard input using your chosen options. 63 | 64 | ## Options 65 | 66 | ### Layouts 67 | Each script is based on a single locale. 68 | 69 | |locale|code| 70 | |---|---| 71 | |English (UK)|en_GB| 72 | |English(US)|en_US| 73 | |Danish|da_DK| 74 | |Finnish (Finland)|fi_FI| 75 | |French (France)|fr_FR| 76 | |German (Germany)|de_DE| 77 | |Italian (Italy)|it_IT| 78 | |Spanish (Spain)|es_ES| 79 | |Swedish (Sweden)|sv_SE| 80 | 81 | > Other layouts can be supported on request, or generated by the user if they create the appropriate key map. See the `keymaps` folder for existing keymap tab separated values (.tsv) files. 82 | 83 | ### Shifting key 84 | This is a key which, while pressed, enables the input of APL glyphs. For example, Ctrl + e produces `∊`. 85 | 86 | Available shifts are listed in the `ahk_shifts` namespace. 87 | 88 | ``` 89 | APLAutoHotKey.ahk_shifts.⎕NL¯2 90 | ┌───┬────────┬────┬────┬─────┬────┬────┬─────┬────┐ 91 | │Alt│CapsLock│Ctrl│LAlt│LCtrl│LWin│RAlt│RCtrl│RWin│ 92 | └───┴────────┴────┴────┴─────┴────┴────┴─────┴────┘ 93 | ``` 94 | 95 | > The AltGr key sends a Left Control + Right Alt signal. Therefore, using the **Alt** (both), **RAlt**, **Ctrl** (both) or **LCtrl** shifting key options can affect the behaviour of the AltGr key. 96 | 97 | ### Suspend shortcut 98 | The user may specify a key combination to toggle suspension of hotkeys, which may be useful if an application uses keyboard shortcuts with which the hotkeys interfere. 99 | 100 | ### Launch at startup 101 | The script can be made to launch at startup by placing it into the user's startup folder or the common startup folder. 102 | 103 | The startup folders on Microsoft Windows can be found by entering `shell:startup` (this user) or `shell:common startup` (all users) into the **Run** app (Win+R). 104 | 105 | ## Dyalog Classic Edition 106 | When generating a script, APLAutoHotKey checks the Microsoft Windows registry for installations of Dyalog Classic interpreters, and adds the paths to their executable files to the "Classic" group. When a Classic window is active, hotkeys suspend to allow the Classic application to handle keyboard input. 107 | 108 | If a user installs a Dyalog Classic interpreter after generating a script with APLAutoHotKey, then they can either rebuild their script using APLAutoHotKey, or add the path to the executable file in an additional `GroupAdd` line in their script. 109 | 110 | ## Development 111 | This application is developed as a [Cider](https://github.com/aplteam/Cider) project. 112 | 113 | Open the project: 114 | 115 | ``` 116 | ]CIDER.OpenProject /path/to/APLAutoHotKey 117 | ``` 118 | 119 | Build a new release workspace: 120 | 121 | 1. In a bash shell in the folder of this cloned repository: 122 | 123 | ``` 124 | ./CI/Inject-Version.sh 125 | ``` 126 | 127 | 2. In Dyalog 128 | 129 | ``` 130 | ]DBuild APLAutoHotKey.dyalogbuild 131 | ``` 132 | 133 | ### Mapping dead keys 134 | Some keys do not immediately produce output when pressed, but will affect the next key press usually by adding an accent to a letter. These are known as "dead keys". 135 | 136 | In AutoHotKey **.ahk** scripts, you may use a Unicode character directly to indicate it as a HotKey meaning that some action is taken when that character is output by the keyboard. For dead keys, you should use the *scan code* corresponding to that key. 137 | 138 | To find the scan code for a particular key, start AutoHotKey by double-clicking any script file. A green "H" icon will appear in the system tray. **Right click** the system tray icon → click **Open** → click the **View** menu item and then click **Key history and script info**. Press the key and then press F5. The 2nd most recent key in the list should be the key you just pressed, and the 3-digit alphanumeric code in the 2nd column is the scan code. 139 | -------------------------------------------------------------------------------- /keymaps/keymaps.md: -------------------------------------------------------------------------------- 1 | # Keymap diagrams 2 | 3 | ## fi_FI 4 | 5 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 6 | │ ⌺ │! ⌶ │" ⍫ │# ⍒ │⊢ ⍋ │% ⌽ │& ⍉ │/ ⊖ │( ⍟ │) ⍱ │= ⍲ │? ! │` ⌹ │Backspace│ 7 | │§ ⋄ │1 ¨ │2 ¯ │3 < │4 ≤ │5 = │6 ≥ │7 > │8 ≠ │9 ∨ │0 ∧ │+ × │' ÷ │ │ 8 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 9 | │Tab │Q ⍰ │W │E ⍷ │R │T ⍨ │Y │U │I ⍸ │O ⍥ │P ⍣ │Å ⍞ │^ ⍬ │Enter │ 10 | │ │q ? │w ⍵ │e ∊ │r ⍴ │t ~ │y ↑ │u ↓ │i ⍳ │o ○ │p * │å ← │¨ → │ │ 11 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 12 | │Caps │A │S │D │F ⍛ │G ⍢ │H ⍙ │J ⍤ │K ⌸ │L ⌷ │Ö [ │Ä ] │* ⍷ │ │ 13 | │Lock │a ⍺ │s ⌈ │d ⌊ │f _ │g ∇ │h ∆ │j ∘ │k ' │l ⎕ │ö ⍎ │ä ⍕ │' ≡ │ │ 14 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 15 | │Shift │> ⊣ │Z ⊆ │X ⊇ │C │V │B │N ¤ │M ∥ │; ⍪ │: ≢ │_ ⍠ │Shift │ 16 | │ │< ⊢ │z ⊂ │x ⊃ │c ∩ │v ∪ │b ⊥ │n ⊤ │m | │, ⍝ │. ⍀ │- ⌿ │ │ 17 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 18 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 19 | │ │ │ │ │ │ │ │ │ 20 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 21 | Additional characters are accessed using Alt Gr: 22 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 23 | │ │! │" │# │⊢ │% │& │/ │( │) │= │? │ │Backspace│ 24 | │§ │1 │2 @ │3 £ │4 $ │5 € │6 │7 { │8 [ │9 ] │0 } │+ \ │' ´ │ │ 25 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 26 | │Tab │Q │W │E │R │T │Y │U │I │O │P │Å │^ │Enter │ 27 | │ │q │w │e € │r │t │y │u │i │o │p │å │¨ ~ │ │ 28 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 29 | │Caps │A │S │D │F │G │H │J │K │L │Ö │Ä Æ │* ≢ │ │ 30 | │Lock │a │s │d │f │g │h │j │k │l │ö │ä │' ⍣ │ │ 31 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 32 | │Shift │> │Z │X │C │V │B │N │M │; │: │_ │Shift │ 33 | │ │< | │z │x │c │v │b │n │m µ │, │. │- │ │ 34 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 35 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 36 | │ │ │ │ │ │ │ │ │ 37 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 38 | More additional characters are available using Alt Gr on the Finnish with Sami keyboard: 39 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 40 | │ │! │" │# │⊢ │% │& │/ │( │) │= │? │ │Backspace│ 41 | │§ │1 │2 @ │3 £ │4 $ │5 € │6 │7 { │8 [ │9 ] │0 } │+ \ │' ´ │ │ 42 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 43 | │Tab │Q  │W │E │R │T Ŧ │Y │U │I Ï │O Õ │P │Å │^ │Enter │ 44 | │ │q â │w │e € │r │t ŧ │y │u │i ï │o õ │p │å │¨ ~ │ │ 45 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 46 | │Caps │A Á │S Š │D Đ │F Ǥ │G Ǧ │H Ȟ │J │K Ǩ │L │Ö Ø │Ä Æ │* │ │ 47 | │Lock │a á │s š │d đ │f ǥ │g ǧ │h ȟ │j │k ǩ │l │ö ø │ä æ │' │ │ 48 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 49 | │Shift │> │Z Ž │X │C Č │V Ǯ │B Ʒ │N Ŋ │M │; │: │_ │Shift │ 50 | │ │< | │z ž │x │c č │v ǯ │b ʒ │n ŋ │m µ │, │. │- │ │ 51 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 52 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 53 | │ │ │ │ │ │ │ │ │ 54 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 55 | 56 | ## fr_FR 57 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 58 | │ ⌺ │1 ⌶ │2 ⍫ │3 ⍒ │4 ⍋ │5 ⌽ │6 ⍉ │7 ⊖ │8 ⍟ │9 ⍱ │0 ⍲ │° ! │+ ⌹ │Backspace│ 59 | │² ⋄ │& ¨ │é ¯ │" < │' ≤ │( = │- ≥ │è > │_ ≠ │ç ∨ │à ∧ │) × │= ÷ │ │ 60 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 61 | │Tab │A ⍰ │Z │E ⍷ │R │T ⍨ │Y │U │I ⍸ │O ⍥ │P ⍣ │¨ ⍞ │£ ⍬ │Enter │ 62 | │ │a ? │z ⍵ │e ∊ │r ⍴ │t ~ │y ↑ │u ↓ │i ⍳ │o ○ │p * │^ ← │$ → │ │ 63 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 64 | │Caps │Q │S │D │F ⍛ │G ⍢ │H ⍙ │J ⍤ │K ⌸ │L ⌷ │M ≡ │% ≢ │μ │ │ 65 | │Lock │q ⍺ │s ⌈ │d ⌊ │f _ │g ∇ │h ∆ │j ∘ │k ' │l ⎕ │m ⍎ │ù ⍕ │* # │ │ 66 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 67 | │Shift │> ⊣ │W ⊆ │X ⊇ │C │V │B │N ¤ │? ∥ │. ⍪ │/ ⍙ │§ ⍠ │Shift │ 68 | │ │< ⊢ │w ⊂ │x ⊃ │c ∩ │v ∪ │b ⊥ │n ⊤ │, | │; ⍝ │: ⍀ │! ⌿ │ │ 69 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 70 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 71 | │ │ │ │ │ │ │ │ │ 72 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 73 | Additional characters on the front of keycaps are accessed using Alt Gr: 74 | ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ 75 | │2 ⍫ ││3 ⍒ ││4 ⍋ ││5 ⌽ ││6 ⍉ ││7 ⊖ ││8 ⍟ ││9 ⍱ ││0 ⍲ ││° ││+ ⌹ ││E ⍷ │ 76 | │é ¯ ││" < ││' ≤ ││( = ││- ≥ ││è > ││_ ≠ ││ç ∨ ││à ∧ ││) × ││= ÷ ││e ∊ │ 77 | ├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤ 78 | │ ~ ││ # ││ { ││ [ ││ ¦ ││ ` ││ \ ││ ^ ││ @ ││ ] ││ } ││ € │ 79 | └────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘ 80 | 81 | 82 | 83 | ## de_DE 84 | This version is based on the layout of the Dyalog hardware keyboards 85 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 86 | │° ⌺ │! ⌶ │" ⍫ │§ ⍒ │$ ⍋ │% ⌽ │& ⍉ │/ ⊖ │( ⍟ │) ⍱ │= ⍲ │? ! │` ⌹ │Backspace│ 87 | │^ ⋄ │1 ¨ │2 ¯ │3 < │4 ≤ │5 = │6 ≥ │7 > │8 ≠ │9 ∨ │0 ∧ │ß × │´ ÷ │ │ 88 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 89 | │Tab │Q ⍰ │W │E ⍷ │R │T ⍨ │Z │U │I ⍸ │O ⍥ │P ⍣ │Ü ⍞ │* ⍬ │Enter │ 90 | │ │q ? │w ⍵ │e ∊ │r ⍴ │t ~ │z ↑ │u ↓ │i ⍳ │o ○ │p * │ü ← │+ → │ │ 91 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 92 | │Caps │A │S │D │F ⍛ │G ⍢ │H │J ⍤ │K ⌸ │L ⌷ │Ö ≡ │Ä ≢ │' │ │ 93 | │Lock │a ⍺ │s ⌈ │d ⌊ │f _ │g ∇ │h ∆ │j ∘ │k ' │l ⎕ │ö ⍎ │ä ⍕ │# │ │ 94 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 95 | │Shift │> ⊣ │Y ⊆ │X ⊇ │C │V │B │N ¤ │M ∥ │; ⍪ │: ⍙ │_ ⍠ │Shift │ 96 | │ │< ⊢ │y ⊂ │x ⊃ │c ∩ │v ∪ │b ⊥ │n ⊤ │m | │, ⍝ │. ⍀ │- ⌿ │ │ 97 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 98 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 99 | │ │ │ │ │ │ │ │ │ 100 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 101 | Additional characters on the front of keycaps are accessed using Alt Gr: 102 | ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ 103 | │" ⍫ ││§ ⍒ ││/ ⊖ ││( ⍟ ││) ⍱ ││= ⍲ ││? ! ││Q ││E ⍷ ││* ⍬ ││> ⊣ ││M │ 104 | │2 ¯ ││3 < ││7 > ││8 ≠ ││9 ∨ ││0 ∧ ││ß × ││q ? ││e ∊ ││+ → ││< ⊢ ││m | │ 105 | ├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤├────┤ 106 | │² ││³ ││{ ││[ ││] ││} ││\ ││@ ││€ ││~ ││| ││μ │ 107 | └────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘ 108 | 109 | ## it_IT 110 | ``` 111 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 112 | │| ⌺ │! ⌶ │" ⍫ │£ ⍒ │$ ⍋ │% ⌽ │& ⍉ │/ ⊖ │( ⍟ │) ⍱ │= ⍲ │? ! │^ ⌹ │Backspace│ 113 | │\ ⋄ │1 ¨ │2 ¯ │3 < │4 ≤ │5 = │6 ≥ │7 > │8 ≠ │9 ∨ │0 ∧ │' × │ì ÷ │ │ 114 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 115 | │Tab │Q ⍰ │W │E ⍷ │R │T ⍨ │Y │U │I ⍸ │O ⍥ │P ⍣ │é ⍞ │* ⍬ │Enter │ 116 | │ │q ? │w ⍵ │e ∊ │r ⍴ │t ~ │y ↑ │u ↓ │i ⍳ │o ○ │p * │è ← │+ → │ │ 117 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 118 | │Caps │A │S │D │F │G │H ⍙ │J ⍤ │K ⌸ │L ⌷ │ç ≡ │° ≢ │§ │ │ 119 | │Lock │a ⍺ │s ⌈ │d ⌊ │f _ │g ∇ │h ∆ │j ∘ │k ' │l ⎕ │ò ⍎ │à ⍕ │ù │ │ 120 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 121 | │Shift │> ⊣ │Z ⊆ │X ⊇ │C │V │B │N ¤ │M ∥ │; ⍪ │: ⍙ │_ ⍠ │Shift │ 122 | │ │< ⊢ │z ⊂ │x ⊃ │c ∩ │v ∪ │b ⊥ │n ⊤ │m | │, ⍝ │. ⍀ │- ⌿ │ │ 123 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 124 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 125 | │ │ │ │ │ │ │ │ │ 126 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 127 | Additional characters on the front of keycaps are accessed using Alt Gr and Alt Gr+Shift 128 | ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ 129 | │% ⌽ ││E ⍷ ││é ⍞ ││* ⍬ ││ç ≡ ││° ≢ │ 130 | │5 = ││e ∊ ││è ← ││+ → ││ò ⍎ ││à ⍕ │ 131 | ├────┤├────┤├────┤├────┤├────┤├────┤ 132 | │€ ││€ ││[ { ││] } ││@ ││# │ 133 | └────┘└────┘└────┘└────┘└────┘└────┘ 134 | ``` 135 | 136 | ## sv_SE 137 | ``` 138 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ 139 | │½ ⌺ │! ⌶ │" ⍫ │# ⍒ │¤ ⍋ │% ⌽ │& ⍉ │/ ⊖ │( ⍟ │) ⍱ │= ⍲ │? ! │` ⌹ │Backspace│ 140 | │§ ⋄ │1 ¨ │2 ¯ │3 < │4 ≤ │5 = │6 ≥ │7 > │8 ≠ │9 ∨ │0 ∧ │+ × │' ÷ │ │ 141 | ├────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬──────┤ 142 | │Tab │Q ⍰ │W │E ⍷ │R │T ⍨ │Y │U │I ⍸ │O ⍥ │P ⍣ │Å ⍞ │^ ⍬ │Enter │ 143 | │ │q ? │w ⍵ │e ∊ │r ⍴ │t ~ │y ↑ │u ↓ │i ⍳ │o ○ │p * │å ← │¨ → │ │ 144 | ├───────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ 145 | │Caps │A │S │D │F ⍛ │G ⍢ │H ⍙ │J ⍤ │K ⌸ │L ⌷ │Ö [ │Ä ] │* ⍷ │ │ 146 | │Lock │a ⍺ │s ⌈ │d ⌊ │f _ │g ∇ │h ∆ │j ∘ │k ' │l ⎕ │ö ⍎ │ä ⍕ │' ≡ │ │ 147 | ├──────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴─────┤ 148 | │Shift │> ⊣ │Z ⊆ │X ⊇ │C │V │B │N ¤ │M ∥ │; ⍪ │: ≢ │_ ⍠ │Shift │ 149 | │ │< ⊢ │z ⊂ │x ⊃ │c ∩ │v ∪ │b ⊥ │n ⊤ │m | │, ⍝ │. ⍀ │- ⌿ │ │ 150 | ├──────┴┬───┴─┬──┴───┬┴────┴────┴────┴────┴────┴┬───┴──┬─┴────┼─────┬──────┤ 151 | │Ctrl │Win │Alt │ │Alt Gr│Win │Menu │Ctrl │ 152 | │ │ │ │ │ │ │ │ │ 153 | └───────┴─────┴──────┴──────────────────────────┴──────┴──────┴─────┴──────┘ 154 | Additional characters are accessed using Alt Gr: 155 | ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ 156 | │" │# │¤ │% │/ │( │) │= │? │E │> │M │ 157 | │2 @ │3 £ │4 $ │5 € │7 { │8 [ │9 ] │0 } │+ \ │e € │< | │m µ │ 158 | └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ 159 | ``` 160 | -------------------------------------------------------------------------------- /apl-packages/APLTreeUtils2.aplc: -------------------------------------------------------------------------------- 1 | :Class APLTreeUtils2 2 | ⍝ This is the predecessor of the namespace `APLTreeUtils`.\\ 3 | ⍝ While `APLTreeUtils` was a namespace scipt designed to be included into pretty much every member of the 4 | ⍝ APLTree library, `APLTreeUtils2` is a class with shared methods. You are supposed to call those methods. 5 | ⍝ This has some major advantageous over the old approach: 6 | ⍝ * It's possible to add new functins to `APLTreeUtils`. With the old approach there was always the possibility 7 | ⍝ of a name clash, so adding new function was practically impossible. 8 | ⍝ * The sequence of fixing does not matter (though with lazy fixing that should not be an issue anymore anyway, 9 | ⍝ but at the time of writing it still is). 10 | ⍝ * Over the years we have seen rare `⎕IO` and `⎕ML` issues with `:Include`. We just avoid the possibility now.\\ 11 | ⍝ For a list with the precise differences between `APLTreeUtils` and `APLTreeUtils2` see the project ReadMe on 12 | ⍝ GitHub. Note that there are many. Most importantly, `APLTreeUtils2` requires Dyalog 18.0. 13 | ⍝ Kai Jaeger - APL Team Ltd.\\ 14 | ⍝ Homepage: