Skip to content

Commit 5f43abd

Browse files
author
epriestley
committed
Add a {key ..} Remarkup rule for discussing keystrokes
Summary: Ruleset for styles in D16506. Test Plan: {F1803883} Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D16510
1 parent b7e5187 commit 5f43abd

File tree

6 files changed

+262
-3
lines changed

6 files changed

+262
-3
lines changed

resources/celerity/map.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
return array(
99
'names' => array(
10-
'core.pkg.css' => '6791587e',
10+
'core.pkg.css' => 'd28c0515',
1111
'core.pkg.js' => '1d376fa9',
1212
'darkconsole.pkg.js' => 'e7393ebb',
1313
'differential.pkg.css' => '3fb7f532',
@@ -105,7 +105,7 @@
105105
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
106106
'rsrc/css/application/uiexample/example.css' => '528b19de',
107107
'rsrc/css/core/core.css' => 'd0801452',
108-
'rsrc/css/core/remarkup.css' => '9905d6c4',
108+
'rsrc/css/core/remarkup.css' => 'cd912f2c',
109109
'rsrc/css/core/syntax.css' => '769d3498',
110110
'rsrc/css/core/z-index.css' => '2b01a823',
111111
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
@@ -792,7 +792,7 @@
792792
'phabricator-object-selector-css' => '85ee8ce6',
793793
'phabricator-phtize' => 'd254d646',
794794
'phabricator-prefab' => 'cfd23f37',
795-
'phabricator-remarkup-css' => '9905d6c4',
795+
'phabricator-remarkup-css' => 'cd912f2c',
796796
'phabricator-search-results-css' => '7dea472c',
797797
'phabricator-shaped-request' => '7cbe244b',
798798
'phabricator-slowvote-css' => 'a94b7230',

src/__phutil_library_map__.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,6 +2707,7 @@
27072707
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
27082708
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
27092709
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
2710+
'PhabricatorKeyboardRemarkupRule' => 'infrastructure/markup/rule/PhabricatorKeyboardRemarkupRule.php',
27102711
'PhabricatorKeyring' => 'applications/files/keyring/PhabricatorKeyring.php',
27112712
'PhabricatorKeyringConfigOptionType' => 'applications/files/keyring/PhabricatorKeyringConfigOptionType.php',
27122713
'PhabricatorLDAPAuthProvider' => 'applications/auth/provider/PhabricatorLDAPAuthProvider.php',
@@ -7532,6 +7533,7 @@
75327533
'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType',
75337534
'PhabricatorJumpNavHandler' => 'Phobject',
75347535
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
7536+
'PhabricatorKeyboardRemarkupRule' => 'PhutilRemarkupRule',
75357537
'PhabricatorKeyring' => 'Phobject',
75367538
'PhabricatorKeyringConfigOptionType' => 'PhabricatorConfigJSONOptionType',
75377539
'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider',

src/docs/user/userguide/remarkup.diviner

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,32 @@ In general:
688688
- The `type` option can be set to `instructions` to indicate that an element
689689
is asking the user to make a choice or follow specific instructions.
690690

691+
Keystrokes
692+
==========
693+
694+
You can use `{key ...}` to render a stylized keystroke. For example, this:
695+
696+
```
697+
Press {key M} to view the starmap.
698+
```
699+
700+
...renders this:
701+
702+
> Press {key M} to view the starmap.
703+
704+
You can also render sequences with modifier keys. This:
705+
706+
```
707+
Use {key command option shift 3} to take a screenshot.
708+
Press {key down down-right right LP} to activate the hadoken technique.
709+
```
710+
711+
...renders this:
712+
713+
> Use {key command option shift 3} to take a screenshot.
714+
> Press {key down down-right right LP} to activate the hadoken technique.
715+
716+
691717
= Fullscreen Mode =
692718

693719
Remarkup editors provide a fullscreen composition mode. This can make it easier

src/infrastructure/markup/PhabricatorMarkupEngine.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ public static function newMarkupEngine(array $options) {
505505

506506
$rules[] = new PhutilRemarkupDocumentLinkRule();
507507
$rules[] = new PhabricatorNavigationRemarkupRule();
508+
$rules[] = new PhabricatorKeyboardRemarkupRule();
508509

509510
if ($options['youtube']) {
510511
$rules[] = new PhabricatorYoutubeRemarkupRule();
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
<?php
2+
3+
final class PhabricatorKeyboardRemarkupRule extends PhutilRemarkupRule {
4+
5+
public function getPriority() {
6+
return 200.0;
7+
}
8+
9+
public function apply($text) {
10+
return preg_replace_callback(
11+
'@{key\b((?:[^}\\\\]+|\\\\.)*)}@m',
12+
array($this, 'markupKeystrokes'),
13+
$text);
14+
}
15+
16+
public function markupKeystrokes(array $matches) {
17+
if (!$this->isFlatText($matches[0])) {
18+
return $matches[0];
19+
}
20+
21+
$keys = explode(' ', $matches[1]);
22+
foreach ($keys as $k => $v) {
23+
$v = trim($v, " \n");
24+
$v = preg_replace('/\\\\(.)/', '\\1', $v);
25+
if (!strlen($v)) {
26+
unset($keys[$k]);
27+
continue;
28+
}
29+
$keys[$k] = $v;
30+
}
31+
32+
$special = array(
33+
array(
34+
'name' => pht('Command'),
35+
'symbol' => "\xE2\x8C\x98",
36+
'aliases' => array(
37+
'cmd',
38+
'command',
39+
),
40+
),
41+
array(
42+
'name' => pht('Option'),
43+
'symbol' => "\xE2\x8C\xA5",
44+
'aliases' => array(
45+
'opt',
46+
'option',
47+
),
48+
),
49+
array(
50+
'name' => pht('Shift'),
51+
'symbol' => "\xE2\x87\xA7",
52+
'aliases' => array(
53+
'shift',
54+
),
55+
),
56+
array(
57+
'name' => pht('Escape'),
58+
'symbol' => "\xE2\x8E\x8B",
59+
'aliases' => array(
60+
'esc',
61+
'escape',
62+
),
63+
),
64+
array(
65+
'name' => pht('Up'),
66+
'symbol' => "\xE2\x86\x91",
67+
'heavy' => "\xE2\xAC\x86",
68+
'aliases' => array(
69+
'up',
70+
'arrow-up',
71+
'up-arrow',
72+
'north',
73+
),
74+
),
75+
array(
76+
'name' => pht('Tab'),
77+
'symbol' => "\xE2\x87\xA5",
78+
'aliases' => array(
79+
'tab',
80+
),
81+
),
82+
array(
83+
'name' => pht('Right'),
84+
'symbol' => "\xE2\x86\x92",
85+
'heavy' => "\xE2\x9E\xA1",
86+
'aliases' => array(
87+
'right',
88+
'right-arrow',
89+
'arrow-right',
90+
'east',
91+
),
92+
),
93+
array(
94+
'name' => pht('Left'),
95+
'symbol' => "\xE2\x86\x90",
96+
'heavy' => "\xE2\xAC\x85",
97+
'aliases' => array(
98+
'left',
99+
'left-arrow',
100+
'arrow-left',
101+
'west',
102+
),
103+
),
104+
array(
105+
'name' => pht('Down'),
106+
'symbol' => "\xE2\x86\x93",
107+
'heavy' => "\xE2\xAC\x87",
108+
'aliases' => array(
109+
'down',
110+
'down-arrow',
111+
'arrow-down',
112+
'south',
113+
),
114+
),
115+
array(
116+
'name' => pht('Up Right'),
117+
'symbol' => "\xE2\x86\x97",
118+
'heavy' => "\xE2\xAC\x88",
119+
'aliases' => array(
120+
'up-right',
121+
'upright',
122+
'up-right-arrow',
123+
'upright-arrow',
124+
'arrow-up-right',
125+
'arrow-upright',
126+
'northeast',
127+
'north-east',
128+
),
129+
),
130+
array(
131+
'name' => pht('Down Right'),
132+
'symbol' => "\xE2\x86\x98",
133+
'heavy' => "\xE2\xAC\x8A",
134+
'aliases' => array(
135+
'down-right',
136+
'downright',
137+
'down-right-arrow',
138+
'downright-arrow',
139+
'arrow-down-right',
140+
'arrow-downright',
141+
'southeast',
142+
'south-east',
143+
),
144+
),
145+
array(
146+
'name' => pht('Down Left'),
147+
'symbol' => "\xE2\x86\x99",
148+
'heavy' => "\xE2\xAC\x8B",
149+
'aliases' => array(
150+
'down-left',
151+
'downleft',
152+
'down-left-arrow',
153+
'downleft-arrow',
154+
'arrow-down-left',
155+
'arrow-downleft',
156+
'southwest',
157+
'south-west',
158+
),
159+
),
160+
array(
161+
'name' => pht('Up Left'),
162+
'symbol' => "\xE2\x86\x96",
163+
'heavy' => "\xE2\xAC\x89",
164+
'aliases' => array(
165+
'up-left',
166+
'upleft',
167+
'up-left-arrow',
168+
'upleft-arrow',
169+
'arrow-up-left',
170+
'arrow-upleft',
171+
'northwest',
172+
'north-west',
173+
),
174+
),
175+
);
176+
177+
$map = array();
178+
foreach ($special as $spec) {
179+
foreach ($spec['aliases'] as $alias) {
180+
$map[$alias] = $spec;
181+
}
182+
}
183+
184+
$is_text = $this->getEngine()->isTextMode();
185+
186+
$parts = array();
187+
foreach ($keys as $k => $v) {
188+
$normal = phutil_utf8_strtolower($v);
189+
if (isset($map[$normal])) {
190+
$spec = $map[$normal];
191+
} else {
192+
$spec = array(
193+
'name' => null,
194+
'symbol' => $v,
195+
);
196+
}
197+
198+
if ($is_text) {
199+
$parts[] = '['.$spec['symbol'].']';
200+
} else {
201+
$parts[] = phutil_tag(
202+
'kbd',
203+
array(
204+
'title' => $spec['name'],
205+
),
206+
$spec['symbol']);
207+
}
208+
}
209+
210+
if ($is_text) {
211+
$parts = implode(' + ', $parts);
212+
} else {
213+
$glue = phutil_tag(
214+
'span',
215+
array(
216+
'class' => 'kbd-join',
217+
),
218+
'+');
219+
$parts = phutil_implode_html($glue, $parts);
220+
}
221+
222+
return $this->getEngine()->storeText($parts);
223+
}
224+
225+
}

webroot/rsrc/css/core/remarkup.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@
7070
border: 1px solid {$lightgreyborder};
7171
}
7272

73+
.phabricator-remarkup .kbd-join {
74+
padding: 0 4px;
75+
color: {$lightgreytext};
76+
}
77+
7378
.phabricator-remarkup pre.remarkup-counterexample {
7479
background-color: {$sh-redbackground};
7580
}

0 commit comments

Comments
 (0)