\documentclass{beamer}
\usepackage{lmodern}
\usepackage[czech]{babel}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{textpos}
\usepackage{tikz,calc}
\usepackage{graphicx}
\usepackage{wrapfig}
\usepackage{color}
\usepackage{mathtools}
\usepackage{hyperref}
\usepackage{epstopdf}
\usepackage{amsmath}
\usepackage{minted}
\hypersetup{
	colorlinks,
	citecolor=black,
	filecolor=black,
	linkcolor=black,
	urlcolor=black
}
\usepackage{pdflscape}

\input{theme/theme.tex}

\title{Tipy a triky nejenom v shellu nejenom pro programátory}
\author{Karel Kočí}
\date{8.10.2017}

\AtBeginSection[]{
	\begin{frame}
		\tableofcontents[currentsection]
	\end{frame}
}

\begin{document}

\input{theme/title.tex}

\begin{frame}[fragile]{O čem to bude?}
	\begin{minted}[frame=lines]{shell}
sed 's/[^\;]*\;//' hist | tr ' ' '\n' | \
	grep -vE '^(-|\||$)' | sort | uniq -c | \
	sort -nr > notes/tatnppvl.result
	\end{minted}
	\begin{tabular}{r|l|r|l|r|l} \hline
		3004 & ls & 2391 & cd & 2225 & git \\ \hline
		1350 & v & 911 & sudo & 608 & tig \\ \hline
		458 & emerge & 410 & push & 405 & ssh \\ \hline
		393 & ..  & 381 & gst & 372 & ci \\ \hline
		320 & add & 303 & vim & 285 & make  \\ \hline
		285 & grep & 282 & rm & 247 & man \\ \hline
		203 & . & 191 & co & 189 & sed \\ \hline
		172 & @world & 159  & ./build\_repo.sh & 156 & omnia \\ \hline
		150 & updater & 148 & mpv & 140 & turris/openwrt \\ \hline
		138 & mount & 124 & cp & 120 & test \\ \hline
		119 & pull & 112 & ip & 109 & turtetris/Makefile \\  \hline
	\end{tabular}
\end{frame}

\section[Section]{Jen shell}

\begin{frame}[fragile]{MAN MAN MAN MAN MAN}
	\begin{minted}[frame=lines]{shell}
man man
man exit
man 3 exit
	\end{minted}
	Z man man:
	\begin{enumerate}
		\item Spustitelný program nebo shell příkaz
		\item Volání systému (funkce z kernelu)
		\item Knihovní volání (funkce poskytované knihovnami)
		\item Speciální soubory (obvykle soubory z /dev)
		\item Souborové formáty a konvence (například /etc/passwd)
		\item Hry
		\item Různorodé (Konvence, makra a pod.)
		\item Příkazy pro systémovou administraci (obvykle sbin)
	\end{enumerate}
\end{frame}

\begin{frame}[fragile]{Náhled na soubory}
	\begin{block}{ll}
		Pro přístupová práva, vlastníky i velikost.
	\begin{minted}[frame=lines]{shell}
alias ll='ls -lh'
	\end{minted}
	\end{block}
	\begin{block}{tree}
		Pro stromovou strukturu.
	\end{block}
\end{frame}

\begin{frame}[fragile]{Připisované soubory}
	\begin{block}{tail -f}
		\begin{minted}[frame=lines]{shell}
sudo tail -f /var/log/messages
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Opakované spuštění}
	\begin{block}{while true; do sleep 1; \emph{command}; done}
		Pro sledování a pod. Například ip address.
	\end{block}
	\begin{block}{dorepeat}
		\begin{minted}[frame=lines]{shell}
dorepeat() {
	while true; do
		"$@"
		sleep 1
		echo
	done
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Hledání souborů}
	\begin{block}{find -name -delete}
		\begin{minted}[frame=lines]{shell}
find -name *elf*
find -name *.orig -delete
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Hledání souborů podle obsahu}
	\begin{block}{grep -Rn PATTERN}
		\begin{minted}[frame=lines]{shell}
grep -Rn elfutils
grep -RnE 'elf-?utils'
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Hledání podle obsahu ve specifických souborech}
	\begin{minted}[frame=lines]{shell}
find -name Makefile | xargs grep -Rn elfutils
	\end{minted}
\end{frame}

\begin{frame}[fragile]{Náhodné heslo}
	\begin{block}{genpasswd}
		\begin{minted}[frame=lines]{shell}
genpasswd() {
	local l=$1
	[ -n "$l" ] || l=16
	tr -dc A-Za-z0-9_ < /dev/urandom \
		| head -c "$l" | xargs
}
		\end{minted}
	\end{block}
\end{frame}

\section[Section]{X server}

\begin{frame}[fragile]{Clipboard}
	\begin{block}{xclip -selection clipboard}
		\begin{minted}[frame=lines]{shell}
cat .ssh/id_rsa.pub | xclip -selection clipboard
		\end{minted}
	\end{block}
	\begin{block}{clip}
		\begin{minted}[frame=lines]{shell}
clip() {
  # Note: printf is magic to remove trailing new lines
  printf %s "$(cat)" | xclip -selection clipboard
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Screenshot}
	\begin{block}{xshot}
		\begin{minted}[frame=lines]{shell}
xshot() {
	import -window "$(xdotool selectwindow)" \
		~/xshot_$(date +%F_%H%M%S_%N).png
}
		\end{minted}
	\end{block}
\end{frame}

\section[Section]{Git}

\begin{frame}[fragile]{Git aliases}
	\begin{block}{git co ci br wt}
		\textasciitilde/.gitconfig
		\begin{minted}[frame=lines]{ini}
[alias]
	co = checkout
	ci = commit
	st = status
	br = branch
	wt = worktree
		\end{minted}
	\end{block}
	\begin{block}{gst}
		\begin{minted}[frame=lines]{shell}
alias gst='git status'
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Verbose commits}
	\textasciitilde/.gitconfig
	\begin{minted}[frame=lines]{ini}
[commit]
	verbose = true
	\end{minted}
	\begin{verbatim}
# Changes to be committed:
#	modified:   utils/localrepo
# ------------------------ >8 ------------------------
diff --git a/utils/localrepo b/utils/localrepo
 HELP_DESCRIPTION = """
-    Local opkg repository management script.
+    Local opkg repository management tool.
     """
	\end{verbatim}
\end{frame}

\begin{frame}[fragile]{git worktree}
	\begin{block}{git worktree add}
		\begin{minted}[frame=lines]{shell}
git branch work-todo
git worktree add ../project-work-todo work-todo
		\end{minted}
	\end{block}
	\begin{block}{git worktree prune}
		\begin{minted}[frame=lines]{shell}
rm -rf ../project-work-done
git worktree prune
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{Git hash $\to$ clipboard}
	\begin{block}{gitclip}
		\begin{minted}[frame=lines]{shell}
gitclip() {
	[ -n "$1" ] && local CMT="$1" || local CMT=HEAD
	git rev-parse "$CMT"| clip
}
		\end{minted}
	\end{block}
	\begin{block}{gitmclip}
		\begin{minted}[frame=lines]{shell}
gitmclip() {
	[ -n "$1" ] && local CMT="$1" || local CMT=HEAD
	git log --format=%B -n 1 "$CMT" | clip
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]{gitbmerge}
	\begin{minted}[frame=lines]{shell}
gitbmerge() {
  (
    set -e
    local WT="$(git worktree list \
      | sed -nE "/\[$1\]/{s/([^ ]+) .*/\1/p}")"
    if [ -n "$WT" ]; then
      rm -r "$WT"
      git worktree prune
    fi
    git merge --ff-only "$1" && \
    git push && git branch -d "$1" \
      && git push origin :"$1"
  )
}
	\end{minted}
\end{frame}

\section[Section]{Stahování}

\begin{frame}[fragile]{Zpracování obsahu pomocí shellu}
	\begin{block}{curl HREF | tar -xzf -}
		\begin{minted}[frame=lines]{shell}
curl http://repo.turris.cz/turris/OpenWrt-SDK.tar.bz2 \
  | tar -xzf -
		\end{minted}
	\end{block}
	\begin{block}{curl -s HREF | grep -n}
		\begin{minted}[frame=lines]{shell}
curl -s http://repo.turris.cz/turris/lists/base.lua \
  | grep -n updater-ng
		\end{minted}
	\end{block}
	Nikdy! \begin{verbatim}curl HREF | sh -s\end{verbatim}
\end{frame}

\begin{frame}[fragile]{Stažení všeho ze serveru}
	\begin{block}{wget -r --no-parent (-l1)}
		\begin{minted}[frame=lines]{shell}
wget -r --no-parent \
  http://repo.turris.cz/turris/packages/
		\end{minted}
	\end{block}
\end{frame}

\section[Section]{SSH}

\begin{frame}[fragile]{Spuštění příkazu na několika hostech}
	\begin{minted}[frame=lines]{shell}
ROUTERS="1 159 189 156 104 199 135 171 244 172"
I=0
for R in $ROUTERS; do
  echo "=== Runnining on 192.168.1.$R ==="

  ssh -i ~/router root@192.168.1.$R -- $@

  #scp -i ~/router user.lua \
  # root@192.168.1.$R:/etc/updater/user.lua

  #ssh -i ~/router root@192.168.1.$R \
  # -- uci set turtetris.line=$I
  #I=$(expr $I + 1)
done
	\end{minted}
\end{frame}

\begin{frame}[fragile]{Port forward}
	\begin{minted}[frame=lines]{shell}
ssh host -L 8484:localhost:8384
	\end{minted}
\end{frame}

\begin{frame}[fragile]{SOCKS proxy}
	\begin{minted}[frame=lines]{shell}
ssh host -D 8123
	\end{minted}
\end{frame}

\begin{frame}[fragile]{Trvalé připojení}
	\begin{block}{cmd}
		\begin{minted}[frame=lines]{shell}
ssh host -o ControlMaster=auto \
  -o ControlPath=$MCNF_DIR/.ssh_access/%r@%h:%p \
  -o ControlPersist=600
		\end{minted}
	\end{block}
	\begin{block}{ssh config}
		\begin{minted}[frame=lines]{shell}
Host *
	ControlMaster auto
	ControlPath .cache/ssh/%r@%h:%p
	ControlPersist 600
		\end{minted}
	\end{block}
\end{frame}

\section[Section]{Bash (Zsh) a emulátor terminálu}

\begin{frame}[fragile]{Prompt a exit code}
	\begin{minted}[frame=lines]{shell}
PROMPT_COMMAND='
EC=$?
if [[ $EC < 0 ]]; then
	echo -e "\e[1;31m"EXIT: $EC"\e[0m"
elif [[ $EC > 0 ]]; then
	echo -e "\e[1;33m"EXIT: $EC"\e[0m"
fi'
	\end{minted}
\end{frame}

\begin{frame}[fragile]{Xterm (urxvt) title}
	\begin{minted}[frame=lines]{shell}
function settitle {
	echo -ne "\033]0;`whoami`@`hostname`:`pwd`\007"
}
case "$TERM" in
	xterm*|*rxvt*)
		trap 'settitle' DEBUG
		;;
esac
	\end{minted}
\end{frame}

\begin{frame}[fragile]{Zsh upozornění od dlouho-běžícího procesu}
	\tiny
	\begin{minted}[frame=lines]{shell}
lrbell_duration=15
lrbell_timestamp=$EPOCHSECONDS
lrbell_window_id=0x0
lrbell_active_window_id() {
	xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2
}
lrbell_begin() {
	lrbell_timestamp=$EPOCHSECONDS
	lrbell_message="`pwd`: $1"
	if [ -n "$DISPLAY" ]; then
		lrbell_window_id=$(lrbell_active_window_id)
	fi
}
lrbell_end() {
	(( $EPOCHSECONDS - $lrbell_timestamp < $lrbell_duration )) && return 0
	print -n '\a'
	if [ -n "$DISPLAY" ] && [ -n "$lrbell_window_id" ]; then
		if [ "$(lrbell_active_window_id)" != "$lrbell_window_id" ]; then
			notify-send "Command finished" "$lrbell_message"
		fi
	fi
}
add-zsh-hook preexec lrbell_begin
add-zsh-hook precmd lrbell_end
	\end{minted}
	\url{https://github.com/rcaloras/bash-preexec}
\end{frame}

\section[Section]{Bash doplňování}

\begin{frame}[fragile]{Jednoduchý příklad}
	\scriptsize
	\begin{minted}[frame=lines]{shell}
_sterm() {
  local cur prev
  _init_completion || return
  COMPREPLY=()
  local ops="-h --help -c -d -e -n -r -s -v"
  case "$prev" in
    -d|-r)
	  ;;
    -s)
	  local speeds="2400 4800 9600 19200 38400 57600 115200 230400"
	  COMPREPLY+=($(compgen -W "${speeds}" -- ${cur}))
	  ;;
    *)
	  COMPREPLY+=($(compgen -W "${ops}" -- ${cur}))
	  ;;
  esac
}
complete -o default -F _sterm sterm
	\end{minted}
\end{frame}

\begin{frame}[fragile]{gitbmerge doplňování}
	\scriptsize
	\begin{minted}[frame=lines]{shell}
_gitbmerge() {
	local cur prev
	_init_completion || return
	[ $COMP_CWORD -gt 1 ] &&  return # Complete only single dependency
	COMPREPLY=()
	local GDIR="$(pwd)"
	while [ ! -d "$GDIR/.git"  ]; do
		[ -z "$GDIR" ] && return
		GDIR="${GDIR%/*}"
	done
	GDIR="$GDIR/.git"
	[ -f "$GDIR" ] && GDIR="$(cat "$GDIR")"
	[ -d "$GDIR/refs/heads" ] || return
	local ops=""
	for B in "$GDIR"/refs/heads/*; do
		ops="$ops ${B#$GDIR/refs/heads/}"
	done
	COMPREPLY+=($(compgen -W "${ops}" -- ${cur}))
}
complete -F _gitbmerge gitbmerge
	\end{minted}
\end{frame}


\begin{frame}
	\Huge A jaké tipy máte vy?

	\Large Děkuji za pozornost. 

	% Poznamka ze vse je take pro zsh v mem gitu
\end{frame}

\end{document}
