Poradnik Bash Bushidō cz. II – Vim oraz biblioteka readline
W tej części cyklu Bash Bushidō dla wojowników konsoli opowiem o edytorze Vim oraz o następnych funkcjach biblioteki readline.
Zdarza mi się, że podczas pisania serii artykułów po czasie zdaję sobie sprawę, że zrobiłem błąd w założeniach. Wypada mi się teraz przyznać, iż nieświadomie uznaję rzeczy dla mnie oczywiste za równie znane dla reszty świata. W związku z tym faktem finalnie powstaje kilka długich artykułów zamiast planowanego jednego czy dwóch – tym razem nie jest inaczej. W wypadku serii o Bashowym Bushidō, czyli drodze wojownika konsoli, mam tę przyjemność, by przedstawić Państwu starannie wybrane zagadnienia, które są bardzo luźno powiązane ze sobą. Dzisiaj opowiem o Vimie i zgodnie z zapowiedziami zajrzymy do następnych funkcji biblioteki readline. Ze względu na obszerność tego artykułu Bash Bushidō, zarządzanie historią opiszę w następnej części cyklu.
Jeśli chcemy szybko wyświetlić wersje Basha, to możemy użyć kombinacji klawiszy ctrl
+ x
, a następnie ctrl
+ v
jak v
ersion. Wyświetli nam to obecną wersję naszej powłoki.
[Alex@SpaceShip ~]$ GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu) [Alex@SpaceShip ====~]$
Wybitnie zainwestowane 30 minut życia? – vimtutor
Oczywiście mógłbym polemizować ze zdaniem, które sam napisałem – przecież w sposób bezpośredni nauka Vima nigdy nie przyniosła mi żadnych pieniędzy. Jednak ten artykuł napisałem w języku markdown w edytorze, który posiada wtyczkę bindującą (okropne zapożyczenie oznaczające powiązanie, przypisanie) klawisze tak, by wyglądało, iż został napisany w Vimie. W swoim życiu miałem okazje korzystać z kilkunastu zintegrowanych środowisk programistycznych i każde z nich posiadało wtyczkę naśladującą Vima. Co więcej, podczas instalacji IDE od JetBrains (PyCharm, IntelliJ IDEA, GoLand, WebStorm) jesteśmy od razu pytani, czy chcemy zainstalować open source’ową wtyczkę IdeaVim.
Jeżeli więc podstawowe możliwości tego cudownego programu nie są Ci jeszcze znane, uruchom, proszę:
vimtutor
i poświęć 30 minut swojego życia na naukę z interaktywnym samouczkiem. Jeżeli nauczysz się podstawowych komend, zaczniesz używać Vima, a do IDE lub innych środowisk doinstalujesz wtyczki – po miesiącu sam zobaczysz, że już nigdy nie będziesz chciał wracać do strzałek.
Jeśli vimtutor uruchomił się w innym języku niż pożądanym, możemy wyeksportować zmienną LANG
tak, by dostać zadany język. W poniższym przypadku język polski.
export LANG=pl_PL.UTF-8 vimtutor
Jako ciekawostkę dodam, iż Vim stał się tak integralną częścią mojego środowiska, że zamieniłem klawisze ESC i CAPS LOCK miejscami. Dzięki czemu nie muszę opuszczać „home row”, co na język polski można przetłumaczyć jako – domyślny (domowy) rząd klawiszy przy zmianie trybu Vima.
Ustawienie Vima jako domyślnego edytora
W celu ustawienia Vima jako domyślny edytor dla użytkownika należy ustawić zmienną „EDITOR”. W tym celu dopisujemy do pliku .bashrc
odpowiednią linię. Cel ten realizuje echo wraz z przekierowaniem do pliku w trybie append (dopisania) do istniejącego pliku lub utworzenia go, gdy nie istnieje.
echo "EDITOR=vim" >> .bashrc
Dzięki temu domyślnym edytorem dla wielu poleceń (np. visudo) będzie vim
.
Wywołanie edytora w celu napisania i uruchomienia skryptu w locie
Ciekawostkę tę umieściłem jako bonus w artykule Bash najpotrzebniejsze skróty klawiszowe. Pozwolę sobie jednak ją powtórzyć. W celu napisania skryptu w locie wciskamy następującą kombinację klawiszy: ctrl+e
po czym ctrl+x
. Jako ciekawostkę dodam, iż nie ma znaczenia czy trzymamy bez przerwy klawisz ctrl
.
W związku z domyślnym wywołaniem emacs
jako edytora, w poprzednim kroku ustawiliśmy zmienną EDITOR w pliku .bashrc
.
Aby zobaczyć, jak działa ten cudowny mechanizm i jeden z moich ulubionych tricków, zachęcam do jego samodzielnego wypróbowania, a dla nieco leniwych, podejrzenia w wyżej wymienionym artykule.
Vi mode
O świętych wojnach w świecie unixowym w najbliższym czasie na naszym blogu pojawi się osobny artykuł. Pozwolę sobie pominąć więc naturalny wstęp.
Domyślnym trybem działania w bibliotece readline jest tryb emacsa. W celu zmiany trybu na tryb vi używamy:
set -o vi
Tutaj czeka nas niemiła niespodzianka. Otóż w trybie vi nie działają skróty, do których się przyzwyczailiśmy, np. ctrl
+ l
nie czyści nam ekranu. Nie mamy też żadnej informacji à propos trybu, w którym jesteśmy (wprowadzanie tekstu czy tryb normalny). Tutaj przychodzi bardzo ponure wyznanie:
Tryb vi jest moim skromnym zdaniem gorszy niż tryb emacsa.
Wynika to z prostego faktu. W trybie emacsowym nie trzeba przechodzić między trybami, by efektywnie edytować linie.
Więcej na temat trybu vi znajdziemy w następnej części Bash Bushidō.
W celu przywrócenia domyślnego trybu używamy:
set -o emacs
Ciekawostka ze świata Fisha
Fish „out of box” dużo lepiej wspiera informowanie użytkownika o trybie pracy, w jakim znajduje się Vim. Prezentuje to poniższy rzut terminala.
Sprawdzenie typu przetwarzanej komendy – type
Do sprawdzenia, z jakim typem komendy mamy tak naprawdę do czynienia, służy nam
polecenie type
.
[Alex@SpaceShip ~]$ type type type is a shell builtin [Alex@SpaceShip ~]$ type bash bash is /usr/bin/bash [Alex@SpaceShip ~]$ type case case is a shell keyword [Alex@SpaceShip ~]$ type which which is aliased to 'alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde' [Alex@SpaceShip ~]$ type command_not_found_handle command_not_found_handle is a function command_not_found_handle () { local runcnf=1; local retval=127; [[ $- =~ i ]] || runcnf=0; [[ ! -S /run/dbus/system_bus_socket ]] && runcnf=0; [[ ! -x '/usr/libexec/packagekitd' ]] && runcnf=0; [[ -n ${COMP_CWORD-} ]] && runcnf=0; if [ $runcnf -eq 1 ]; then '/usr/libexec/pk-command-not-found' "$@"; retval=$?; else if [[ -n "${BASH_VERSION-}" ]]; then printf 'bash: %scommand not found\n' "${1:+$1: }" 1>&2; fi; fi; return $retval } [Alex@SpaceShip ~]$
Istnieje też przełącznik -t, dzięki któremu type
zwraca tylko pojedyncze słowo. Jest on szczególnie przydatny w skryptach.
[Alex@SpaceShip el7_builder]$ type -t type builtin [Alex@SpaceShip el7_builder]$ type -t bash file [Alex@SpaceShip el7_builder]$ type -t case keyword [Alex@SpaceShip el7_builder]$ type -t which alias [Alex@SpaceShip el7_builder]$ type -t command_not_found_handle function
Sprawdzenie, czy komenda jest aliasem
Tutaj istnieje co najmniej 5 sposobów, z czego 4 z nich da się łatwo oskryptować. Pierwszy z nich to oczywiście opisywana powyżej funkcja wbudowana w Basha type
. Trzy pozostałe programistyczne to:
1. Pusta komenda alias
– wypisuje nam wszystkie obecne aliasy.
2. Użycie which nazwa_komendy
– zwraca informacje o ewentualnym aliasie.
3. Wykorzystanie zmiennej BASH_ALIASES
.
Wszystkie trzy sposoby zostały ukazane poniżej:
[Alex@SpaceShip jargon-4.4.7]$ alias alias egrep='egrep --color=auto' alias fgrep='fgrep --color=auto' alias grep='grep --color=auto' alias l.='ls -d .* --color=auto' alias ll='ls -l --color=auto' alias ls='ls --color=auto' alias vi='vim' alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde' [Alex@SpaceShip jargon-4.4.7]$ which vi alias vi='vim' /usr/bin/vim [Alex@SpaceShip jargon-4.4.7]$ echo ${BASH_ALIASES[fgrep]} fgrep --color=auto
Oczywiście wadą podejścia ze zmienną BASH_ALIASES
jest brak kompatybilności z innymi powłokami zgodnymi ze standardem POSIX.
Rozwinięcie aliasu z linii komend
Ostatnim sposobem sprawdzenia, czy zadana komenda jest aliasem, którego raczej się nie oskrptowuje jest interaktywne sprawdzenie istnienia aliasu z jego równoczesnym rozwinięciem. Możemy to uzyskać, korzystając z następującej kombinacji klawiszy: ctrl
+ alt
+ e
. Jest to chyba najciekawszy trick w dzisiejszej lekcji.
Jak widzimy, nie ma znaczenia czy użyjemy samej komendy, czy komendy z argumentami.
Wbrew pozorom możliwości funkcji shell-expand-line
nie ograniczają się tylko do aliasów. Mamy możliwość rozwijania całych podpoleceń czy zmiennych. Pokazują to poniższe przykłady.
Zakończenie i zapowiedź kolejnej części
W następnej części przyjrzymy się !
i jego specjalnemu znaczeniu w linii komend. Poznamy też obiecane bardziej zaawansowane funkcje historii Basha. Na sam koniec dodamy do niego własne skróty klawiszowe.