Розв’яжіть всі псевдоніми в командному рядку zsh


12

Я вклав псевдоніми і хочу вирішити всі вони перед виконанням команди. Як це зробити?

Якщо є функція, яка не пов'язана ні з якими клавішами, то M-x foobarі для мене добре. Я міг би навіть використовувати зовнішню команду ( type, command, which, що завгодно). Я спробував все з теми, чому б не використовувати "який"? Що тоді використовувати? але нічого не працює.


2
C-x aрозширює псевдонім під курсором (припускаючи, що ви використовуєте систему завершення).
Стефан Шазелас

Право, _expand_alias (^Xa): expands the word the cursor is on if it is an alias. Це корисно, проте все-таки шкода, що в bash можна розширити цілу лінію, але в zsh ні.
WeSenseASoulInSearchOfAnswers

Я припускаю, що можна написати команду, що поєднує _expand_aliasфайли, яка викликає, поки буфер редагування більше не зміниться.
vinc17

Відповіді:


10

Зауважте, що Ctrl-Alt-E у bashне тільки розширює псевдоніми. Він також розширює змінні, підстановку команд (!), Підстановку процесу (!), Розширення арифметики та видалення лапок (це не робить генерацію імен файлів (глобалізація) чи розширення тильди).

Це не завжди вдається розширити псевдоніми. Тому, хоча він має свої цілі, важливо усвідомити, що його результат потенційно змінює значення командного рядка, має побічні ефекти та є потенційно небезпечними.

Наприклад у:

$ a=';w' b=1
$ alias foo=bar
$ b=2; echo $b $a; cd /tmp/dir && for i do foo $(pwd) <(ls); done

Якщо я натискаю M-C-Eтут, це дає мені:

$ b=2; echo 1 ;w; cd /tmp/dir && for i do foo / /dev/fd/63; done

Що дає мені зовсім інший командний рядок (і уявіть, що було б, якби я мав rm -rf *замість pwdвище) і не розширює fooпсевдонім.

З zsh, щоб створити на ноті Жиля синоніми розширених всередині функцій, ви можете зробити:

expand-aliases() {
  unset 'functions[_expand-aliases]'
  functions[_expand-aliases]=$BUFFER
  (($+functions[_expand-aliases])) &&
    BUFFER=${functions[_expand-aliases]#$'\t'} &&
    CURSOR=$#BUFFER
}

zle -N expand-aliases
bindkey '\e^E' expand-aliases

Це розширить псевдоніми лише в тому випадку, якщо поточний командний рядок є синтаксично дійсним (тому він подвоюється як перевірка синтаксису).

На відміну від bashMCE, він також вирішує псевдоніми повністю. Наприклад, якщо у вас є:

$ alias ll='ls -l'; alias ls='ls --color'
$ ll

Буде розширено до:

$ ls --color -l

Зауважте, що він також канонізує синтаксис таким чином:

$ for i (*) cmd $i; foo

буде змінено на:

$ for i in *
        do
                cmd $i
        done
        foo

Це баггі. Якщо у мене є alias ls='ls --color'і набрати C-x aбільше ls, я отримую: \ls --color(так що новий lsНЕ неправильно витлумачений в якості псевдоніма). Але з вашим expand-aliasesя розумію: ls --colorрезультат робить неоднозначним.
vinc17

@ vinc17, це не неоднозначно в тому, що він повністю вирішує псевдонім (в цьому відношенні він менше баггі, ніж bashеквівалент). Але це правда, якщо запустити команду після цього, ви отримаєте ще один раунд розширення псевдоніму (наприклад, в bash), тому в ідеалі ви хочете тимчасово вимкнути розширення псевдоніму, тому, наприклад, оберніть це в (){ setopt localoptions noexpandalias; ...; }. Зауважте, що ви можете сказати, що _expand_aliasце баггі, а також він розширює псевдонім при запуску \ls.
Стефан Шазелас

@ vinc17, що відхилення від нахилу косого ряду _expand_aliasтакож легко обдурити, як alias 'foo=repeat 3 foo'або alias ls='ls --color'; alias '\ls=echo fooled'. Тут немає ідеального рішення.
Стефан Шазелас

Що стосується _expand_aliasдля alias 'foo=repeat 3 foo', я вважав би відсутню зворотної косої межі , як помилка. І alias '\ls=echo fooled'його не можна допускати; тут я віддаю перевагу Баш, який говорить: bash: alias: '\ls': invalid alias name.
vinc17

@ vinc17, я не бачу, як це можна розглядати як інше, крім обмеження в bash. Якщо вам не подобаються псевдоніми з косою рисою, не використовуйте їх, але чому б ви хотіли, щоб оболонка їх відхиляла? Хоча псевдоніми - це заміна функцій бідної людини в csh (звідки вони беруться), в оболонках, подібних до Борна, вони є хаками, щоб робити трюки, які неможливо виконати з функціями, деякою формою розширення макросів, яка зачепить на початку аналізатора оболонки , Я не бачу сенсу обмежувати те, що він може зробити.
Стефан Шазелас

6

Якщо ввести командний рядок у визначення функції та потім роздрукувати функцію, псевдоніми будуть розширені. Ви також отримаєте нормалізований пробіл.

% alias foo='bar -1'
% alias bar='qux -2'
% f () foo -3
% which f
f () {
        qux -2 -1 -3
}

Щоб все це вкласти в інтерактивну команду, ви можете зробити віджет zle. Ви можете визначити функцію безпосередньо, вставивши її код у запис у functionsмасиві; ви отримаєте ефект нормалізації, коли прочитаєте назад.

normalize-command-line () {
  functions[__normalize_command_line_tmp]=$BUFFER
  BUFFER=${${functions[__normalize_command_line_tmp]#$'\t'}//$'\n\t'/$'\n'}
  ((CURSOR == 0 || CURSOR = #BUFFER)
  unset 'functions[__normalize_command_line_tmp]'
}
zle -N normalize-command-line
bindkey  normalize-command-line

Ви отримуєте такий же ефект нормалізації в preexecгачку . Псевдоніми також розширюються під час автоматичної завантаження функції ( autoload -Uзазвичай використовується для уникнення розширення псевдоніму).

Функція _expand_aliasзавершення розширює слово під курсором, якщо це псевдонім. Він використовує aliasesмасив . Це не рекурсивно. Ви можете реалізувати більш загальний псевдонім-експандер, використовуючи aliases, але це дещо складно, оскільки з'ясування місць, де розширення псевдонімів, тісно пов'язане з синтаксисом оболонки.


2
Я завжди використовував autoload -Uпросто тому, що zsh документація рекомендує це, але я ніколи не розумів, що -Uнасправді робив, поки не прочитав це :). Крім того, для тих , хто зацікавлений, можна посилатися на _expand_alias працювати безпосередньо ввівши свій псевдонім в командному рядку, вражаючи <Esc>, xдля запуску мінібуфер, потім набравши_expand_alias<Enter>
the_velour_fog

2

Якщо у вас багато вкладених фантазійних псевдонімів, і ви не впевнені, що zsh насправді робить з ними та в якому порядку параметри передаються команді, ви завжди можете запустити zsh з -xопцією. Це буде друкувати команди та аргументи під час їх виконання.

Однак майте на увазі, що ця опція призначена скоріше для налагодження, тому вона виводить безліч непотрібних речей відразу після zsh -xвиклику (в основному кожна функція / віджет / плагін вашого .zshrc), і під час виконання команд це може бути також багатослівним, особливо якщо ви визначили preexecі precmdгачок.

Я також повинен зазначити, що він друкує лише ті команди, які остаточно виконуються, а окремі команди друкуються окремо, потім після

alias a='echo a'
alias b='echo b'
alias c='echo c'
alias d='echo d'
a && b || c; d

Ти побачиш

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.