Bash 2

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 version. 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.

Autorzy

Artykuły na blogu są pisane przez osoby z zespołu EuroLinux. 80% treści zawdzięczamy naszym developerom, pozostałą część przygotowuje dział sprzedaży lub marketingu. Dokładamy starań, żeby treści były jak najlepsze merytorycznie i językowo, ale nie jesteśmy nieomylni. Jeśli zauważysz coś wartego poprawienia lub wyjaśnienia, będziemy wdzięczni za wiadomość.