Kiedy przeczytałem twoje pytanie, moją pierwszą myślą było $SHLVL
. Potem zobaczyłem, że chcesz liczyć vim
poziomy
oprócz poziomów powłoki. Prostym sposobem na to jest zdefiniowanie funkcji powłoki:
vim() { ( ((SHLVL++)); command vim "$@");}
To będzie automatycznie i cicho zwiększać za SHLVL
każdym razem, gdy wpiszesz vim
polecenie. Musisz to zrobić dla każdego wariantu vi
/ vim
, którego kiedykolwiek używałeś; na przykład,
vi() { ( ((SHLVL++)); command vi "$@");}
view() { ( ((SHLVL++)); command view "$@");}
Zewnętrzny zestaw nawiasów tworzy podpowłokę, więc ręczna zmiana wartości SHLVL
nie zanieczyszcza bieżącego (macierzystego) środowiska powłoki. Oczywiście command
słowo kluczowe ma zapobiegać wywoływaniu się funkcji (co spowodowałoby nieskończoną pętlę rekurencji). I oczywiście powinieneś umieścić te definicje w swoim .bashrc
lub innym pliku inicjującym powłokę.
Powyżej jest niewielka nieefektywność. W niektórych muszlach (bash to jeden), jeśli tak mówisz
( cmd 1 ; cmd 2 ; … ; cmd n )
gdzie jest zewnętrzny program wykonywalny (tj. nie wbudowane polecenie), powłoka utrzymuje dodatkowy proces leżący w pobliżu, tylko po to, aby czekać na zakończenie. To (prawdopodobnie) nie jest konieczne; zalety i wady są dyskusyjne. Jeśli nie masz nic przeciwko związaniu odrobiny pamięci i gniazda procesu (i zobaczeniu o jeden proces powłoki więcej niż potrzebujesz, gdy wykonujesz a ), to wykonaj powyższe czynności i przejdź do następnej sekcji. To samo, jeśli używasz powłoki, która nie utrzymuje dodatkowego procesu. Ale jeśli chcesz uniknąć dodatkowego procesu, pierwszą rzeczą do wypróbowania jestcmdn
cmdn
ps
vim() { ( ((SHLVL++)); exec vim "$@");}
Jest exec
to polecenie, aby zapobiec dalszemu procesowi powłoki.
Ale jest gotcha. Obsługa powłoki SHLVL
jest nieco intuicyjna: gdy powłoka się uruchamia, sprawdza, czy SHLVL
jest ustawiona. Jeśli nie jest ustawiony (lub ustawiony na coś innego niż liczba), powłoka ustawia go na 1. Jeśli jest ustawiony (na liczbę), powłoka dodaje do niego 1.
Ale według tej logiki, jeśli tak mówisz exec sh
, SHLVL
powinieneś pójść w górę. Ale to niepożądane, ponieważ twój rzeczywisty poziom pocisków nie wzrósł. Powłoka radzi sobie z tym, odejmując jedną z następujących SHLVL
czynności exec
:
$ echo "$SHLVL"
1
$ set | grep SHLVL
SHLVL=1
$ env | grep SHLVL
SHLVL=1
$ (env | grep SHLVL)
SHLVL=1
$ (env) | grep SHLVL
SHLVL=1
$ (exec env) | grep SHLVL
SHLVL=0
Więc
vim() { ( ((SHLVL++)); exec vim "$@");}
jest praniem; zwiększa się SHLVL
tylko w celu ponownego zmniejszenia. Równie dobrze możesz powiedzieć vim
, bez korzystania z funkcji.
Uwaga:
Według Stéphane'a Chazelasa (który wie wszystko) , niektóre powłoki są wystarczająco inteligentne, aby tego nie robić, jeśli exec
są w podpowłoce.
Aby to naprawić, zrobiłbyś
vim() { ( ((SHLVL+=2)); exec vim "$@");}
Potem zobaczyłem, że chcesz liczyć vim
poziomy
niezależnie od poziomów powłoki. Cóż, działa dokładnie ta sama sztuczka (z niewielką modyfikacją):
vim() { ( ((SHLVL++, VILVL++)); export VILVL; exec vim "$@");}
(i tak dalej vi
, view
itp) Jak export
to konieczne, ponieważ VILVL
nie jest zdefiniowany jako zmiennej środowiskowej domyślnie. Ale to nie musi być częścią funkcji; możesz po prostu wypowiedzieć export VILVL
jako osobne polecenie (w swoim .bashrc
). Jak wspomniano powyżej, jeśli proces dodatkowej powłoki nie stanowi dla ciebie problemu, możesz command vim
zamiast tego zrobić exec vim
i zostawić w SHLVL
spokoju:
vim() { ( ((VILVL++)); command vim "$@");}
Preferencje osobiste:
możesz chcieć zmienić nazwę VILVL
na coś podobnego VIM_LEVEL
. Kiedy patrzę na „ VILVL
”, bolą mnie oczy; nie potrafią powiedzieć, czy jest to błędna pisownia „winylu”, czy zniekształcona rzymska cyfra.
Jeśli używasz powłoki, która nie obsługuje SHLVL
(np. Myślnik), możesz ją zaimplementować samodzielnie, o ile powłoka implementuje plik startowy. Po prostu zrób coś takiego
if [ "$SHELL_LEVEL" = "" ]
then
SHELL_LEVEL=1
else
SHELL_LEVEL=$(expr "$SHELL_LEVEL" + 1)
fi
export SHELL_LEVEL
w twoim .profile
lub odpowiednim pliku. (Prawdopodobnie nie powinieneś używać nazwy SHLVL
, ponieważ spowoduje to chaos, jeśli zaczniesz używać powłoki, która obsługuje SHLVL
).
Inne odpowiedzi dotyczyły problemu osadzania wartości zmiennych środowiskowych w zachęcie powłoki, więc nie powtórzę tego, zwłaszcza, że mówisz, że już wiesz, jak to zrobić.
$SHLVL
zmienna (obsługiwana przez kilka powłok) jest tym, czego szukasz?