mv: s/tv/mv/
This commit is contained in:
parent
3a34a2e0b0
commit
7d66721687
@ -154,7 +154,7 @@ with lib;
|
|||||||
connectTo = [
|
connectTo = [
|
||||||
"cd"
|
"cd"
|
||||||
"gum"
|
"gum"
|
||||||
"pigstarter"
|
"wry"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -217,6 +217,7 @@ with lib;
|
|||||||
"sendmail" # for cron
|
"sendmail" # for cron
|
||||||
];
|
];
|
||||||
|
|
||||||
|
services.bitlbee.enable = true;
|
||||||
services.printing.enable = true;
|
services.printing.enable = true;
|
||||||
|
|
||||||
services.journald.extraConfig = ''
|
services.journald.extraConfig = ''
|
||||||
|
779
mv/2configs/bash_completion.sh
Normal file
779
mv/2configs/bash_completion.sh
Normal file
@ -0,0 +1,779 @@
|
|||||||
|
|
||||||
|
# Expand variable starting with tilde (~)
|
||||||
|
# We want to expand ~foo/... to /home/foo/... to avoid problems when
|
||||||
|
# word-to-complete starting with a tilde is fed to commands and ending up
|
||||||
|
# quoted instead of expanded.
|
||||||
|
# Only the first portion of the variable from the tilde up to the first slash
|
||||||
|
# (~../) is expanded. The remainder of the variable, containing for example
|
||||||
|
# a dollar sign variable ($) or asterisk (*) is not expanded.
|
||||||
|
# Example usage:
|
||||||
|
#
|
||||||
|
# $ v="~"; __expand_tilde_by_ref v; echo "$v"
|
||||||
|
#
|
||||||
|
# Example output:
|
||||||
|
#
|
||||||
|
# v output
|
||||||
|
# -------- ----------------
|
||||||
|
# ~ /home/user
|
||||||
|
# ~foo/bar /home/foo/bar
|
||||||
|
# ~foo/$HOME /home/foo/$HOME
|
||||||
|
# ~foo/a b /home/foo/a b
|
||||||
|
# ~foo/* /home/foo/*
|
||||||
|
#
|
||||||
|
# @param $1 Name of variable (not the value of the variable) to expand
|
||||||
|
__expand_tilde_by_ref()
|
||||||
|
{
|
||||||
|
# Does $1 start with tilde (~)?
|
||||||
|
if [[ ${!1} == \~* ]]; then
|
||||||
|
# Does $1 contain slash (/)?
|
||||||
|
if [[ ${!1} == */* ]]; then
|
||||||
|
# Yes, $1 contains slash;
|
||||||
|
# 1: Remove * including and after first slash (/), i.e. "~a/b"
|
||||||
|
# becomes "~a". Double quotes allow eval.
|
||||||
|
# 2: Remove * before the first slash (/), i.e. "~a/b"
|
||||||
|
# becomes "b". Single quotes prevent eval.
|
||||||
|
# +-----1----+ +---2----+
|
||||||
|
eval $1="${!1/%\/*}"/'${!1#*/}'
|
||||||
|
else
|
||||||
|
# No, $1 doesn't contain slash
|
||||||
|
eval $1="${!1}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
} # __expand_tilde_by_ref()
|
||||||
|
|
||||||
|
|
||||||
|
# Get the word to complete.
|
||||||
|
# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
|
||||||
|
# where the user is completing in the middle of a word.
|
||||||
|
# (For example, if the line is "ls foobar",
|
||||||
|
# and the cursor is here --------> ^
|
||||||
|
# @param $1 string Characters out of $COMP_WORDBREAKS which should NOT be
|
||||||
|
# considered word breaks. This is useful for things like scp where
|
||||||
|
# we want to return host:path and not only path, so we would pass the
|
||||||
|
# colon (:) as $1 in this case.
|
||||||
|
# @param $2 integer Index number of word to return, negatively offset to the
|
||||||
|
# current word (default is 0, previous is 1), respecting the exclusions
|
||||||
|
# given at $1. For example, `_get_cword "=:" 1' returns the word left of
|
||||||
|
# the current word, respecting the exclusions "=:".
|
||||||
|
# @deprecated Use `_get_comp_words_by_ref cur' instead
|
||||||
|
# @see _get_comp_words_by_ref()
|
||||||
|
_get_cword()
|
||||||
|
{
|
||||||
|
local LC_CTYPE=C
|
||||||
|
local cword words
|
||||||
|
__reassemble_comp_words_by_ref "$1" words cword
|
||||||
|
|
||||||
|
# return previous word offset by $2
|
||||||
|
if [[ ${2//[^0-9]/} ]]; then
|
||||||
|
printf "%s" "${words[cword-$2]}"
|
||||||
|
elif [[ "${#words[cword]}" -eq 0 || "$COMP_POINT" == "${#COMP_LINE}" ]]; then
|
||||||
|
printf "%s" "${words[cword]}"
|
||||||
|
else
|
||||||
|
local i
|
||||||
|
local cur="$COMP_LINE"
|
||||||
|
local index="$COMP_POINT"
|
||||||
|
for (( i = 0; i <= cword; ++i )); do
|
||||||
|
while [[
|
||||||
|
# Current word fits in $cur?
|
||||||
|
"${#cur}" -ge ${#words[i]} &&
|
||||||
|
# $cur doesn't match cword?
|
||||||
|
"${cur:0:${#words[i]}}" != "${words[i]}"
|
||||||
|
]]; do
|
||||||
|
# Strip first character
|
||||||
|
cur="${cur:1}"
|
||||||
|
# Decrease cursor position
|
||||||
|
((index--))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Does found word matches cword?
|
||||||
|
if [[ "$i" -lt "$cword" ]]; then
|
||||||
|
# No, cword lies further;
|
||||||
|
local old_size="${#cur}"
|
||||||
|
cur="${cur#${words[i]}}"
|
||||||
|
local new_size="${#cur}"
|
||||||
|
index=$(( index - old_size + new_size ))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
|
||||||
|
# We messed up! At least return the whole word so things
|
||||||
|
# keep working
|
||||||
|
printf "%s" "${words[cword]}"
|
||||||
|
else
|
||||||
|
printf "%s" "${cur:0:$index}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
} # _get_cword()
|
||||||
|
|
||||||
|
|
||||||
|
# Get word previous to the current word.
|
||||||
|
# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
|
||||||
|
# will properly return the previous word with respect to any given exclusions to
|
||||||
|
# COMP_WORDBREAKS.
|
||||||
|
# @deprecated Use `_get_comp_words_by_ref cur prev' instead
|
||||||
|
# @see _get_comp_words_by_ref()
|
||||||
|
#
|
||||||
|
_get_pword()
|
||||||
|
{
|
||||||
|
if [[ $COMP_CWORD -ge 1 ]]; then
|
||||||
|
_get_cword "${@:-}" 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Complete variables.
|
||||||
|
# @return True (0) if variables were completed,
|
||||||
|
# False (> 0) if not.
|
||||||
|
_variables()
|
||||||
|
{
|
||||||
|
if [[ $cur =~ ^(\$\{?)([A-Za-z0-9_]*)$ ]]; then
|
||||||
|
[[ $cur == *{* ]] && local suffix=} || local suffix=
|
||||||
|
COMPREPLY+=( $( compgen -P ${BASH_REMATCH[1]} -S "$suffix" -v -- \
|
||||||
|
"${BASH_REMATCH[2]}" ) )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Assign variable one scope above the caller
|
||||||
|
# Usage: local "$1" && _upvar $1 "value(s)"
|
||||||
|
# Param: $1 Variable name to assign value to
|
||||||
|
# Param: $* Value(s) to assign. If multiple values, an array is
|
||||||
|
# assigned, otherwise a single value is assigned.
|
||||||
|
# NOTE: For assigning multiple variables, use '_upvars'. Do NOT
|
||||||
|
# use multiple '_upvar' calls, since one '_upvar' call might
|
||||||
|
# reassign a variable to be used by another '_upvar' call.
|
||||||
|
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
||||||
|
_upvar()
|
||||||
|
{
|
||||||
|
if unset -v "$1"; then # Unset & validate varname
|
||||||
|
if (( $# == 2 )); then
|
||||||
|
eval $1=\"\$2\" # Return single value
|
||||||
|
else
|
||||||
|
eval $1=\(\"\${@:2}\"\) # Return array
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Assign variables one scope above the caller
|
||||||
|
# Usage: local varname [varname ...] &&
|
||||||
|
# _upvars [-v varname value] | [-aN varname [value ...]] ...
|
||||||
|
# Available OPTIONS:
|
||||||
|
# -aN Assign next N values to varname as array
|
||||||
|
# -v Assign single value to varname
|
||||||
|
# Return: 1 if error occurs
|
||||||
|
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
||||||
|
_upvars()
|
||||||
|
{
|
||||||
|
if ! (( $# )); then
|
||||||
|
echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
|
||||||
|
"value] | [-aN varname [value ...]] ..." 1>&2
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
while (( $# )); do
|
||||||
|
case $1 in
|
||||||
|
-a*)
|
||||||
|
# Error checking
|
||||||
|
[[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
|
||||||
|
"number specifier" 1>&2; return 1; }
|
||||||
|
printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
|
||||||
|
"${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
|
||||||
|
return 1; }
|
||||||
|
# Assign array of -aN elements
|
||||||
|
[[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
|
||||||
|
shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
|
||||||
|
"\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
|
||||||
|
;;
|
||||||
|
-v)
|
||||||
|
# Assign single value
|
||||||
|
[[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
|
||||||
|
shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
|
||||||
|
"argument(s)" 1>&2; return 1; }
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
|
||||||
|
return 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# @param $1 exclude Characters out of $COMP_WORDBREAKS which should NOT be
|
||||||
|
# considered word breaks. This is useful for things like scp where
|
||||||
|
# we want to return host:path and not only path, so we would pass the
|
||||||
|
# colon (:) as $1 in this case.
|
||||||
|
# @param $2 words Name of variable to return words to
|
||||||
|
# @param $3 cword Name of variable to return cword to
|
||||||
|
# @param $4 cur Name of variable to return current word to complete to
|
||||||
|
# @see __reassemble_comp_words_by_ref()
|
||||||
|
__get_cword_at_cursor_by_ref()
|
||||||
|
{
|
||||||
|
local cword words=()
|
||||||
|
__reassemble_comp_words_by_ref "$1" words cword
|
||||||
|
|
||||||
|
local i cur index=$COMP_POINT lead=${COMP_LINE:0:$COMP_POINT}
|
||||||
|
# Cursor not at position 0 and not leaded by just space(s)?
|
||||||
|
if [[ $index -gt 0 && ( $lead && ${lead//[[:space:]]} ) ]]; then
|
||||||
|
cur=$COMP_LINE
|
||||||
|
for (( i = 0; i <= cword; ++i )); do
|
||||||
|
while [[
|
||||||
|
# Current word fits in $cur?
|
||||||
|
${#cur} -ge ${#words[i]} &&
|
||||||
|
# $cur doesn't match cword?
|
||||||
|
"${cur:0:${#words[i]}}" != "${words[i]}"
|
||||||
|
]]; do
|
||||||
|
# Strip first character
|
||||||
|
cur="${cur:1}"
|
||||||
|
# Decrease cursor position
|
||||||
|
((index--))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Does found word match cword?
|
||||||
|
if [[ $i -lt $cword ]]; then
|
||||||
|
# No, cword lies further;
|
||||||
|
local old_size=${#cur}
|
||||||
|
cur="${cur#"${words[i]}"}"
|
||||||
|
local new_size=${#cur}
|
||||||
|
index=$(( index - old_size + new_size ))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# Clear $cur if just space(s)
|
||||||
|
[[ $cur && ! ${cur//[[:space:]]} ]] && cur=
|
||||||
|
# Zero $index if negative
|
||||||
|
[[ $index -lt 0 ]] && index=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local "$2" "$3" "$4" && _upvars -a${#words[@]} $2 "${words[@]}" \
|
||||||
|
-v $3 "$cword" -v $4 "${cur:0:$index}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reassemble command line words, excluding specified characters from the
|
||||||
|
# list of word completion separators (COMP_WORDBREAKS).
|
||||||
|
# @param $1 chars Characters out of $COMP_WORDBREAKS which should
|
||||||
|
# NOT be considered word breaks. This is useful for things like scp where
|
||||||
|
# we want to return host:path and not only path, so we would pass the
|
||||||
|
# colon (:) as $1 here.
|
||||||
|
# @param $2 words Name of variable to return words to
|
||||||
|
# @param $3 cword Name of variable to return cword to
|
||||||
|
#
|
||||||
|
__reassemble_comp_words_by_ref()
|
||||||
|
{
|
||||||
|
local exclude i j line ref
|
||||||
|
# Exclude word separator characters?
|
||||||
|
if [[ $1 ]]; then
|
||||||
|
# Yes, exclude word separator characters;
|
||||||
|
# Exclude only those characters, which were really included
|
||||||
|
exclude="${1//[^$COMP_WORDBREAKS]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default to cword unchanged
|
||||||
|
eval $3=$COMP_CWORD
|
||||||
|
# Are characters excluded which were former included?
|
||||||
|
if [[ $exclude ]]; then
|
||||||
|
# Yes, list of word completion separators has shrunk;
|
||||||
|
line=$COMP_LINE
|
||||||
|
# Re-assemble words to complete
|
||||||
|
for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
|
||||||
|
# Is current word not word 0 (the command itself) and is word not
|
||||||
|
# empty and is word made up of just word separator characters to
|
||||||
|
# be excluded and is current word not preceded by whitespace in
|
||||||
|
# original line?
|
||||||
|
while [[ $i -gt 0 && ${COMP_WORDS[$i]} == +([$exclude]) ]]; do
|
||||||
|
# Is word separator not preceded by whitespace in original line
|
||||||
|
# and are we not going to append to word 0 (the command
|
||||||
|
# itself), then append to current word.
|
||||||
|
[[ $line != [$' \t']* ]] && (( j >= 2 )) && ((j--))
|
||||||
|
# Append word separator to current or new word
|
||||||
|
ref="$2[$j]"
|
||||||
|
eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
|
||||||
|
# Indicate new cword
|
||||||
|
[[ $i == $COMP_CWORD ]] && eval $3=$j
|
||||||
|
# Remove optional whitespace + word separator from line copy
|
||||||
|
line=${line#*"${COMP_WORDS[$i]}"}
|
||||||
|
# Start new word if word separator in original line is
|
||||||
|
# followed by whitespace.
|
||||||
|
[[ $line == [$' \t']* ]] && ((j++))
|
||||||
|
# Indicate next word if available, else end *both* while and
|
||||||
|
# for loop
|
||||||
|
(( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
|
||||||
|
done
|
||||||
|
# Append word to current word
|
||||||
|
ref="$2[$j]"
|
||||||
|
eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
|
||||||
|
# Remove optional whitespace + word from line copy
|
||||||
|
line=${line#*"${COMP_WORDS[i]}"}
|
||||||
|
# Indicate new cword
|
||||||
|
[[ $i == $COMP_CWORD ]] && eval $3=$j
|
||||||
|
done
|
||||||
|
[[ $i == $COMP_CWORD ]] && eval $3=$j
|
||||||
|
else
|
||||||
|
# No, list of word completions separators hasn't changed;
|
||||||
|
eval $2=\( \"\${COMP_WORDS[@]}\" \)
|
||||||
|
fi
|
||||||
|
} # __reassemble_comp_words_by_ref()
|
||||||
|
|
||||||
|
|
||||||
|
# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
|
||||||
|
# word-to-complete.
|
||||||
|
# With a colon in COMP_WORDBREAKS, words containing
|
||||||
|
# colons are always completed as entire words if the word to complete contains
|
||||||
|
# a colon. This function fixes this, by removing the colon-containing-prefix
|
||||||
|
# from COMPREPLY items.
|
||||||
|
# The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
|
||||||
|
# your .bashrc:
|
||||||
|
#
|
||||||
|
# # Remove colon (:) from list of word completion separators
|
||||||
|
# COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
|
||||||
|
#
|
||||||
|
# See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
|
||||||
|
# appears in the filename? - http://tiswww.case.edu/php/chet/bash/FAQ
|
||||||
|
# @param $1 current word to complete (cur)
|
||||||
|
# @modifies global array $COMPREPLY
|
||||||
|
#
|
||||||
|
__ltrim_colon_completions()
|
||||||
|
{
|
||||||
|
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
|
||||||
|
# Remove colon-word prefix from COMPREPLY items
|
||||||
|
local colon_word=${1%"${1##*:}"}
|
||||||
|
local i=${#COMPREPLY[*]}
|
||||||
|
while [[ $((--i)) -ge 0 ]]; do
|
||||||
|
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
} # __ltrim_colon_completions()
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Using this function as a helper function is deprecated. Use
|
||||||
|
# `_known_hosts_real' instead.
|
||||||
|
_known_hosts()
|
||||||
|
{
|
||||||
|
local cur prev words cword
|
||||||
|
_init_completion -n : || return
|
||||||
|
|
||||||
|
# NOTE: Using `_known_hosts' as a helper function and passing options
|
||||||
|
# to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
|
||||||
|
local options
|
||||||
|
[[ "$1" == -a || "$2" == -a ]] && options=-a
|
||||||
|
[[ "$1" == -c || "$2" == -c ]] && options+=" -c"
|
||||||
|
_known_hosts_real $options -- "$cur"
|
||||||
|
} # _known_hosts()
|
||||||
|
|
||||||
|
|
||||||
|
# Helper function for completing _known_hosts.
|
||||||
|
# This function performs host completion based on ssh's config and known_hosts
|
||||||
|
# files, as well as hostnames reported by avahi-browse if
|
||||||
|
# COMP_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value. Also hosts from
|
||||||
|
# HOSTFILE (compgen -A hostname) are added, unless
|
||||||
|
# COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
|
||||||
|
# Usage: _known_hosts_real [OPTIONS] CWORD
|
||||||
|
# Options: -a Use aliases
|
||||||
|
# -c Use `:' suffix
|
||||||
|
# -F configfile Use `configfile' for configuration settings
|
||||||
|
# -p PREFIX Use PREFIX
|
||||||
|
# Return: Completions, starting with CWORD, are added to COMPREPLY[]
|
||||||
|
_known_hosts_real()
|
||||||
|
{
|
||||||
|
local configfile flag prefix
|
||||||
|
local cur curd awkcur user suffix aliases i host
|
||||||
|
local -a kh khd config
|
||||||
|
|
||||||
|
local OPTIND=1
|
||||||
|
while getopts "acF:p:" flag "$@"; do
|
||||||
|
case $flag in
|
||||||
|
a) aliases='yes' ;;
|
||||||
|
c) suffix=':' ;;
|
||||||
|
F) configfile=$OPTARG ;;
|
||||||
|
p) prefix=$OPTARG ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
[[ $# -lt $OPTIND ]] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
|
||||||
|
cur=${!OPTIND}; let "OPTIND += 1"
|
||||||
|
[[ $# -ge $OPTIND ]] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
|
||||||
|
$(while [[ $# -ge $OPTIND ]]; do printf '%s\n' ${!OPTIND}; shift; done)
|
||||||
|
|
||||||
|
[[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
|
||||||
|
kh=()
|
||||||
|
|
||||||
|
# ssh config files
|
||||||
|
if [[ -n $configfile ]]; then
|
||||||
|
[[ -r $configfile ]] && config+=( "$configfile" )
|
||||||
|
else
|
||||||
|
for i in /etc/ssh/ssh_config ~/.ssh/config ~/.ssh2/config; do
|
||||||
|
[[ -r $i ]] && config+=( "$i" )
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Known hosts files from configs
|
||||||
|
if [[ ${#config[@]} -gt 0 ]]; then
|
||||||
|
local OIFS=$IFS IFS=$'\n' j
|
||||||
|
local -a tmpkh
|
||||||
|
# expand paths (if present) to global and user known hosts files
|
||||||
|
# TODO(?): try to make known hosts files with more than one consecutive
|
||||||
|
# spaces in their name work (watch out for ~ expansion
|
||||||
|
# breakage! Alioth#311595)
|
||||||
|
tmpkh=( $( awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u ) )
|
||||||
|
IFS=$OIFS
|
||||||
|
for i in "${tmpkh[@]}"; do
|
||||||
|
# First deal with quoted entries...
|
||||||
|
while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do
|
||||||
|
i=${BASH_REMATCH[1]}${BASH_REMATCH[3]}
|
||||||
|
j=${BASH_REMATCH[2]}
|
||||||
|
__expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
|
||||||
|
[[ -r $j ]] && kh+=( "$j" )
|
||||||
|
done
|
||||||
|
# ...and then the rest.
|
||||||
|
for j in $i; do
|
||||||
|
__expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
|
||||||
|
[[ -r $j ]] && kh+=( "$j" )
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [[ -z $configfile ]]; then
|
||||||
|
# Global and user known_hosts files
|
||||||
|
for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \
|
||||||
|
/etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \
|
||||||
|
~/.ssh/known_hosts2; do
|
||||||
|
[[ -r $i ]] && kh+=( "$i" )
|
||||||
|
done
|
||||||
|
for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
|
||||||
|
[[ -d $i ]] && khd+=( "$i"/*pub )
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we have known_hosts files to use
|
||||||
|
if [[ ${#kh[@]} -gt 0 || ${#khd[@]} -gt 0 ]]; then
|
||||||
|
# Escape slashes and dots in paths for awk
|
||||||
|
awkcur=${cur//\//\\\/}
|
||||||
|
awkcur=${awkcur//\./\\\.}
|
||||||
|
curd=$awkcur
|
||||||
|
|
||||||
|
if [[ "$awkcur" == [0-9]*[.:]* ]]; then
|
||||||
|
# Digits followed by a dot or a colon - just search for that
|
||||||
|
awkcur="^$awkcur[.:]*"
|
||||||
|
elif [[ "$awkcur" == [0-9]* ]]; then
|
||||||
|
# Digits followed by no dot or colon - search for digits followed
|
||||||
|
# by a dot or a colon
|
||||||
|
awkcur="^$awkcur.*[.:]"
|
||||||
|
elif [[ -z $awkcur ]]; then
|
||||||
|
# A blank - search for a dot, a colon, or an alpha character
|
||||||
|
awkcur="[a-z.:]"
|
||||||
|
else
|
||||||
|
awkcur="^$awkcur"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#kh[@]} -gt 0 ]]; then
|
||||||
|
# FS needs to look for a comma separated list
|
||||||
|
COMPREPLY+=( $( awk 'BEGIN {FS=","}
|
||||||
|
/^\s*[^|\#]/ {
|
||||||
|
sub("^@[^ ]+ +", ""); \
|
||||||
|
sub(" .*$", ""); \
|
||||||
|
for (i=1; i<=NF; ++i) { \
|
||||||
|
sub("^\\[", "", $i); sub("\\](:[0-9]+)?$", "", $i); \
|
||||||
|
if ($i !~ /[*?]/ && $i ~ /'"$awkcur"'/) {print $i} \
|
||||||
|
}}' "${kh[@]}" 2>/dev/null ) )
|
||||||
|
fi
|
||||||
|
if [[ ${#khd[@]} -gt 0 ]]; then
|
||||||
|
# Needs to look for files called
|
||||||
|
# .../.ssh2/key_22_<hostname>.pub
|
||||||
|
# dont fork any processes, because in a cluster environment,
|
||||||
|
# there can be hundreds of hostkeys
|
||||||
|
for i in "${khd[@]}" ; do
|
||||||
|
if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
|
||||||
|
host=${i/#*key_22_/}
|
||||||
|
host=${host/%.pub/}
|
||||||
|
COMPREPLY+=( $host )
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# apply suffix and prefix
|
||||||
|
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
||||||
|
COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# append any available aliases from config files
|
||||||
|
if [[ ${#config[@]} -gt 0 && -n "$aliases" ]]; then
|
||||||
|
local hosts=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\{0,1\}['"$'\t '"']\{1,\}\([^#*?]*\)\(#.*\)\{0,1\}$/\2/p' "${config[@]}" )
|
||||||
|
COMPREPLY+=( $( compgen -P "$prefix$user" \
|
||||||
|
-S "$suffix" -W "$hosts" -- "$cur" ) )
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add hosts reported by avahi-browse, if desired and it's available.
|
||||||
|
if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI:-} ]] && \
|
||||||
|
type avahi-browse &>/dev/null; then
|
||||||
|
# The original call to avahi-browse also had "-k", to avoid lookups
|
||||||
|
# into avahi's services DB. We don't need the name of the service, and
|
||||||
|
# if it contains ";", it may mistify the result. But on Gentoo (at
|
||||||
|
# least), -k wasn't available (even if mentioned in the manpage) some
|
||||||
|
# time ago, so...
|
||||||
|
COMPREPLY+=( $( compgen -P "$prefix$user" -S "$suffix" -W \
|
||||||
|
"$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
|
||||||
|
awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add hosts reported by ruptime.
|
||||||
|
COMPREPLY+=( $( compgen -W \
|
||||||
|
"$( ruptime 2>/dev/null | awk '!/^ruptime:/ { print $1 }' )" \
|
||||||
|
-- "$cur" ) )
|
||||||
|
|
||||||
|
# Add results of normal hostname completion, unless
|
||||||
|
# `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
|
||||||
|
if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; then
|
||||||
|
COMPREPLY+=(
|
||||||
|
$( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
|
||||||
|
fi
|
||||||
|
|
||||||
|
__ltrim_colon_completions "$prefix$user$cur"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
} # _known_hosts_real()
|
||||||
|
|
||||||
|
|
||||||
|
# Get the word to complete and optional previous words.
|
||||||
|
# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
|
||||||
|
# where the user is completing in the middle of a word.
|
||||||
|
# (For example, if the line is "ls foobar",
|
||||||
|
# and the cursor is here --------> ^
|
||||||
|
# Also one is able to cross over possible wordbreak characters.
|
||||||
|
# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
|
||||||
|
# Available VARNAMES:
|
||||||
|
# cur Return cur via $cur
|
||||||
|
# prev Return prev via $prev
|
||||||
|
# words Return words via $words
|
||||||
|
# cword Return cword via $cword
|
||||||
|
#
|
||||||
|
# Available OPTIONS:
|
||||||
|
# -n EXCLUDE Characters out of $COMP_WORDBREAKS which should NOT be
|
||||||
|
# considered word breaks. This is useful for things like scp
|
||||||
|
# where we want to return host:path and not only path, so we
|
||||||
|
# would pass the colon (:) as -n option in this case.
|
||||||
|
# -c VARNAME Return cur via $VARNAME
|
||||||
|
# -p VARNAME Return prev via $VARNAME
|
||||||
|
# -w VARNAME Return words via $VARNAME
|
||||||
|
# -i VARNAME Return cword via $VARNAME
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
#
|
||||||
|
# $ _get_comp_words_by_ref -n : cur prev
|
||||||
|
#
|
||||||
|
_get_comp_words_by_ref()
|
||||||
|
{
|
||||||
|
local exclude flag i OPTIND=1
|
||||||
|
local cur cword words=()
|
||||||
|
local upargs=() upvars=() vcur vcword vprev vwords
|
||||||
|
|
||||||
|
while getopts "c:i:n:p:w:" flag "$@"; do
|
||||||
|
case $flag in
|
||||||
|
c) vcur=$OPTARG ;;
|
||||||
|
i) vcword=$OPTARG ;;
|
||||||
|
n) exclude=$OPTARG ;;
|
||||||
|
p) vprev=$OPTARG ;;
|
||||||
|
w) vwords=$OPTARG ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
while [[ $# -ge $OPTIND ]]; do
|
||||||
|
case ${!OPTIND} in
|
||||||
|
cur) vcur=cur ;;
|
||||||
|
prev) vprev=prev ;;
|
||||||
|
cword) vcword=cword ;;
|
||||||
|
words) vwords=words ;;
|
||||||
|
*) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
|
||||||
|
1>&2; return 1
|
||||||
|
esac
|
||||||
|
let "OPTIND += 1"
|
||||||
|
done
|
||||||
|
|
||||||
|
__get_cword_at_cursor_by_ref "$exclude" words cword cur
|
||||||
|
|
||||||
|
[[ $vcur ]] && { upvars+=("$vcur" ); upargs+=(-v $vcur "$cur" ); }
|
||||||
|
[[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
|
||||||
|
[[ $vprev && $cword -ge 1 ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
|
||||||
|
"${words[cword - 1]}"); }
|
||||||
|
[[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
|
||||||
|
"${words[@]}"); }
|
||||||
|
|
||||||
|
(( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Initialize completion and deal with various general things: do file
|
||||||
|
# and variable completion where appropriate, and adjust prev, words,
|
||||||
|
# and cword as if no redirections exist so that completions do not
|
||||||
|
# need to deal with them. Before calling this function, make sure
|
||||||
|
# cur, prev, words, and cword are local, ditto split if you use -s.
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -n EXCLUDE Passed to _get_comp_words_by_ref -n with redirection chars
|
||||||
|
# -e XSPEC Passed to _filedir as first arg for stderr redirections
|
||||||
|
# -o XSPEC Passed to _filedir as first arg for other output redirections
|
||||||
|
# -i XSPEC Passed to _filedir as first arg for stdin redirections
|
||||||
|
# -s Split long options with _split_longopt, implies -n =
|
||||||
|
# @return True (0) if completion needs further processing,
|
||||||
|
# False (> 0) no further processing is necessary.
|
||||||
|
#
|
||||||
|
_init_completion()
|
||||||
|
{
|
||||||
|
local exclude= flag outx errx inx OPTIND=1
|
||||||
|
|
||||||
|
while getopts "n:e:o:i:s" flag "$@"; do
|
||||||
|
case $flag in
|
||||||
|
n) exclude+=$OPTARG ;;
|
||||||
|
e) errx=$OPTARG ;;
|
||||||
|
o) outx=$OPTARG ;;
|
||||||
|
i) inx=$OPTARG ;;
|
||||||
|
s) split=false ; exclude+== ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# For some reason completion functions are not invoked at all by
|
||||||
|
# bash (at least as of 4.1.7) after the command line contains an
|
||||||
|
# ampersand so we don't get a chance to deal with redirections
|
||||||
|
# containing them, but if we did, hopefully the below would also
|
||||||
|
# do the right thing with them...
|
||||||
|
|
||||||
|
COMPREPLY=()
|
||||||
|
local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)"
|
||||||
|
_get_comp_words_by_ref -n "$exclude<>&" cur prev words cword
|
||||||
|
|
||||||
|
# Complete variable names.
|
||||||
|
_variables && return 1
|
||||||
|
|
||||||
|
# Complete on files if current is a redirect possibly followed by a
|
||||||
|
# filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">".
|
||||||
|
if [[ $cur == $redir* || $prev == $redir ]]; then
|
||||||
|
local xspec
|
||||||
|
case $cur in
|
||||||
|
2'>'*) xspec=$errx ;;
|
||||||
|
*'>'*) xspec=$outx ;;
|
||||||
|
*'<'*) xspec=$inx ;;
|
||||||
|
*)
|
||||||
|
case $prev in
|
||||||
|
2'>'*) xspec=$errx ;;
|
||||||
|
*'>'*) xspec=$outx ;;
|
||||||
|
*'<'*) xspec=$inx ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
cur="${cur##$redir}"
|
||||||
|
_filedir $xspec
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove all redirections so completions don't have to deal with them.
|
||||||
|
local i skip
|
||||||
|
for (( i=1; i < ${#words[@]}; )); do
|
||||||
|
if [[ ${words[i]} == $redir* ]]; then
|
||||||
|
# If "bare" redirect, remove also the next word (skip=2).
|
||||||
|
[[ ${words[i]} == $redir ]] && skip=2 || skip=1
|
||||||
|
words=( "${words[@]:0:i}" "${words[@]:i+skip}" )
|
||||||
|
[[ $i -le $cword ]] && cword=$(( cword - skip ))
|
||||||
|
else
|
||||||
|
i=$(( ++i ))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ $cword -le 0 ]] && return 1
|
||||||
|
prev=${words[cword-1]}
|
||||||
|
|
||||||
|
[[ ${split-} ]] && _split_longopt && split=true
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to complete -o SubOptions=
|
||||||
|
#
|
||||||
|
# Returns 0 if the completion was handled or non-zero otherwise.
|
||||||
|
_ssh_suboption_check()
|
||||||
|
{
|
||||||
|
# Get prev and cur words without splitting on =
|
||||||
|
local cureq=`_get_cword :=` preveq=`_get_pword :=`
|
||||||
|
if [[ $cureq == *=* && $preveq == -o ]]; then
|
||||||
|
_ssh_suboption $cureq
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_complete_ssh()
|
||||||
|
{
|
||||||
|
local cur prev words cword
|
||||||
|
_init_completion -n : || return
|
||||||
|
|
||||||
|
local configfile
|
||||||
|
local -a config
|
||||||
|
|
||||||
|
_ssh_suboption_check && return 0
|
||||||
|
|
||||||
|
case $prev in
|
||||||
|
-F|-i|-S)
|
||||||
|
_filedir
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-c)
|
||||||
|
_ssh_ciphers
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-m)
|
||||||
|
_ssh_macs
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-l)
|
||||||
|
COMPREPLY=( $( compgen -u -- "$cur" ) )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-O)
|
||||||
|
COMPREPLY=( $( compgen -W 'check forward exit stop' -- "$cur" ) )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-o)
|
||||||
|
_ssh_options
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-w)
|
||||||
|
_available_interfaces
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-b)
|
||||||
|
_ip_addresses
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-D|-e|-I|-L|-p|-R|-W)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$cur" == -F* ]]; then
|
||||||
|
cur=${cur#-F}
|
||||||
|
_filedir
|
||||||
|
# Prefix completions with '-F'
|
||||||
|
COMPREPLY=( "${COMPREPLY[@]/#/-F}" )
|
||||||
|
cur=-F$cur # Restore cur
|
||||||
|
elif [[ "$cur" == -* ]]; then
|
||||||
|
COMPREPLY=( $( compgen -W '$( _parse_usage "$1" )' -- "$cur" ) )
|
||||||
|
else
|
||||||
|
# Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument
|
||||||
|
set -- "${words[@]}"
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
if [[ $1 == -F* ]]; then
|
||||||
|
if [[ ${#1} -gt 2 ]]; then
|
||||||
|
configfile="$(dequote "${1:2}")"
|
||||||
|
else
|
||||||
|
shift
|
||||||
|
[[ $1 ]] && configfile="$(dequote "$1")"
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
_known_hosts_real -a -F "$configfile" "$cur"
|
||||||
|
if [[ $cword -ne 1 ]]; then
|
||||||
|
compopt -o filenames
|
||||||
|
COMPREPLY+=( $( compgen -c -- "$cur" ) )
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
} &&
|
||||||
|
shopt -u hostcomplete && complete -F _complete_ssh ssh
|
@ -1,12 +1,15 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
let
|
||||||
|
HOME = getEnv "HOME";
|
||||||
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
krebs.enable = true;
|
krebs.enable = true;
|
||||||
|
|
||||||
krebs.build = {
|
krebs.build = {
|
||||||
user = config.krebs.users.tv;
|
user = config.krebs.users.mv;
|
||||||
target = mkDefault "root@${config.krebs.build.host.name}";
|
target = mkDefault "root@${config.krebs.build.host.name}";
|
||||||
source = {
|
source = {
|
||||||
git.nixpkgs = {
|
git.nixpkgs = {
|
||||||
@ -15,10 +18,10 @@ with lib;
|
|||||||
target-path = mkDefault "/var/src/nixpkgs";
|
target-path = mkDefault "/var/src/nixpkgs";
|
||||||
};
|
};
|
||||||
dir.secrets = {
|
dir.secrets = {
|
||||||
path = mkDefault "/home/tv/secrets/${config.krebs.build.host.name}";
|
path = mkDefault "${HOME}/secrets/${config.krebs.build.host.name}";
|
||||||
};
|
};
|
||||||
dir.stockholm = {
|
dir.stockholm = {
|
||||||
path = mkDefault "/home/tv/stockholm";
|
path = mkDefault "${HOME}/stockholm";
|
||||||
target-path = mkDefault "/var/src/stockholm";
|
target-path = mkDefault "/var/src/stockholm";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -40,16 +43,16 @@ with lib;
|
|||||||
defaultUserShell = "/run/current-system/sw/bin/bash";
|
defaultUserShell = "/run/current-system/sw/bin/bash";
|
||||||
mutableUsers = false;
|
mutableUsers = false;
|
||||||
users = {
|
users = {
|
||||||
tv = {
|
mv = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
uid = 1337;
|
uid = 1338;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
security.sudo.extraConfig = ''
|
security.sudo.extraConfig = ''
|
||||||
Defaults mailto="${config.krebs.users.tv.mail}"
|
Defaults mailto="${config.krebs.users.mv.mail}"
|
||||||
'';
|
'';
|
||||||
time.timeZone = "Europe/Berlin";
|
time.timeZone = "Europe/Berlin";
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ with lib;
|
|||||||
|
|
||||||
let
|
let
|
||||||
# TODO krebs.build.user
|
# TODO krebs.build.user
|
||||||
user = config.users.users.tv;
|
user = config.users.users.mv;
|
||||||
|
|
||||||
out = {
|
out = {
|
||||||
services.xserver.display = 11;
|
services.xserver.display = 11;
|
||||||
|
19
mv/5pkgs/default.nix
Normal file
19
mv/5pkgs/default.nix
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# TODO use XDG_RUNTIME_DIR?
|
||||||
|
cr = pkgs.writeScriptBin "cr" ''
|
||||||
|
#! /bin/sh
|
||||||
|
set -efu
|
||||||
|
export LC_TIME=de_DE.utf8
|
||||||
|
exec ${pkgs.chromium}/bin/chromium \
|
||||||
|
--ssl-version-min=tls1 \
|
||||||
|
--disk-cache-dir=/tmp/chromium-disk-cache_"$LOGNAME" \
|
||||||
|
--disk-cache-size=50000000 \
|
||||||
|
"%@"
|
||||||
|
'';
|
||||||
|
ff = pkgs.callPackage ./ff {};
|
||||||
|
xmonad-tv =
|
||||||
|
let src = pkgs.writeNixFromCabal "xmonad-tv.nix" ./xmonad-tv; in
|
||||||
|
pkgs.haskellPackages.callPackage src {};
|
||||||
|
}
|
8
mv/5pkgs/ff/default.nix
Normal file
8
mv/5pkgs/ff/default.nix
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
pkgs.writeScriptBin "ff" ''
|
||||||
|
#! ${pkgs.bash}/bin/bash
|
||||||
|
exec sudo -u ff -i <<EOF
|
||||||
|
exec ${pkgs.firefoxWrapper}/bin/firefox $(printf " %q" "$@")
|
||||||
|
EOF
|
||||||
|
''
|
1
mv/5pkgs/xmonad-tv/.gitignore
vendored
Normal file
1
mv/5pkgs/xmonad-tv/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/shell.nix
|
277
mv/5pkgs/xmonad-tv/Main.hs
Normal file
277
mv/5pkgs/xmonad-tv/Main.hs
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
{-# LANGUAGE DeriveDataTypeable #-} -- for XS
|
||||||
|
{-# LANGUAGE FlexibleContexts #-} -- for xmonad'
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
|
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Control.Exception
|
||||||
|
import Text.Read (readEither)
|
||||||
|
import XMonad
|
||||||
|
import System.IO (hPutStrLn, stderr)
|
||||||
|
import System.Environment (getArgs, withArgs, getEnv, getEnvironment)
|
||||||
|
import System.Posix.Process (executeFile)
|
||||||
|
import XMonad.Prompt (defaultXPConfig)
|
||||||
|
import XMonad.Actions.DynamicWorkspaces ( addWorkspacePrompt, renameWorkspace
|
||||||
|
, removeEmptyWorkspace)
|
||||||
|
import XMonad.Actions.GridSelect
|
||||||
|
import XMonad.Actions.CycleWS (toggleWS)
|
||||||
|
--import XMonad.Actions.CopyWindow ( copy )
|
||||||
|
import XMonad.Layout.NoBorders ( smartBorders )
|
||||||
|
import qualified XMonad.StackSet as W
|
||||||
|
import Data.Map (Map)
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
-- TODO import XMonad.Layout.WorkspaceDir
|
||||||
|
import XMonad.Hooks.UrgencyHook (SpawnUrgencyHook(..), withUrgencyHook)
|
||||||
|
-- import XMonad.Layout.Tabbed
|
||||||
|
--import XMonad.Layout.MouseResizableTile
|
||||||
|
import XMonad.Layout.Reflect (reflectVert)
|
||||||
|
import XMonad.Layout.FixedColumn (FixedColumn(..))
|
||||||
|
import XMonad.Hooks.Place (placeHook, smart)
|
||||||
|
import XMonad.Hooks.FloatNext (floatNextHook)
|
||||||
|
import XMonad.Actions.PerWorkspaceKeys (chooseAction)
|
||||||
|
import XMonad.Layout.PerWorkspace (onWorkspace)
|
||||||
|
--import XMonad.Layout.BinarySpacePartition
|
||||||
|
|
||||||
|
--import XMonad.Actions.Submap
|
||||||
|
import XMonad.Stockholm.Pager
|
||||||
|
import XMonad.Stockholm.Rhombus
|
||||||
|
import XMonad.Stockholm.Shutdown
|
||||||
|
|
||||||
|
|
||||||
|
myTerm :: String
|
||||||
|
myTerm = "urxvtc"
|
||||||
|
|
||||||
|
myRootTerm :: String
|
||||||
|
myRootTerm = "urxvtc -name root-urxvt -e su -"
|
||||||
|
|
||||||
|
myFont :: String
|
||||||
|
myFont = "-schumacher-*-*-*-*-*-*-*-*-*-*-*-iso10646-*"
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = getArgs >>= \case
|
||||||
|
["--shutdown"] -> sendShutdownEvent
|
||||||
|
_ -> mainNoArgs
|
||||||
|
|
||||||
|
mainNoArgs :: IO ()
|
||||||
|
mainNoArgs = do
|
||||||
|
workspaces0 <- getWorkspaces0
|
||||||
|
xmonad'
|
||||||
|
-- $ withUrgencyHookC dzenUrgencyHook { args = ["-bg", "magenta", "-fg", "magenta", "-h", "2"], duration = 500000 }
|
||||||
|
-- urgencyConfig { remindWhen = Every 1 }
|
||||||
|
-- $ withUrgencyHook borderUrgencyHook "magenta"
|
||||||
|
-- $ withUrgencyHookC BorderUrgencyHook { urgencyBorderColor = "magenta" } urgencyConfig { suppressWhen = Never }
|
||||||
|
$ withUrgencyHook (SpawnUrgencyHook "echo emit Urgency ")
|
||||||
|
$ defaultConfig
|
||||||
|
{ terminal = myTerm
|
||||||
|
, modMask = mod4Mask
|
||||||
|
, keys = myKeys
|
||||||
|
, workspaces = workspaces0
|
||||||
|
, layoutHook = smartBorders $ myLayout
|
||||||
|
-- , handleEventHook = myHandleEventHooks <+> handleTimerEvent
|
||||||
|
--, handleEventHook = handleTimerEvent
|
||||||
|
, manageHook = placeHook (smart (1,0)) <+> floatNextHook
|
||||||
|
, startupHook = spawn "echo emit XMonadStartup"
|
||||||
|
, normalBorderColor = "#1c1c1c"
|
||||||
|
, focusedBorderColor = "#f000b0"
|
||||||
|
, handleEventHook = handleShutdownEvent
|
||||||
|
}
|
||||||
|
where
|
||||||
|
myLayout =
|
||||||
|
(onWorkspace "im" $ reflectVert $ Mirror $ Tall 1 (3/100) (12/13))
|
||||||
|
(FixedColumn 1 20 80 10 ||| Full)
|
||||||
|
|
||||||
|
|
||||||
|
xmonad' :: (LayoutClass l Window, Read (l Window)) => XConfig l -> IO ()
|
||||||
|
xmonad' conf = do
|
||||||
|
path <- getEnv "XMONAD_STATE"
|
||||||
|
try (readFile path) >>= \case
|
||||||
|
Right content -> do
|
||||||
|
hPutStrLn stderr ("resuming from " ++ path)
|
||||||
|
withArgs ("--resume" : lines content) (xmonad conf)
|
||||||
|
Left e -> do
|
||||||
|
hPutStrLn stderr (displaySomeException e)
|
||||||
|
xmonad conf
|
||||||
|
|
||||||
|
getWorkspaces0 :: IO [String]
|
||||||
|
getWorkspaces0 =
|
||||||
|
try (getEnv "XMONAD_WORKSPACES0_FILE") >>= \case
|
||||||
|
Left e -> warn (displaySomeException e)
|
||||||
|
Right p -> try (readFile p) >>= \case
|
||||||
|
Left e -> warn (displaySomeException e)
|
||||||
|
Right x -> case readEither x of
|
||||||
|
Left e -> warn e
|
||||||
|
Right y -> return y
|
||||||
|
where
|
||||||
|
warn msg = hPutStrLn stderr ("getWorkspaces0: " ++ msg) >> return []
|
||||||
|
|
||||||
|
displaySomeException :: SomeException -> String
|
||||||
|
displaySomeException = displayException
|
||||||
|
|
||||||
|
|
||||||
|
spawnTermAt :: String -> X ()
|
||||||
|
--spawnTermAt _ = floatNext True >> spawn myTerm
|
||||||
|
--spawnTermAt "ff" = floatNext True >> spawn myTerm
|
||||||
|
--spawnTermAt _ = spawn myTerm
|
||||||
|
spawnTermAt ws = do
|
||||||
|
env <- liftIO getEnvironment
|
||||||
|
let env' = ("XMONAD_SPAWN_WORKSPACE", ws) : env
|
||||||
|
xfork (executeFile "urxvtc" True [] (Just env')) >> return ()
|
||||||
|
|
||||||
|
myKeys :: XConfig Layout -> Map (KeyMask, KeySym) (X ())
|
||||||
|
myKeys conf = Map.fromList $
|
||||||
|
[ ((_4 , xK_Escape ), spawn "/var/setuid-wrappers/slock")
|
||||||
|
, ((_4S , xK_c ), kill)
|
||||||
|
|
||||||
|
, ((_4 , xK_x ), chooseAction spawnTermAt)
|
||||||
|
, ((_4C , xK_x ), spawn myRootTerm)
|
||||||
|
--, ((_4M , xK_x ), spawn "xterm")
|
||||||
|
--, ((_4M , xK_x ), mySpawn "xterm")
|
||||||
|
|
||||||
|
--, ((_4 , xK_F1 ), withFocused jojo)
|
||||||
|
--, ((_4 , xK_F1 ), printAllGeometries)
|
||||||
|
|
||||||
|
, ((0 , xK_Menu ), gets windowset >>= allWorkspaceNames >>= pager pagerConfig (windows . W.view) )
|
||||||
|
, ((_S , xK_Menu ), gets windowset >>= allWorkspaceNames >>= pager pagerConfig (windows . W.shift) )
|
||||||
|
, ((_C , xK_Menu ), toggleWS)
|
||||||
|
, ((_4 , xK_Menu ), rhombus horseConfig (liftIO . hPutStrLn stderr) ["Correct", "Horse", "Battery", "Staple", "Stuhl", "Tisch"] )
|
||||||
|
|
||||||
|
-- %! Rotate through the available layout algorithms
|
||||||
|
, ((_4 , xK_space ), sendMessage NextLayout)
|
||||||
|
, ((_4S , xK_space ), setLayout $ XMonad.layoutHook conf) -- reset layout
|
||||||
|
|
||||||
|
---- BinarySpacePartition
|
||||||
|
--, ((_4 , xK_l), sendMessage $ ExpandTowards R)
|
||||||
|
--, ((_4 , xK_h), sendMessage $ ExpandTowards L)
|
||||||
|
--, ((_4 , xK_j), sendMessage $ ExpandTowards D)
|
||||||
|
--, ((_4 , xK_k), sendMessage $ ExpandTowards U)
|
||||||
|
--, ((_4S , xK_l), sendMessage $ ShrinkFrom R)
|
||||||
|
--, ((_4S , xK_h), sendMessage $ ShrinkFrom L)
|
||||||
|
--, ((_4S , xK_j), sendMessage $ ShrinkFrom D)
|
||||||
|
--, ((_4S , xK_k), sendMessage $ ShrinkFrom U)
|
||||||
|
--, ((_4 , xK_n), sendMessage Rotate)
|
||||||
|
--, ((_4S , xK_n), sendMessage Swap)
|
||||||
|
|
||||||
|
---- mouseResizableTile
|
||||||
|
--, ((_4 , xK_u), sendMessage ShrinkSlave)
|
||||||
|
--, ((_4 , xK_i), sendMessage ExpandSlave)
|
||||||
|
|
||||||
|
-- move focus up or down the window stack
|
||||||
|
--, ((_4 , xK_m ), windows W.focusMaster)
|
||||||
|
, ((_4 , xK_j ), windows W.focusDown)
|
||||||
|
, ((_4 , xK_k ), windows W.focusUp)
|
||||||
|
|
||||||
|
-- modifying the window order
|
||||||
|
, ((_4S , xK_m ), windows W.swapMaster)
|
||||||
|
, ((_4S , xK_j ), windows W.swapDown)
|
||||||
|
, ((_4S , xK_k ), windows W.swapUp)
|
||||||
|
|
||||||
|
-- resizing the master/slave ratio
|
||||||
|
, ((_4 , xK_h ), sendMessage Shrink) -- %! Shrink the master area
|
||||||
|
, ((_4 , xK_l ), sendMessage Expand) -- %! Expand the master area
|
||||||
|
|
||||||
|
-- floating layer support
|
||||||
|
, ((_4 , xK_t ), withFocused $ windows . W.sink) -- make tiling
|
||||||
|
|
||||||
|
-- increase or decrease number of windows in the master area
|
||||||
|
, ((_4 , xK_comma ), sendMessage $ IncMasterN 1)
|
||||||
|
, ((_4 , xK_period ), sendMessage $ IncMasterN (-1))
|
||||||
|
|
||||||
|
, ((_4 , xK_a ), addWorkspacePrompt defaultXPConfig)
|
||||||
|
, ((_4 , xK_r ), renameWorkspace defaultXPConfig)
|
||||||
|
, ((_4 , xK_Delete ), removeEmptyWorkspace)
|
||||||
|
|
||||||
|
, ((_4 , xK_Return ), toggleWS)
|
||||||
|
--, (0 , xK_Menu ) & \k -> (k, gridselectWorkspace wsGSConfig { gs_navigate = makeGSNav k } W.view)
|
||||||
|
--, (_4 , xK_v ) & \k -> (k, gridselectWorkspace wsGSConfig { gs_navigate = makeGSNav k } W.view)
|
||||||
|
--, (_4S , xK_v ) & \k -> (k, gridselectWorkspace wsGSConfig { gs_navigate = makeGSNav k } W.shift)
|
||||||
|
--, (_4 , xK_b ) & \k -> (k, goToSelected wGSConfig { gs_navigate = makeGSNav k })
|
||||||
|
]
|
||||||
|
where
|
||||||
|
_4 = mod4Mask
|
||||||
|
_C = controlMask
|
||||||
|
_S = shiftMask
|
||||||
|
_M = mod1Mask
|
||||||
|
_4C = _4 .|. _C
|
||||||
|
_4S = _4 .|. _S
|
||||||
|
_4M = _4 .|. _M
|
||||||
|
_4CM = _4 .|. _C .|. _M
|
||||||
|
_4SM = _4 .|. _S .|. _M
|
||||||
|
|
||||||
|
|
||||||
|
pagerConfig :: PagerConfig
|
||||||
|
pagerConfig = defaultPagerConfig
|
||||||
|
{ pc_font = myFont
|
||||||
|
, pc_cellwidth = 64
|
||||||
|
--, pc_cellheight = 36 -- TODO automatically keep screen aspect
|
||||||
|
--, pc_borderwidth = 1
|
||||||
|
--, pc_matchcolor = "#f0b000"
|
||||||
|
, pc_matchmethod = MatchPrefix
|
||||||
|
--, pc_colors = pagerWorkspaceColors
|
||||||
|
, pc_windowColors = windowColors
|
||||||
|
}
|
||||||
|
where
|
||||||
|
windowColors _ _ _ True _ = ("#ef4242","#ff2323")
|
||||||
|
windowColors wsf m c u wf = do
|
||||||
|
let def = defaultWindowColors wsf m c u wf
|
||||||
|
if m == False && wf == True
|
||||||
|
then ("#402020", snd def)
|
||||||
|
else def
|
||||||
|
|
||||||
|
horseConfig :: RhombusConfig
|
||||||
|
horseConfig = defaultRhombusConfig
|
||||||
|
{ rc_font = myFont
|
||||||
|
, rc_cellwidth = 64
|
||||||
|
--, rc_cellheight = 36 -- TODO automatically keep screen aspect
|
||||||
|
--, rc_borderwidth = 1
|
||||||
|
--, rc_matchcolor = "#f0b000"
|
||||||
|
, rc_matchmethod = MatchPrefix
|
||||||
|
--, rc_colors = pagerWorkspaceColors
|
||||||
|
--, rc_paint = myPaint
|
||||||
|
}
|
||||||
|
|
||||||
|
wGSConfig :: GSConfig Window
|
||||||
|
wGSConfig = defaultGSConfig
|
||||||
|
{ gs_cellheight = 20
|
||||||
|
, gs_cellwidth = 192
|
||||||
|
, gs_cellpadding = 5
|
||||||
|
, gs_font = myFont
|
||||||
|
, gs_navigate = navNSearch
|
||||||
|
}
|
||||||
|
|
||||||
|
-- wsGSConfig = defaultGSConfig
|
||||||
|
-- { gs_cellheight = 20
|
||||||
|
-- , gs_cellwidth = 64
|
||||||
|
-- , gs_cellpadding = 5
|
||||||
|
-- , gs_font = myFont
|
||||||
|
-- , gs_navigate = navNSearch
|
||||||
|
-- }
|
||||||
|
|
||||||
|
-- custom navNSearch
|
||||||
|
--makeGSNav :: (KeyMask, KeySym) -> TwoD a (Maybe a)
|
||||||
|
--makeGSNav esc = nav
|
||||||
|
-- where
|
||||||
|
-- nav = makeXEventhandler $ shadowWithKeymap keyMap navNSearchDefaultHandler
|
||||||
|
-- keyMap = Map.fromList
|
||||||
|
-- [ (esc , cancel)
|
||||||
|
-- , ((0,xK_Escape) , cancel)
|
||||||
|
-- , ((0,xK_Return) , select)
|
||||||
|
-- , ((0,xK_Left) , move (-1, 0) >> nav)
|
||||||
|
-- , ((0,xK_Right) , move ( 1, 0) >> nav)
|
||||||
|
-- , ((0,xK_Down) , move ( 0, 1) >> nav)
|
||||||
|
-- , ((0,xK_Up) , move ( 0,-1) >> nav)
|
||||||
|
-- , ((0,xK_BackSpace) , transformSearchString (\s -> if (s == "") then "" else init s) >> nav)
|
||||||
|
-- ]
|
||||||
|
-- -- The navigation handler ignores unknown key symbols, therefore we const
|
||||||
|
-- navNSearchDefaultHandler (_,s,_) = do
|
||||||
|
-- transformSearchString (++ s)
|
||||||
|
-- nav
|
||||||
|
|
||||||
|
|
||||||
|
(&) :: a -> (a -> c) -> c
|
||||||
|
(&) = flip ($)
|
||||||
|
|
||||||
|
allWorkspaceNames :: W.StackSet i l a sid sd -> X [i]
|
||||||
|
allWorkspaceNames ws =
|
||||||
|
return $ map W.tag (W.hidden ws) ++ [W.tag $ W.workspace $ W.current ws]
|
6
mv/5pkgs/xmonad-tv/Makefile
Normal file
6
mv/5pkgs/xmonad-tv/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.PHONY: ghci
|
||||||
|
ghci: shell.nix
|
||||||
|
nix-shell --command 'exec ghci -Wall'
|
||||||
|
|
||||||
|
shell.nix: xmonad.cabal
|
||||||
|
cabal2nix --shell . > $@
|
17
mv/5pkgs/xmonad-tv/xmonad.cabal
Normal file
17
mv/5pkgs/xmonad-tv/xmonad.cabal
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
Author: tv
|
||||||
|
Build-Type: Simple
|
||||||
|
Cabal-Version: >= 1.2
|
||||||
|
License: MIT
|
||||||
|
Name: xmonad-tv
|
||||||
|
Version: 0
|
||||||
|
|
||||||
|
Executable xmonad
|
||||||
|
Build-Depends:
|
||||||
|
base,
|
||||||
|
containers,
|
||||||
|
unix,
|
||||||
|
xmonad,
|
||||||
|
xmonad-contrib,
|
||||||
|
xmonad-stockholm
|
||||||
|
GHC-Options: -Wall -O3 -threaded -rtsopts
|
||||||
|
Main-Is: Main.hs
|
Loading…
Reference in New Issue
Block a user