Подружить Far и bash (Cygwin и другие)

Хотите говорить о Far и не знаете, куда обратиться?
gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Sun 24 Apr, 2016 23:25

Давно пользуюсь Far на винде, и консолью (без mc) в линуксе. Давно уже поставил Cygwin под винду и радуюсь наличию привычных линуксовых команд. В фаре выполняю команды попроще, если что-нибудь нужно посерьёзнее, запускаю bash прямо с командной строки фара, а для чего-то даже и отдельную консоль (putty+cygtermd, хотя хочется попробовать ConEmu). Последнее время появляется всё бОльшее желание, чтоб фар и bash/cygwin больше дружили. Давайте обсудим, поделимся опытом.

Вопросы и предложения.
  1. Far и bash:
    1. OK Выполнение команд с помощью bash
      https://forum.farmanager.com/viewtopic. ... 90#p139090
      Чтобы командная строка выполнялась через bash (кроме встроенных команд). Минус - каждая команда выполняется отдельным процессом, это медленнее и не позволяет задавать функции, переменные, получать результат выполнения последней команды и т.д. Было бы здорово в будущем сделать запускающийся и умирающей вместе с фаром долгоиграющий bash-скрипт, принимающий и выполняющий команды через какой-либо механизм IPC.
    2. OK Возможность ввода мультистрочных команд
      https://forum.farmanager.com/viewtopic. ... 15#p139615
      Чтобы можно было вводить команды на несколько строчек для удобочитаемости.
    3. Улучшения completion-а в UNIX стиле
      https://forum.farmanager.com/viewtopic.php?f=3&t=10356
      Чтобы можно было писать, например, $USERPROFILE с автодополнением (как сейчас можно %USERPROFILE%).
      Чтобы в режиме Panels Off можно было дополнять табом, как в bash-е. В некотором роде можно сделать макросом, но не в точности как в bash-e.
  2. Far и Cygwin:
    1. 25% Поддержка путей, начинающихся с `/`
      viewtopic.php?f=60&t=10529
      X Чтобы `cd /home/root` шло в `C:\cygwin\root`, а `cd /cygdrive/c/Windows` в `C:\Windows` (пути могут отличаться).
      - Чтобы диалоги copy/move и т.д. понимали Cygwin-пути.
      - Чтобы можно было отображать текущие пути вверху панелей в формате Cygwin-а.
      - Чтобы Alt-Shift-Ins умел выдавать пути в удобоваримом виде для Cygwin-а и например какой-нибудь макрос, переключащий режим копирования путей Win/UNIX.

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Mon 25 Apr, 2016 00:07

Добился некоторых успехов по пункту 1a: Выполнение команд с помощью bash
Smitis wrote:А если подменить шелл set comspec=c:\cygwin\bin\bash? Спрашиваю чисто из академического интереса. Может кто уже пробовал.
Попробовал. Первая проблема - команда запускается как `%ComSpec% /C COMMAND`, а bash не понимает /C. Лечится несложно, в `far:config` `System.Executor.ComSpecParams`, по умолчанию `/C`, можно поменять на -c для bash. Я не стал, т.к. всё равно пришлось писать wrapper script (см. далее).

Вторая проблема - не все команды идут через ComSpec. Чтобы убедиться, поставить `set ComSpec=invalid`, и запустить `ls`, команда выполнится. Если же написать `ls | cat`, то уже вылезет ошибка, что invalid не найден.
Может это и не проблема никакая, но хотелось бы знать логику работы. В случае чего можно запускать `'' ls`, тогда выполнится через ComSpec.

Третья проблема - ComSpec-у передаётся полный путь до команды, с обратными слэшами. Например, запускаешь ls, а выполняется bash -c 'C:\cygwin\bin\ls.EXE'. Результат - ошибка: /usr/bin/bash: C:cygwinbinls.exe: command not found
Для bash `\` - escape-символ, соответственно они теряются. Было бы здорово, если б у фара были б ещё настройки для совместимости с разными ComSpec-ами: выдавать путь к команде через `/`. Кстати, cmd в Windows 7 понимает пути через `/`.
Написал wrapper script:


Поставил `set ComSpec=C:\path\to\bashcmd.sh`
Чтоб работало, нужно объяснить Windows, как запускать `.sh` файлы. Это уже другая тема, но вкратце:

Code: Select all

assoc .sh=UNIXShell.Script
ftype UNIXShell.Script="C:\cygwin\bin\bash.exe" "%1" %*
# По желанию добавить `;.SH` в переменную среды PathExt в конце
Скрипт заменяет обратные слэши в команде на прямые, и выполняет команду. Если поставить `set BASHCMD_DEBUG=1`, каждая команда печатается то, что пришло на вход, и что будет выполнено через eval.

В принципе вроде бы оно сносно работает. Буду дальше тестировать.
Некоторые вещи всё-таки не работают:
  • `[ $TERM ] && echo "TERM=$TERM" || echo "TERM is undefined"`
    C:cygwinbin[.EXE: command not found
    [ это встроенная ф-ция bash, но в Cygwin есть и команда такая. Почему-то именно в этом случае путь к `[` - совсем без разделителей `\`, естественно команда не находится.
  • `{ echo $'Directory listing\n'; ls -l; } >ls.txt`
    Скрипт запускается с пустой строкой, соотв-но ничего не происходит. Если добавить перед командой пустую строку (в кавычках) `'' `, всё работает.
Что не нравится:
  • Каждая команда запускается в отдельном процессе. Любые переменные или функции, которые она задаёт, тут же теряются. Соотв-но нет полного ощущения shell-а. Как только нужно сделать что-то более-менее замороченное, надо всё-таки запускать bash.
  • Теряется возможность использовать алиасы, прописанные в doskey.ini и подгружаемые при старте фара через макрос. Можно из bashcmd.sh подгружать отдельно файл с алиасами, (а то и вовсе `/etc/bash.bashrc`, `~/.bashrc`, но если там какой-нибудь bash_completion, то каждая команда будет выполняться медленновато, уж очень это неэффективно). Хотелось бы, чтоб алиасы распознавались фаром ещё до того, как выполнять команду через ComSpec.

    Вопрос: как лучше прописать `ComSpec=/path/to/bashcmd.sh` именно фару (при запуске)? Через макрос?

    Code: Select all

    Macro { description="Use bash to execute commands";
      area="Shell"; key="auto"; flags="RunAfterFARStart";
      action=Что писать тут?;
    }
    

Shmuel
Posts: 5100
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 140 times

Подружить Far и bash (Cygwin и другие)

Post by Shmuel » Mon 25 Apr, 2016 07:49

gene.pavlovsky wrote: action=Что писать тут?
Например так:
action = function() win.SetEnv("ComSpec", "/path/to/bashcmd.sh") end;

Karagy
Posts: 56
Joined: Tue 02 May, 2006 08:43
Location: Питер
Been thanked: 3 times

Подружить Far и bash (Cygwin и другие)

Post by Karagy » Mon 25 Apr, 2016 08:27

Я далёк от темы, но меня настораживают следующие вопросы, который топикпастер почему-то не задал:
- чем будет отрисовываться окно для Far?
- чем будет отрисовываться консоль для bash?

А то получится как соседних тредах - где народ совершенно искренне недоумевает почему нельзя dll редактировать обычным текстовым редактором.

siberia-man
Posts: 69
Joined: Sat 28 Jun, 2014 23:07
Been thanked: 1 time

Подружить Far и bash (Cygwin и другие)

Post by siberia-man » Mon 25 Apr, 2016 09:46

gene.pavlovsky wrote: запустить `ls`, команда выполнится
путь к внешней команде ls прописан в переменной окружения PATH
gene.pavlovsky wrote: Если же написать `ls | cat`, то уже вылезет ошибка
чтобы выполнить эту команду необходим командный интерпретатор - создать конвейер, а установкой в неправильное значение вы лишились его.
gene.pavlovsky wrote: Каждая команда запускается в отдельном процессе
это естественно - ведь для каждой команды запускается новый экземпляр шелла
gene.pavlovsky wrote: Теряется возможность использовать алиасы, прописанные в doskey.ini
алиасы в баше и доскей различаются и существенно. Но можно попробовать что-то вроде `bash --rcfile FILENAME -i`. При этом прописать где-то путь до файла алиасов и минимизировать различия в описании алисов разных систем.

А в целом мне не очень нравится идея стыковать нестыкуемое (или плохо стыкуемое). Сам использую far+conemu для редактирования недольших файлов и навигации по системе (far) и удобной среды для запуска консольных приложений (conemu). Если нужен полноценный шелл запускают cygwin+mintty в нужном каталоге.

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Mon 25 Apr, 2016 14:35

Shmuel wrote:
gene.pavlovsky wrote: action=Что писать тут?
Например так:
action = function() win.SetEnv("ComSpec", "/path/to/bashcmd.sh") end;
Благодарю!
Karagy wrote:Я далёк от темы, но меня настораживают следующие вопросы, который топикпастер почему-то не задал:
- чем будет отрисовываться окно для Far?
- чем будет отрисовываться консоль для bash?
Не пойму, при чём тут это? Far запускается или сам по себе, или через ConEmu (можно в mintty/putty через winpty, но не вижу смысла городить этот огород). Т.е. консоль не юниксовая. Что значит отрисовать консоль для bash? Bash это не полноэкранная программа. Есть ввод, есть вывод. Всё и так нормально работает в фаре. Полноэкранные программы cygwin-а - например просмотрщик текстовых файлов less, или редактор vi - и так отлично работают из-под фара (сигвиновцы постарались). Фар же из-под сигвиновской юниксоподобной консоли без winpty (эмулятора виндовой консоли) не работает, так что вижу смысл именно запускать фар первично, а из него выполнять команды через bash, или же запускать сам bash при необходимости (чем я регулярно занимаюсь, а хочу, чтоб это надобилось реже).
siberia-man wrote: путь к внешней команде ls прописан в переменной окружения PATH
siberia-man wrote: чтобы выполнить эту команду необходим командный интерпретатор - создать конвейер, а установкой в неправильное значение вы лишились его.
Это всё понятно, хотелось бы узнать, в каких случаях фар решает, что сам справится, а в каких запускает ComSpec. Предположим, что вместо bash может быть некий совершенно с иным синтаксисом shell (да пусть хоть какой-нибудь интерпретатор python, мало ли маньяков-извращенцев на свете). Что для far-а вроде бы понятно (он так думает), может для ComSpec-а означать нечто совершенно своё. Имхо была бы не вредна опция выполнять всё-всё, кроме внутренних команд, cd/chdir, через ComSpec.
siberia-man wrote: это естественно - ведь для каждой команды запускается новый экземпляр шелла
С точки зрения и производительности, и ощущения "сессии" было бы лучше запустить долгоживущий шелл, и кормить ему команды по одной. Понятно, что это целая новая ф-циональность, и для шелла типа cmd она не особо полезна, так что мало кто захочет этим заниматься. К примеру в mc на командной строке можно легко засунуть какое-либо значение, или скажем рез-т выполнения программы, в переменную, а потом далее ей пользоваться. Именно "локальная" переменная в рамках сессии, не экспортируемая в окружение. Или можно определить ф-цию, и далее ей воспользоваться. Бывает нужно что-то такое на раз сделать, обработать как-то замысловато группу файлов (в одну команду не выходит). Но не так, чтоб это стоило сохранять на будущее в файл.
siberia-man wrote:алиасы в баше и доскей различаются и существенно. Но можно попробовать что-то вроде `bash --rcfile FILENAME -i`. При этом прописать где-то путь до файла алиасов и минимизировать различия в описании алисов разных систем.
Это я скорее просто упомянул факт, нежели чем пожаловался. Ясно, что по хорошему придётся держать два файла с алиасами в форматах для bash и cmd (хотя если переключиться на один bash, то второй не нужен мне лично), или написать скрипт-конвертор, это несложно.
siberia-man wrote:А в целом мне не очень нравится идея стыковать нестыкуемое (или плохо стыкуемое)
Понимаю ваше мнение. Мне кажется, что добиться полной интеграции, как скажем mc, весьма сложно и трудозатратно. Но в какой-то мере к этому приблизиться можно с хорошим соотношением цена/качество, так сказать. Уже даже то, что я получил сейчас, вместе с ComSpec и моим wrapper скриптом, позволяет наконец делать такие вещи, которых меня давно напрягало, что их не сделать в cmd. Т.е. уже profit имеется, без изменений к фару. Думаю, одними существующими фичами да макросами получить ощутимую выгоду, а если б ещё разработчики фара приложили руку, от результата можно было бы вообще писать кипятком от щастья.

Smitis
Posts: 1452
Joined: Fri 18 Mar, 2005 12:51
Location: Питер
Has thanked: 12 times
Been thanked: 23 times
Contact:

Подружить Far и bash (Cygwin и другие)

Post by Smitis » Mon 25 Apr, 2016 16:38

gene.pavlovsky wrote:Уже даже то, что я получил сейчас, вместе с ComSpec и моим wrapper скриптом, позволяет наконец делать такие вещи, которых меня давно напрягало, что их не сделать в cmd.
Есть ещё TakeCommand
Разум когда-нибудь победит.

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Mon 25 Apr, 2016 17:28

Smitis wrote: Есть ещё TakeCommand
Да, я видел. Но если и изучать какой-нибудь новый для меня shell, то это будет fish или zsh. Я по работе и на винде, и на линуксе работаю, стараюсь пользоваться кроссплатформенными инструментами.
Last edited by gene.pavlovsky on Thu 01 Jan, 1970 01:00, edited 0 times in total.
Reason: Спрятан оверквотинг

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Tue 26 Apr, 2016 09:58

siberia-man wrote:алиасы в баше и доскей различаются и существенно. Но можно попробовать что-то вроде `bash --rcfile FILENAME -i`. При этом прописать где-то путь до файла алиасов и минимизировать различия в описании алисов разных систем.
Забыл сказать. Не проблема написать алиасы для bash-а в rcfile. Но проблема, что у меня в doskey.ini бол-во алиасов - это cd в какие-то часто используемые директории. Не знаю, может кому удобнее через folder history и поиск это делать, или через user menu к примеру, а мне нравится через комстроку, например `klx=cd d:\dropbox\doc\vehicles\motorbike\klx250`. Переписывать это в формате bash бесполезно, ведь cd фар сам должен делать. Так что возможность эта насовсем теряется, при использовании любого другого ComSpec, чем стандартный. Может быть это даже баг? Я, если честно, не совсем понимаю, когда у меня на старте фара выполняется doskey /macrofile=/path/to/doskey.ini, то какой шелл это всё дело исполняет, и каким образом алиасы становятся доступны в фаре. И почему они перестают быть доступны при использовании другого ComSpec.

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Tue 26 Apr, 2016 23:33

Так, с алиасами вопрос решился. Я, как оказалось, неправильно себе представлял, как именно работают алиасы doskey.
DrKnS мне разъяснил. Сами алиасы хранятся в консольном хосте (консоль, внутри которой работает Far, cmd, и другие консольные программы). Консоль в Windows, в отличии от привычного мне терминала UNIX, имеет достаточно много возможностей, и целый API для работы с ней. Алиасы хранятся именно там. Команда doskey работает непосредственно с ними. По умолчанию `doskey proj=cd c:\project` добавляет алиасы в секцию [cmd.exe], которые будут доступны только исполняемому файлу cmd.exe (и Фар их тоже читает, когда ComSpec=cmd.exe). С ключом `/exename=Far.exe` алиасы будут доступны в фаре с любым ComSpec-ом. В doskey.ini поменял [cmd.exe] на [Far.exe] - все алиасы оттуда доступны теперь.
viewtopic.php?p=137363#p137363

Smitis
Posts: 1452
Joined: Fri 18 Mar, 2005 12:51
Location: Питер
Has thanked: 12 times
Been thanked: 23 times
Contact:

Подружить Far и bash (Cygwin и другие)

Post by Smitis » Fri 29 Apr, 2016 10:27

Мне кажется, реализация вот этой почти забытой идеи могла бы помочь viewtopic.php?f=15&t=8641 в "дружбе" ФАРа с различными оболочками.
Разум когда-нибудь победит.

User avatar
HaRT
Moderator
Posts: 8025
Joined: Tue 30 Aug, 2005 17:21
Location: Санкт-Петербург
Has thanked: 67 times
Been thanked: 99 times

Подружить Far и bash (Cygwin и другие)

Post by HaRT » Fri 29 Apr, 2016 12:21

Для полноты информации: дружба с разными командными интерпретаторами упрочена реализацией #3223 (там есть и содержательное обсуждение):
changelog wrote:

Code: Select all

drkns 28.04.2016 16:47:33 +0200 - build 4644

1. Продолжение экспериментальных изменений в запускателе:
   - System.Executor.NotQuotedShell и System.Executor.ComSpecParams больше нет. Однако, теперь есть System.Executor.ComspecArguments, управляющий одновременно и ключами, и кавычками.
     По умолчанию значение совместимо с cmd.exe - /S /C "{0}", где {0} будет заменено исполняемой командой.
     Для bash замените на -c '{0}', для tcc - на -с {0}
   - (частично) #0003223: при передаче в comspec разворачивалось больше, чем нужно.
Фар есть инструмент, а не нянька. © 2009 DrKnS

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Fri 29 Apr, 2016 12:52

Последние изменения действительно улучшают ситуацию, но по-прежнему есть вопросы (например бат-файлы по-прежнему выполняются %ComSpec% /c, что конечно фейлится при ComSpec=bash). Есть также загвоздка с quoting/escaping кавычек при передачи ком строки, содержащей те же кавычки, что используются в System.Executor.ComspecArguments. Например для bash: -с '${0}', если команда содержит одинарные кавычки, получается не очень хорошо. Ещё вопрос - список символов, наличие которых фар считает резоном запускать команду через ComSpec, а не самому - сейчас это " <>|&", причём учитываются они только тогда, когда не в кавычках. Это явно заточено под конкретный род ComSpec-ов (cmd и подобных), для других шеллов сами символы (а также их интерпретация внутри кавычек) могут частично или полностью отличаться. Вот скажем для bash, $VAR это то же, что в cmd %VAR%. Причём если $ в двойных кавычках тоже работает. Но если \$ - то всего лишь символ. Текущая реализация вряд ли может быть доработана, чтобы иметь достаточную гибкость с помощью каких-либо far:config переменных давать полную универсальность для произвольного шелла. Что тут делать - мне не ясно. Запускать все команды через ComSpec - тоже не идеально, ведь хочется, чтоб автоматически работали некоторые вещи, которые просто так из-под bash не запустятся. К примеру, vbs-скрипты.

Вариант вынести всю эту логику в ProcessFarCommandLine мне кажется единственным, способным дать людям полную возможность прикрутить любой шелл.

gene.pavlovsky
Posts: 157
Joined: Tue 11 Aug, 2015 16:53
Has thanked: 11 times

Подружить Far и bash (Cygwin и другие)

Post by gene.pavlovsky » Fri 29 Apr, 2016 12:58

Чем больше думаю и пробую, тем сложнее все кажется в общем случае. Может быть, действительно стоит оставить ComSpec для cmd-совместимых шеллов, а всю кастом логику для произвольных вынести в макроапи или плагин апи? Только по-моему там должны быть две ф-ции - первая (если есть) запускается фаром в самом начале execute(), перед PartCmdLine - она решает, хочет ли макрос/плагин забрать ком строку себе на выполнение, или же он от неё отказывается и возвращает (возможно, с изменениями) фару на выполнение согласно существующей логике (т.е. это кастом версия PartCmdLine). Вторая же ф-ция собственно получает ком строку уже непосредственно на выполнение.

Smitis
Posts: 1452
Joined: Fri 18 Mar, 2005 12:51
Location: Питер
Has thanked: 12 times
Been thanked: 23 times
Contact:

Подружить Far и bash (Cygwin и другие)

Post by Smitis » Fri 29 Apr, 2016 13:00

HaRT wrote:Для полноты информации: дружба с разными командными интерпретаторами упрочена реализацией
Имхо, реализация не совсем удобная для использования различных оболочек с одной копией ФАРа, т.к. настройки возможны только для одной оболочки. Можно использовать что-то типа -set:System.Executor.ComspecArguments="/S /C \"{0}\"" (например, через ярлык). Но это настройка запоминается и при обычном запуске там может оказаться сосвсем не то, что нужно.
Разум когда-нибудь победит.

User avatar
DrKnS
Posts: 4563
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 2 times
Been thanked: 113 times
Contact:

Подружить Far и bash (Cygwin и другие)

Post by DrKnS » Fri 29 Apr, 2016 15:41

gene.pavlovsky wrote: сейчас это " <>|&", причём учитываются они только тогда, когда не в кавычках
Ну если вы сможете изобразить regex, под который попадают "<>|& не в кавычках" и если каким-нибудь другим регексом можно матчить эти ваши $VAR, \$ и т. п. то я буду только рад выкинуть текущий кусок кода в пользу такого регекса из far:config.

Post Reply

Return to “Обсуждение Far Manager”