Почему «invoke-history» висит в powershell? - PullRequest
1 голос
/ 13 апреля 2020

Если моя последняя команда была чем-то вроде 'dir', то invoke-history, кажется, работает нормально. Если моя последняя команда была чем-то вроде 'vim $ profile', invoke-history покажет команду и повиснет. Есть ли способ это исправить? Большая часть моей работы в powershell заключается в редактировании скрипта и его запуске ... Это становится огромной проблемой.

1 Ответ

3 голосов
/ 13 апреля 2020

Похоже, что ошибка на Windows PowerShell 5.1 / PowerShell [Core] 7.0 :

Такие программы, как vim, полагаются на возможность печатать на терминал (консоль) напрямую , без PowerShell в качестве посредника.

  • При вызове direct , это работает как задумано.

  • При вызове через Invoke-History PowerShell делает вставленным между vim и терминалом, что приводит к неисправности vim:

    • Ошибка Invoke-History: Vim: Warning: Output is not to a terminal.
    • Пользовательский интерфейс vim не отображается, хотя vim работает , о чем свидетельствует тот факт, что вы можете набрать :q, а затем ввести для выхода.

Ошибка сообщена в этой проблеме GitHub .


Обходные пути :

Вы можете свернуть свою собственную функцию Invoke-History, чтобы поместить ее в файл $PROFILE, который вручную получает и выполняет предыдущую команду из истории:

function Invoke-History {
  [CmdletBinding(SupportsShouldProcess)]
  param(
    [string] $Id = (Get-History -Count 1).Id
  )
  $cmd = if ($Id -as [long]) {
      (Get-History -ErrorAction Stop -Id $Id).CommandLine
    } else {
      (Get-History).Where({ $_.CommandLine.TrimStart() -match ('^' + [regex]::Escape($Id)) }, 'Last').CommandLine
    }
  if (-not $cmd) { Throw "Cannot locate the history for command line $Id" }
  if ($PSCmdlet.ShouldProcess($cmd)) {
    # Note: Invoke-Expression is safe to use here, but
    #       should generally be avoided.
    Invoke-Expression $cmd
  }
}

Примечание. Встроенные псевдонимы r и ihy будут автоматически вызывать пользовательскую функцию, а не командлет, поскольку функции имеют более высокий приоритет при поиске команд чем командлеты.


В качестве альтернативы используйте другие способы выполнения команд из истории :

  • Введите #, а затем один из следующее:

    • Используйте клавишу со стрелкой вверх для перемещения назад в истории команд.
    • Введите часть предыдущей команды и затем нажмите Tab для циклического переключения соответствующих команд.
    • Введите число (Id ) команды для повторного выполнения, как показано Get-History, а затем нажмите Tab , чтобы показать эту команду.
    • Нажмите Введите для отправки отображаемая команда.
  • Используйте функцию PSReadLine ReverseSearchHistory, которая связана с комбинацией клавиш Ctrl-R по умолчанию:

    • Нажмите комбинацию клавиш и введите часть предыдущей команды: самая последняя совпадающая команда отобразится автоматически; несколько раз нажмите комбинацию клавиш для циклического переключения между всеми совпадающими командами.
    • Нажмите Введите , чтобы отправить отображаемую команду, или Tab , чтобы сначала отредактировать ее.

Примечание. Начиная с PowerShell 7.0, только метод PSReadLine основан на постоянной истории нескольких сеансов; метод # знает только о командах текущего сеанса.


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...