diff --git a/lib/data/model/server/snippet.dart b/lib/data/model/server/snippet.dart index c634be87..97a58d27 100644 --- a/lib/data/model/server/snippet.dart +++ b/lib/data/model/server/snippet.dart @@ -115,10 +115,10 @@ class Snippet implements TagPickable { final key = argsFmted.substring(start, end).toLowerCase(); // Special funcs - final special = _find(specialCtrl, key); + final special = _find(SnippetFuncs.specialCtrl, key); if (special != null) { final raw = key.substring(special.key.length + 1, key.length - 1); - await special.value(raw); + await special.value((term: terminal, raw: raw)); } // Term keys @@ -152,15 +152,17 @@ class Snippet implements TagPickable { // `${ctrl+ad}` -> `ctrla + d` final chars = key.substring(termKey.key.length + 1, key.length - 1); - terminal.charInput( + if (chars.isEmpty) return; + final ok = terminal.charInput( chars.codeUnitAt(0), ctrl: ctrlAlt.ctrl, alt: ctrlAlt.alt, ); - - for (final char in chars.codeUnits.skip(1)) { - terminal.charInput(char, ctrl: false, alt: false); + if (!ok) { + Loggers.app.warning('Failed to input: $key'); } + + terminal.textInput(chars.substring(1)); } MapEntry? _find(Map map, String key) { @@ -180,12 +182,6 @@ class Snippet implements TagPickable { static final fmtTermKeys = { r'${ctrl': TerminalKey.control, r'${alt': TerminalKey.alt, - r'${enter': TerminalKey.enter, - }; - - static final specialCtrl = { - // `${sleep 3}` -> sleep 3 seconds - r'${sleep': SnippetFuncs.sleep, }; } @@ -201,11 +197,31 @@ class SnippetResult { }); } +typedef SnippetFuncCtx = ({Terminal term, String raw}); + abstract final class SnippetFuncs { - static FutureOr sleep(String raw) async { - final seconds = int.tryParse(raw); + static final specialCtrl = { + // `${sleep 3}` -> sleep 3 seconds + r'${sleep': SnippetFuncs.sleep, + r'${enter': SnippetFuncs.enter, + }; + + static const help = { + 'sleep': 'Sleep for a few seconds', + 'enter': 'Enter a few times', + }; + + static FutureOr sleep(SnippetFuncCtx ctx) async { + final seconds = int.tryParse(ctx.raw); if (seconds == null) return; final duration = Duration(seconds: seconds); await Future.delayed(duration); } + + static FutureOr enter(SnippetFuncCtx ctx) async { + final times = int.tryParse(ctx.raw) ?? 1; + for (var i = 0; i < times; i++) { + ctx.term.keyInput(TerminalKey.enter); + } + } } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 56d2f78c..23651a96 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -112,6 +112,7 @@ "followSystem": "System verfolgen", "font": "Schriftarten", "fontSize": "Schriftgröße", + "forExample": "Zum Beispiel", "force": "freiwillig", "foundNUpdate": "Update {count} gefunden", "fullScreen": "Vollbildmodus", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 58e20538..f0c3de10 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -112,6 +112,7 @@ "followSystem": "Follow system", "font": "Font", "fontSize": "Font size", + "forExample": "For example", "force": "Force", "foundNUpdate": "Found {count} update", "fullScreen": "Full screen mode", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2c281b08..9de9687e 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -112,6 +112,7 @@ "followSystem": "Seguir al sistema", "font": "Fuente", "fontSize": "Tamaño de fuente", + "forExample": "Por ejemplo", "force": "Forzar", "foundNUpdate": "Encontradas {count} actualizaciones", "fullScreen": "Modo pantalla completa", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 9d9a658a..6c6cfb2b 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -112,6 +112,7 @@ "followSystem": "Suivre le système", "font": "Police", "fontSize": "Taille de la police", + "forExample": "Par exemple", "force": "Forcer", "foundNUpdate": "{count} mise à jour trouvée", "fullScreen": "Mode plein écran", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 9ef3ffa9..e156fe62 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -112,6 +112,7 @@ "followSystem": "Ikuti sistem", "font": "Font", "fontSize": "Ukuran huruf", + "forExample": "Sebagai contoh", "force": "sukarela", "foundNUpdate": "Menemukan {count} pembaruan", "fullScreen": "Mode Layar Penuh", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index af713a6f..567c3553 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -112,6 +112,7 @@ "followSystem": "システムに従う", "font": "フォント", "fontSize": "フォントサイズ", + "forExample": "例えば", "force": "強制", "foundNUpdate": "{count}個の更新が見つかりました", "fullScreen": "フルスクリーンモード", diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index b6657b14..c934c245 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -112,6 +112,7 @@ "followSystem": "Volg systeem", "font": "Lettertype", "fontSize": "Lettergrootte", + "forExample": "Bijvoorbeeld", "force": "Forceer", "foundNUpdate": "{count} update gevonden", "fullScreen": "Volledig schermmodus", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 965951fc..b6b90324 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -112,6 +112,7 @@ "followSystem": "Seguir sistema", "font": "Fonte", "fontSize": "Tamanho da fonte", + "forExample": "Por exemplo", "force": "Forçar", "foundNUpdate": "Encontradas {count} atualizações", "fullScreen": "Modo tela cheia", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 7691f4d1..5d2c8e20 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -112,6 +112,7 @@ "followSystem": "следовать за системой", "font": "шрифт", "fontSize": "размер шрифта", + "forExample": "Например", "force": "принудительно", "foundNUpdate": "Найдено {count} обновлений", "fullScreen": "полноэкранный режим", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index faa68b09..89bcaab9 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -112,6 +112,7 @@ "followSystem": "跟随系统", "font": "字体", "fontSize": "字体大小", + "forExample": "例如", "force": "强制", "foundNUpdate": "找到 {count} 个更新", "fullScreen": "全屏模式", diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb index 455fc4e1..4024e9b5 100644 --- a/lib/l10n/app_zh_tw.arb +++ b/lib/l10n/app_zh_tw.arb @@ -112,6 +112,7 @@ "followSystem": "跟隨系統", "font": "字體", "fontSize": "字體大小", + "forExample": "例如", "force": "強制", "foundNUpdate": "找到 {count} 個更新", "fullScreen": "全屏模式", diff --git a/lib/view/page/snippet/edit.dart b/lib/view/page/snippet/edit.dart index 170f4146..81157e9e 100644 --- a/lib/view/page/snippet/edit.dart +++ b/lib/view/page/snippet/edit.dart @@ -200,9 +200,13 @@ class _SnippetEditPageState extends State padding: const EdgeInsets.all(13), child: SimpleMarkdown( data: ''' -📌 ${l10n.supportFmtArgs} +📌 ${l10n.supportFmtArgs}\n +${Snippet.fmtArgs.keys.map((e) => '`$e`').join(', ')}\n -${Snippet.fmtArgs.keys.map((e) => '`$e`').join(', ')} +${Snippet.fmtTermKeys.keys.map((e) => '`$e+?}`').join(', ')}\n +${l10n.forExample}: +- `\${ctrl+c}` (Control + C) +- `\${ctrl+b}d` (Tmux Detach) ''', styleSheet: MarkdownStyleSheet( codeblockDecoration: const BoxDecoration(