# plik receptury: bashrc

# settings/bash_profile: ustawienia środowiskowe podpowłoki
# Aby ponownie odczytać plik (i uwzględnić wprowadzone w nim zmiany)
# należy wpisać polecnie:
# source $SETTINGS/bashrc

# Zabezpieczenie przed błędami. Ewentualne komunikaty o nieodnalezieniu
# pliku powinny być łatwe do zrozumienia.
# Początkowy znak ':' zapobiega wykonaniu kodu jako programu
# (po zastąpieniu wartości zmiennej).
: ${SETTINGS:='SETTINGS_zmienna_nie_zdefiniowana'}

# Tylko na czas debugowania --powoduje błędną pracę scp, rsync
# echo "Włączanie pliku $SETTINGS/bash_profile..."
# export PS4='+xtrace $LINENO: '
# set -x

# Debugowanie/logowanie --nie zakłóca pracy scp, rsync
#case "$-" in
#    *i*) echo "$(date '+%Y-%m-%d_%H:%M:%S_%Z') Interaktywna" \
#              "$SETTINGS/bash_profile ssh=$SSH_CONNECTION" >> ~/rc.log ;;
#    *  ) echo "$(date '+%Y-%m-%d_%H:%M:%S_%Z') Nieinteraktywna" \
#              "$SETTINGS/bash_profile ssh=$SSH_CONNECTION" >> ~/rc.log ;;
#esac

# Teoretycznie kod ten jest włączany również w plikach /etc/bashrc (/etc/bash.bashrc)
# i ~/.bashrc i zmienia także ustawienia powłok logowania. W praktyce
# trzeba sprawdzić, czy rzeczywiście tak jest.

# Ustawienie bardziej użytecznych znaków zachęty.
# Zmiana dotyczy TYLKO powłok interaktywnych. Ograniczenie to jest szczególnie istotne
# ponieważ wiele osób sprawdzając, czy powłoka pracuje w trybie interakcyjnym
# używa poleceń if [ "$PS1" ]; then
case "$-" in
    *i*)
        #export PS1='\n[\u@\h t:\l l:$SHLVL h:\! j:\j v:\V]\n$PWD\$ '
        #export PS1='\n[\u@\h:T\l:L$SHLVL:C\!:\D{%Y-%m-%d_%H:%M:%S_%Z}]\n$PWD\$ '
        export PS1='\n[\u@\h:T\l:L$SHLVL:C\!:J\j:\D{%Y-%m-%d_%H:%M:%S_%Z}]\n$PWD\$ '
        #export PS2='> '                     # Drugi znak zachęty (tj. znak kontynuacji)
        #export PS3='Please make a choice: ' # Zgłoszenie instrukcji select
        export PS4='+xtrace $LINENO: '       # Zgłoszenie mehcanizmu debugowania xtrace
    ;;
esac

# Jeżeli uda się odnaleźć plik inputrc, zostanie on wykorzystany.
# Przeszukiwanie obejmuje kilka nazw. Warto również zwrócić uwagę na
# kolejność ich występowania. Ustawienia użytkownika powinny być ważniejsze
# niż ustawienia systemowe.
for file in $SETTINGS/inputrc ~/.inputrc /etc/inputrc; do
    [ -r "$file" ] && export INPUTRC="$file" && break # Wykorzystanie pierwsze znalezionego
done

# Bez plików zrzutu (domyślnie)
# W wielu systemach ustawienie to jest definiowane w pliku /etc/security/limits.conf
ulimit -S -c 0 > /dev/null 2>&1

# Naciśnięcie ctrl+D nie powinno kończyć pracy powłoki
set -o ignoreeof

# Parametry rejestracji poleceń
export HISTSIZE=5000          # Liczba poleceń przechowywanych w pamięci
export HISTFILESIZE=5000      # Liczba poleceń przechowywanych w pliku historii
export HISTCONTROL=ignoreboth # bash < 3, pominięcie duplikatów i wierszy
                              # rozpoczynających się od spacji
export HISTIGNORE='&:[ ]*'    # bash >= 3, pominięcie duplikatów i wierszy 
                              # rozpoczynających się od spacji
#export HISTTIMEFORMAT='%Y-%m-%d_%H:%M:%S_%Z=' # bash >= 3, znacznik czasu
shopt -s histappend           # Dodawanie wpisów zamiast nadpisywania pliku historii
shopt -q -s cdspell           # Automatyczna korekta prostych błędów w użyciu polecenia 'cd'
shopt -q -s checkwinsize      # Uaktualnienie wartości zmiennych LINES i COLUMNS
shopt -q -s cmdhist           # Zapisanie wielowierszowych poleceń jako jednowierszowych
set -o notify   # (or set -b) # Natychmiastowe powiadamianie o zakończeniu procesów 
                              # drugoplanowych

# Inne ustawienia powłoki bash
export LC_COLLATE='C'         # Włączenie standardowej kolejności sortowania (tj. najpierw wielkie litery)
export HOSTFILE='/etc/hosts'  # Uzupełnianie nazw jednostek na podstwie pliku /etc/hosts
export CDPATH='~/:.:..:../..' # Zmienna o działaniu podobnym do $PATH, ale przeznaczona 
                              # dla polecenia 'cd'
# Znak '.' jest niezbędny, aby zmienna $CDPATH była poprawnie przetwarzana w trybie 
# POSIX, ale jednocześnie powoduje przekazanie do strumienia STDOUT nazwy katalogu.

# Import ustawień mechanizmu uzupełniania poleceń, jeśli są zapisane w standardowym 
# pliku. W powolnych systemach operacja ta może zając parę sekund, więc dołączanie ich 
# nie zawsze jest wskazane, nawet jeśli zostały zdefiniowane (w wielu systemach 
# ustawienie to nie jest uwzględniane - np. w systemie Red Hat Linux).
# [ -r /etc/bash_completion ] && source /etc/bash_completion

# Wykorzystanie filtru lesspipe (jeśli uda się go odnaleźć). Ustawienie zmiennej 
# $LESSOPEN. Zastąpienie znaku ':' w treści $PATH znakami spacji pozwala na 
# wykorzystanie ciągu $PATH w pętli
for path in $SETTINGS /opt/bin ~/ ${PATH//:/ }; do
    # Wykorzystanie pierwszego znalezionego pliku 'lesspipe.sh' (preferowane) lub
    # 'lesspipe' (Debian)
    [ -x "$path/lesspipe.sh" ] && eval $("$path/lesspipe.sh") && break
    [ -x "$path/lesspipe" ]    && eval $("$path/lesspipe")    && break
done

# Ustawienie innych parametrów polecenia less i edytorów tekstowych
export LESS="--LONG-PROMPT --LINE-NUMBERS --QUIET"
export VISUAL='vi'  # Edytor domyślny (zawsze dostępny)
# Można by w tym miejscu zastosować instrukcję 'type -P', ale została ona
# dodana do powłoki bash-2.05b, a korzystamy także ze starszych systemów.
# Nie można również zastosować instrukcji 'which', gdyż w niektórych systemach
# zwraca ona wynik tylko wtedy, gdy plik istnieje.
for path in ${PATH//:/ }; do
    # Nadpisanie zmiennej VISUAL, jeśli jest edytor nano
    [ -x "$path/nano" ] \
      && export VISUAL='nano --smooth --const --nowrap --suspend' && break
done
# Zobacz uwagę dotyczącą wyszukania edytora nano
for path in ${PATH//:/ }; do
    # Utworzenie aliasu vi dla edytora vim w trybie binarnym
    [ -x "$path/vim" ] && alias vi='vim -b' && break
done
export EDITOR="$VISUAL"      # Jeszcze inna możliwość
export SVN_EDITOR="$VISUAL"  # System Subversion
alias edit=$VISUAL           # Polecenie działające we wszystkich systemach

# Ustawienie opcji polecenia ls i aliasów
# Ustawienia związane z kolorami mogą nie działać w danym terminalu.
# Nie przeszkadzają jednak w prawidłowym jego funkcjonowaniu.
# Powód wykorzystania takiej instrukcji pętli został opisany w uwadze do edytora nano
for path in ${PATH//:/ }; do
    [ -r "$path/dircolors" ] && eval "$(dircolors)" \
      && LS_OPTIONS='--color=auto' && break
done
export LS_OPTIONS="$LS_OPTIONS -F -h"
# Użycie pliku dircolors może spowodować przerwanie pracy skryptu csh z błędem
# "Unknown colorls variable `do'.". Jest to spowodowane występowaniem kodu  ":do=01;35:"
# w treści zmiennej środowiskowej LS_COLORS. Rozwiązanie problemu zostało opisane na 
# stronie http://forums.macosxhints.com/showthread.php?t=7287
# eval "$(dircolors)"
alias ls="ls $LS_OPTIONS"
alias ll="ls $LS_OPTIONS -l"
alias ll.="ls $LS_OPTIONS -ld"  # Użycie: ll. ~/.*
alias la="ls $LS_OPTIONS -la"

# Użyteczne aliasy
alias bot='cd $(dirname $(find . | tail -1))'
alias clr='cd ~/ && clear'   # Wyczyszczenie ekranu i przejście do katalogu $HOME
alias cls='clear'            # DOS-owa wersja instrukcji clear
alias copy='cp'              # DOS-owa wersja instrukcji cp
#alias cp='cp -i'            # Irytujące ustawienie systemu Red Hat z pliku /root/.bashrc
alias cvsst='cvs -qn update' # Spójny status CVS (podobnie jak svn st)
alias del='rm'               # DOS-owa wersja instrukcji rm
alias diff='diff -u'         # Domyślne użycie zunifikowanego formatu wyjściowego diff
alias jdiff="diff --side-by-side --ignore-case --ignore-blank-lines\
 --ignore-all-space --suppress-common-lines" # Użyteczne opcje polecenia GNU diff
alias dir='ls'               # DOS-owa wersja polecenia ls
alias hr='history -a && history -n' # Dodanie bieżącej historii do pliku i ponowne jego odczytanie
alias ipconfig='ifconfig'    # Windows-owa wersja polecenia ifconfig
alias md='mkdir'             # DOS-owa wersja polecenia mkdir
alias move='mv'              # DOS-owa wersja polecenia mv
#alias mv='mv -i'            # Irytujące ustwienie systemu Red Hat z pliku /root/.bashrc
alias ntsysv='rcconf'        # Instrukcja rcconf w systemie Debian jest zbliżona do
                             # instrukcji ntsysv systemu Red Hat
alias pathping='mtr'         # mtr - sieciowe narzędzie diagnostyczne
alias r='fc -s'              # Przywrócenie i uruchomienie 'polecenia' rozpoczynającego 
                             # się od...
alias rd='rmdir'             # DOS-owa wersja polecenia rmdir
alias ren='mv'               # DOS-owa wersja polecenia  mv/rename
#alias rm='rm -i'            # Irytujące ustwienie systemu Red Hat z pliku /root/.bashrc
alias svnpropfix='svn propset svn:keywords "Id URL"'
alias tracert='traceroute'   # DOS-owa wersja polecenia traceroute
alias vzip='unzip -lvM'      # Przeglądanie zawartości pliku ZIP
alias wgetdir="wget --non-verbose --recursive --no-parent --no-directories\
 --level=1"                  # Pobranie całej zawartości katalogu za pomocą polecenia wget
alias zonex='host -l'        # Zrzut strefy DNS

# Jeśli skrypt istnieje i jest wykonywalny, tworzony jest alias do pobierania
# nagłówków z serwera WWW
for path in ${PATH//:/ }; do
    [ -x "$path/lwp-request" ] && alias httpdinfo='lwp-request -eUd' && break
done

# Przyspieszenie działania klawiatury, ale bez zgłaszania błędu jeśli nie ma pliku 
# kbdrate. Jeśli nie ma pliku najłatwiejszym i najszybszym rozwiązaniem jest
# zignorowanie błędu.
kbdrate -r 30.0 -d 250 &> /dev/null


# Użyteczne funkcje
# utworzenie nowego katalogu i przeście do niego
# użycie: mcd (<prawa dostępu>) <katalog>
function mcd {
    local newdir='_polecenie_mcd_zawiodło_'
    if [ -d "$1" ]; then         # Katalog istnieje - komunikat
        echo "$1 istnieje..."
        newdir="$1"
    else
        if [ -n "$2" ]; then     # Określenie praw dostępu
            command mkdir -p -m $1 "$2" && newdir="$2"
        else                     # Standardowe polecenie mkdir
            command mkdir -p "$1" && newdir="$1"
        fi
    fi
    builtin cd "$newdir"         # Przejście do katalogu
} # koniec funkcji mcd



# Prosty kalkulator uruchamiany z wiersza poleceń
function calc {
    # TYLKO LICZBY CAŁKOWITE! --> echo Wynikiem jest: $(( $* ))
    # Liczby rzeczywiste
    awk "BEGIN {print \"Wynikiem jest: \" $* }";
} # koniec funkcji calc


# Funkcja umożliwia wykorzystanie polecenia 'cd ...' do zmiany katalogów o 2 poziomy
# w góre, 'cd ....' do zmiany o 3 poziomy w góre itd. (podobnie jak 4NT/4DOS)
# Użycie: cd ..., itp.

function cd {

    local option= length= count= cdpath= i= # Zasięg lokalny i pusta wartość początkowa

    # Jeśli została podane opcje -L lub -P (dowiązania symbolicznego), należy je
    # zachować, a następnie usunąć
    if [ "$1" = "-P" -o "$1" = "-L" ]; then
        option="$1"
        shift
    fi

    # Czy jest wykorzystywana specjalna składnia? Sprawdzenie, czy zmienna $1 nie jest
    # pusta. Sprawdzenie, czy trzy pierwsze znaki $1 to '...'. Sprawdzenie, czy nie
    # występuje znak ukośnika - jeżeli operacja podstawienia się nie powiedzie,
    # znak ukośnika nie występuje. Wykonanie procedur startowych jest możliwe tylko w
    # powłokach bash 2.0 i wersjach późniejszych.
    if [ -n "$1" -a "${1:0:3}" = '...' -a "$1" = "${1%/*}" ]; then
        # Specjalna składnia jest wykorzystywana
        length=${#1}  # Zakładamy, że zmienna $1 przechowuje tylko znaki kropki,
                      # które należy.
        count=2       # 'cd ..' nadal oznacza przejście o jeden poziom w górę, pierwsze
                      # dwa znaki są więc ignorowane.

        # Przechodzenie o jeden katalog w góre, aż do wyczerpania znaków kropki
        for ((i=$count;i<=$length;i++)); do
            cdpath="${cdpath}../" # Utworzenie ścieżki
        done

        # Wykonanie samego polecenia cd
        builtin cd $option "$cdpath"
    elif [ -n "$1" ]; then
        # Specjalna składnia NIE jest wykorzystywana - zwykłe polecenie cd
        builtin cd $option "$*"
    else
        # Specjalna składnia NIE jest wykorzystywana - polecenie przejścia do katalogu domowego
        builtin cd $option
    fi
} # koniec funkcji cd


# Ustawienia właściwe dla miejsca pracy lub konkretnego komputera
case $HOSTNAME in
    *.firma.pl        ) # source $SETTINGS/firma.pl
                      ;;
    komp1.*           ) # ustawienia komputera komp1
                      ;;
    komp2.firma.pl    ) # source .bashrc.komp2
                      ;;
    drake.*           ) # echo DRAKE w bash_profile.jp!
                        export TAPE=/dev/tape
                      ;;
esac
