Browse Source

WIP nnn configuration

master
Daniel Flanagan 1 month ago
parent
commit
3d2b35d2f0
Signed by: lytedev GPG Key ID: 5B2020A0F9921EF4
15 changed files with 251 additions and 299 deletions
  1. +1
    -0
      apps/kitty/kitty.conf
  2. +3
    -0
      apps/nnn/.gitignore
  3. +3
    -0
      apps/nnn/config.fish
  4. +231
    -0
      apps/nnn/plugins/preview
  5. +0
    -150
      apps/shell/bash/aliases.bash
  6. +0
    -7
      apps/shell/bash/autocompletions
  7. +0
    -9
      apps/shell/bash/profile
  8. +0
    -38
      apps/shell/bash/prompt
  9. +0
    -68
      apps/shell/bash/rc
  10. +4
    -2
      apps/shell/fish/aliases.fish
  11. +1
    -0
      apps/shell/fish/config.fish
  12. +0
    -25
      apps/shell/inputrc
  13. +3
    -0
      bin/setup-dotfiles
  14. +3
    -0
      env/arch-linux/provision.d/20-install-packages.bash
  15. +2
    -0
      readme.md

+ 1
- 0
apps/kitty/kitty.conf View File

@ -1,5 +1,6 @@
font_family Iosevka
allow_remote_control yes
repaint_delay 5
input_delay 1
sync_to_monitor yes


+ 3
- 0
apps/nnn/.gitignore View File

@ -0,0 +1,3 @@
.lastd
mounts
sessions

+ 3
- 0
apps/nnn/config.fish View File

@ -0,0 +1,3 @@
set -Ux NNN_OPTS EHacdrx
set -Ux NNN_COLORS 1234
set -Ux NNN_PLUG p:preview

+ 231
- 0
apps/nnn/plugins/preview View File

@ -0,0 +1,231 @@
#!/usr/bin/env sh
# Description: Terminal based file previewer
#
# Note: This plugin needs a "NNN_FIFO" to work. See man.
#
# Dependencies:
# - Supports 3 independent methods to preview with:
# - tmux (>=3.0), or
# - kitty with allow_remote_control on, or
# - $TERMINAL set to a terminal (it's xterm by default).
# - less or $PAGER
# - tree or exa or ls
# - mediainfo or file
# - mktemp
# - unzip
# - tar
# - man
# - optional: bat for code syntax highlighting
# - optional: kitty terminal or catimg for images
# - optional: scope.sh file viewer from ranger.
# To use:
# 1. drop scope.sh executable in $PATH
# 2. set/export $USE_SCOPE as 1
# - optional: pistol file viewer (https://github.com/doronbehar/pistol).
# To use:
# 1. install pistol
# 2. set/export $USE_PISTOL as 1
#
# Usage:
# You need to set a NNN_FIFO path and a key for the plugin with NNN_PLUG,
# then start `nnn`:
#
# $ nnn -a
#
# or
#
# $ NNN_FIFO=/tmp/nnn.fifo nnn
#
# Then in `nnn`, launch the `preview-tui` plugin.
#
# If you provide the same NNN_FIFO to all nnn instances, there will be a
# single common preview window. If you provide different FIFO path (e.g.
# with -a), they will be independent.
#
# The previews will be shown in a tmux split. If that isn't possible, it
# will try to use a kitty terminal split. And as a final fallback, a
# different terminal window will be used ($TERMINAL).
#
# Tmux and kitty users can configure $SPLIT to either "h" or "v" to set a
# 'h'orizontal split or a 'v'ertical split (as in, the line that splits the
# windows will be horizontal or vertical).
#
# Kitty users need `allow_remote_control` set to `yes`. To customize the
# window split, `enabled_layouts` has to be set to `all` or `splits` (the
# former is the default value). This terminal is also able to show images
# without extra dependencies.
#
# Shell: POSIX compliant
# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero
SPLIT="$SPLIT" # you can set a permanent split here
TERMINAL="$TERMINAL" # same goes for the terminal
USE_SCOPE="${USE_SCOPE:-0}"
USE_PISTOL="${USE_PISTOL:-0}"
PAGER="${PAGER:-less -R}"
[ "$PAGER" = "most" ] && PAGER="less -R"
if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
TERMINAL=tmux
elif [ -n "$KITTY_WINDOW_ID" ] && kitty @ ls >/dev/null 2>&1; then
TERMINAL=kitty
else
TERMINAL="${TERMINAL:-xterm}"
fi
if [ -z "$SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
SPLIT='h'
elif [ "$SPLIT" != 'h' ]; then
SPLIT='v'
fi
exists() {
which "$1" >/dev/null 2>&1
}
fifo_pager() {
cmd="$1"
shift
# We use a FIFO to access $PAGER PID in jobs control
tmpfifopath="${TMPDIR:-/tmp}/nnn-preview-tui-fifo.$$"
mkfifo "$tmpfifopath" || return
$PAGER < "$tmpfifopath" &
(
exec > "$tmpfifopath"
"$cmd" "$@" &
)
rm "$tmpfifopath"
}
# Binary file: show file info inside the pager
print_bin_info() {
printf -- "-------- \033[1;31mBinary file\033[0m --------\n"
if exists mediainfo; then
mediainfo "$1" 2>/dev/null
else
file -b "$1"
fi
}
preview_file () {
kill %- %+ 2>/dev/null && wait %- %+ 2>/dev/null
clear
# Trying to use pistol if it's available.
if [ "$USE_PISTOL" -ne 0 ] && exists pistol; then
fifo_pager pistol "$1"
return
fi
# Trying to use scope.sh if it's available.
if [ "$USE_SCOPE" -ne 0 ] && exists scope.sh; then
fifo_pager scope.sh "$1" "$cols" "$lines" "$(mktemp -d)" \
"True" 2>/dev/null
return
fi
# Detecting the exact type of the file: the encoding, mime type, and
# extension in lowercase.
encoding="$(file -Lb --mime-encoding -- "$1")"
mimetype="$(file -Lb --mime-type -- "$1")"
ext="${1##*.}"
if [ -n "$ext" ]; then
ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
fi
lines=$(($(tput lines)-1))
cols=$(tput cols)
# Otherwise, falling back to the defaults.
if [ -d "$1" ]; then
cd "$1" || return
if exists tree; then
fifo_pager tree -L 3 -F
elif exists exa; then
fifo_pager exa -G --colour=always 2>/dev/null
else
fifo_pager ls --color=always
fi
elif [ "$encoding" = "binary" ]; then
if [ "${mimetype%%/*}" = "image" ] ; then
if [ "$TERMINAL" = "kitty" ]; then
# Kitty terminal users can use the native image preview method.
kitty +kitten icat --silent --transfer-mode=stream --stdin=no \
"$1" &
elif exists catimg; then
catimg "$1"
elif exists viu; then
viu -t "$1"
else
fifo_pager print_bin_info "$1"
fi
elif [ "$mimetype" = "application/zip" ] ; then
fifo_pager unzip -l "$1"
elif [ "$ext" = "gz" ] || [ "$ext" = "bz2" ] ; then
fifo_pager tar -tvf "$1"
else
fifo_pager print_bin_info "$1"
fi
elif [ "$mimetype" = "text/troff" ] ; then
fifo_pager man -Pcat -l "$1"
else
if exists bat; then
fifo_pager bat --terminal-width="$cols" --paging=never --decorations=always --color=always \
"$1" 2>/dev/null
else
$PAGER "$1" &
fi
fi
}
if [ "$PREVIEW_MODE" ] ; then
if [ ! -r "$NNN_FIFO" ] ; then
echo "No FIFO available! (\$NNN_FIFO='$NNN_FIFO')" >&2
read -r
exit 1
fi
preview_file "$1"
# use cat instead of 'exec <' to avoid issues with dash shell
# shellcheck disable=SC2002
cat "$NNN_FIFO" |\
while read -r selection ; do
preview_file "$selection"
done
# Restoring the previous layout for kitty users. This will only work for
# kitty >= 0.18.0.
if [ "$TERMINAL" = "kitty" ]; then
kitty @ last-used-layout --no-response >/dev/null 2>&1
fi
exit 0
fi
if [ "$TERMINAL" = "tmux" ]; then
# tmux splits are inverted
if [ "$SPLIT" = "v" ]; then SPLIT="h"; else SPLIT="v"; fi
tmux split-window -e "NNN_FIFO=$NNN_FIFO" -e "PREVIEW_MODE=1" -d"$SPLIT" "$0" "$1"
elif [ "$TERMINAL" = "kitty" ]; then
# Setting the layout for the new window. It will be restored after the
# script ends.
kitty @ goto-layout splits >/dev/null
# Trying to use kitty's integrated window management as the split window.
# All environmental variables that will be used in the new window must
# be explicitly passed.
kitty @ launch --no-response --title "nnn preview" --keep-focus \
--cwd "$PWD" --env "PATH=$PATH" --env "NNN_FIFO=$NNN_FIFO" \
--env "PREVIEW_MODE=1" --env "PAGER=$PAGER" \
--env "USE_SCOPE=$USE_SCOPE" --env "SPLIT=$SPLIT" \
--env "USE_PISTOL=$USE_PISTOL" \
--location "${SPLIT}split" "$0" "$1" >/dev/null
else
PREVIEW_MODE=1 $TERMINAL -e "$0" "$1" &
fi

+ 0
- 150
apps/shell/bash/aliases.bash View File

@ -1,150 +0,0 @@
#!/usr/bin/env bash
# filesystem aliases
alias lx='ls -lXB' # order by filetype
alias lk='ls -lSr' # order by filesize reversed
alias lt='ls -ltr' # order by file modified time
alias lc='ls -ltcr' # order by filectime
alias lu='ls -ltur' # order by file access time
alias ls='ls -h --color --group-directories-first' # flat view w/ directories first
alias l='ls -h --color --group-directories-first' # same as above
alias ll='ls -lv --group-directories-first' # non-flat view
alias lm='ll | more'
alias lr='ll -R' # please don't - why is this even here...?
alias la='ll -A' # show all
alias tree='tree -Csuh'
alias f='fzf'
alias cp="rsync -ah --progress"
alias year="cal $(date +%Y)"
alias y="year"
# gets the newest function for the current directory (or the specified directory
# if one is provided)
function ltl() {
local d="${1-$PWD}"
unset -v l
for f in "$d"/*; do
[[ $f -nt $l ]] && [[ ! -d $f ]] && l="$f"
done
echo "$l"
}
function ltld() {
local d="${1-$PWD}"
unset -v l
for f in "$d"/*; do
[[ $f -nt $l ]] && [[ -d $f ]] && l="$f"
done
echo "$l"
}
alias vltl="vim \"\$(ltl)\""
alias cdltl="cd \"\$(ltld)\""
alias ltlv="vltl"
# navigation aliases
function c() {
if [[ -n $1 ]]; then
cd "${NICE_HOME}" || exit 1
else
cd "${NICE_HOME}" && cd "${1}" || exit 1
fi
}
alias cd..="cd .."
alias cdd="cd \"\$DOTFILES_PATH\"" # go to dotfiles
alias cde="cd \"\$ENV_PATH\"" # go to current dotfiles...? env
alias cdc="cd \"\$XDG_CONFIG_HOME\"" # go to ~/.config
alias cdn="cd \"\$NOTES_PATH\""
alias cdl="cd \"\$NICE_HOME/dl\""
alias cdg="cd \"\$NICE_HOME/games\""
# quick parent-directory aliases
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias .....="cd ../../../.."
alias ......="cd ../../../../.."
alias .......="cd ../../../../../.."
alias ........="cd ../../../../../../.."
alias .........="cd ../../../../../../../.."
# tmux aliases
# TODO: see if this can be worked around?
alias tmnew="tmux new -s"
alias tmls="tmux list-sessions"
alias tmatt="tmux attach -t"
alias tu="tmux attach -t utils || tmux new -s utils"
alias tdf="tmux attach -t dotfiles || tmux new -s dotfiles -c \"\$DOTFILES_PATH\""
alias tmon="tmux attach -t monitoring || tmux new -s monitoring"
alias tcom="tmux attach -t comms || tmux new -s comms"
alias tn="tmux attach -t notes || tmux new -s notes -c \"\$NOTES_PATH\""
alias tm="tmux attach -t music || tmux new -s music"
# git aliases
# TODO: make these git aliases in the gitconfig?
g() {
if [[ $# == '0' ]]; then
git status
else
git $*
fi
}
alias gs="git status"
alias gd="git diff"
alias gds="git diff --staged"
# alias gdv="git dv" # TODO: what is this?
alias gpl="git pull"
alias gp="git push"
alias gpa="git push --all && git push --tags"
alias gpt="git push && git push --tags"
alias gpf="git push --force-with-lease"
alias gac="git add -A && git commit"
alias gacnv="git add -A && git commit --no-verify"
alias gsur="git submodule update --remote"
alias glf="git ls-files"
alias gl="git log --pretty=format:\"%h %ad%x09%an%x09%s\" --date=short"
# docker aliases
alias dlf="docker logs --tail=500 -f"
alias dclf="docker-compose logs --tail=500 -f"
alias ctop="docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock quay.io/vektorlab/ctop:latest"
# misc aliases
alias p="ping 8.8.8.8"
alias C="clear && clear"
alias r="ranger"
alias rn="/usr/bin/watch -n 1"
alias sctl="sudo systemctl"
alias sctlu="systemctl --user"
alias logs="sudo journalctl"
alias logsr="sudo journalctl -r"
alias logsf="sudo journalctl -f"
alias bt="sudo bluetoothctl"
alias btctl="bt"
alias pbcopy="clip"
alias pbcopy="clip"
alias pt="htop -t" # experimental htop tree-view-by-default
alias resrc="source \$HOME/.bashrc"
alias redshift="redshift -r -l 39.0997:-94.5786 -t 6500K:2500K"
alias noredshift="killall redshift; redshift -P -O 5700"
alias gpmdpe="electron --app=/usr/share/gpmdp/resources/app.asar"
alias t="task"
alias sc="sc-im"
alias scs="sc-im \"\$NOTES_PATH/_scratch.sc\""
alias disks="lsblk && df -h"
alias dd="dd status=progress"
alias wifi="sudo nmtui"
alias pa="pulsemixer"
# games aliases
# this sometimes fixes steam dynamic library issues?
alias lsteam="LD_PRELOAD='/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1 /usr/$LIB/libgpg-error.so' steam"
# neomutt is better
alias mutt="neomutt"
# fsw aliases
alias fsw-mix-test="fsw \"mix test\" ./**/*.{ex,exs,erl,hrl,xrl,yrl}"
# weechat aliases
alias chat="WEECHAT_PASSPHRASE=\"\$(pass config/weechat-passphrase | head -n 1)\" weechat"

+ 0
- 7
apps/shell/bash/autocompletions View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
# autocompletions
complete -cf sudo
complete -cf man
complete -F _fzf_path_completion -o default -o bashdefault zathura

+ 0
- 9
apps/shell/bash/profile View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
# bash_profile is executed immediately after logging in
if [[ -f "$HOME/.bashrc" ]]; then
source "$HOME/.bashrc"
fi
export PATH="$HOME/.cargo/bin:$PATH"

+ 0
- 38
apps/shell/bash/prompt View File

@ -1,38 +0,0 @@
#!/usr/bin/env bash
COLOR_RESET='\[\e[0m\]'
# TODO: if root, background instead?
PROMPT_SUCCESS_COLOR='\[\e[0;34m\]'
PROMPT_FAILURE_COLOR='\[\e[0;31m\]'
DIR_COLOR='\[\e[0;35m\]'
MAX_PATH_PIECE_CHARS=${BASH_PROMPT_MAX_PATH_PIECE_CHARS:-3}
# prompt rendering functions
preprocess_pwd() {
p="$PWD"
[[ "$p" == "/" ]] && echo "/" && return 1
[[ "$p" == "${NICE_HOME}" ]] && echo "~" && return 0
# with ellipsis
#echo "$(<<< "$p" cut -c2- | awk '{split($0,p,"/");for(k in p){if(k==length(p)){printf "/%s",p[k]}else{if(length(p[k])>'"$((MAX_PATH_PIECE_CHARS+1))"'){printf "/%.'"$((MAX_PATH_PIECE_CHARS))"'s…",p[k]}else{printf "/%s",p[k]}}}}')"
# without ellipsis
echo "$(<<< "$p" cut -c2- | awk '{split($0,p,"/");for(k in p){if(k==length(p)){printf "/%s",p[k]}else{printf "/%.'"$MAX_PATH_PIECE_CHARS"'s",p[k]}}}')"
}
export -f "preprocess_pwd"
prompt_command_func()
{
RET=$?
history -a # commit history to prevent data loss from edge cases
# set the color of user@host based on the result of the previous command
if [[ $RET -eq 0 ]]; then
STATUS_COLOR=$PROMPT_SUCCESS_COLOR
else
STATUS_COLOR=$PROMPT_FAILURE_COLOR
fi
PS1="$STATUS_COLOR\u@\h$COLOR_RESET $DIR_COLOR$(preprocess_pwd)$COLOR_RESET "
}
export -f "prompt_command_func"
export PROMPT_COMMAND="prompt_command_func"

+ 0
- 68
apps/shell/bash/rc View File

@ -1,68 +0,0 @@
#!/usr/bin/env bash
export XDG_CONFIG_HOME="$HOME/.config"
export DOTFILES_PATH="$XDG_CONFIG_HOME/lytedev-dotfiles"
. "$DOTFILES_PATH/bin/prelude"
[[ ! $- == *i* ]] && return # stop parsing on a non-interactive shell
. "$DOTFILES_PATH/apps/shell/bash/aliases.bash"
. "$DOTFILES_PATH/apps/shell/bash/autocompletions"
. "$DOTFILES_PATH/apps/shell/bash/prompt"
stty -ixon # disable ctrl-s terminal freezing
bind -f "$DOTFILES_PATH/apps/shell/inputrc" # load our key
# load our vconsole colors if in a tty
if [[ "${TERM%%-*}" = 'linux' ]]; then
c="$DOTFILES_PATH/bin/lib/colors/vconsole"
[[ -s "$c" ]] && . "$c"
fi
# prevents some Java GUI apps from not working or rendering properly due to
# using wacky window managers
export _JAVA_AWT_WM_NONREPARENTING=1
export ERL_AFLAGS="-kernel shell_history enabled -kernel shell_history_file_bytes 1024000"
has_command fd && export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
export LS_COLORS='ow=01;36;40'
export LESS="-x2" # less tab size of 2 spaces
export TERMINAL="kitty"
export BROWSER="firefox-developer-edition"
export HISTFILESIZE="10000000" # "unlimited" history
export HISTSIZE="10000000" # "unlimited" history
export HISTCONTROL=ignoreboth # ignore duplicates and commands starting with space (" ")
shopt -s globstar # allow ** recursive wildcard globbing
# prevents binds or commands pulling from history from insta-sending, and
# instead places them in the readline for editing
shopt -s histverify
shopt -s histappend # always _append_ to bash history
shopt -s cmdhist # ensure command history is comprised of single lines
HISTIGNORE='ls:ll:la' # ignore certain commands
# set our EDITOR to neovim if we've got it
export EDITOR="vim"
if has_command nvim; then
alias vim="nvim"
alias ovim="\\vim"
export EDITOR="nvim"
fi
# load a per-device config last so anything can be overridden
. maybe_source_env_file bashrc
. maybe_source_env_file .hidden/bashrc
# create paths we kind of expect to exist in some scripts
mkdir -p "$NOTES_PATH" "$SCROTS_PATH" "$USER_LOGS_PATH"
# open nice home instead if we're opening at home
if [ "$PWD" = "$HOME" ] || [ "$PWD" = "$NICE_HOME" ]; then
cd "$NICE_HOME" || cd || return
fi
# if [[ -d "$HOME/.asdf/" ]] && [[ -f "$HOME/.asdf/asdf.sh" ]]; then
# . "$HOME/.asdf/asdf.sh"
# elif [[ -d /opt/asdf-vm/ ]] && [[ -f /opt/asdf-vm/asdf.sh ]]; then
# . "/opt/asdf-vm/asdf.sh"
# fi
# [ -f ~/.fzf.bash ] && source ~/.fzf.bash

+ 4
- 2
apps/shell/fish/aliases.fish View File

@ -13,6 +13,7 @@ alias la 'll -A' # show all
# TODO: cat > bat
alias tree 'tree -Csuh'
alias f fzf
alias r 'nnn -P p'
alias t "tmux"
alias rcp 'rsync -r -ah --progress'
@ -37,7 +38,8 @@ function c --description "Quickly jump to a subdirectory of NICE_HOME (or just t
end
end
complete --erase --command c
complete --command c -a "(pushd $NICE_HOME && fd . . --max-depth 1 --min-depth 1 && popd)"
complete --command c -a \
"(pushd $NICE_HOME && fd . . --max-depth 1 --min-depth 1 -x ls -p && popd)"
alias cd.. "d .."
alias cdd "d $DOTFILES_PATH" # go to dotfiles
@ -79,7 +81,7 @@ function pp
end
alias p "ping 8.8.8.8"
alias C "clear && clear" # TODO: this should clear a tmux pane's scrollback/logs
alias r "nnn"
alias l "nnn"
alias sctl "sudo systemctl"
alias sctlu "systemctl --user"
alias bt "sudo bluetoothctl" # TODO: a vi-like tui for bluetooth would be great


+ 1
- 0
apps/shell/fish/config.fish View File

@ -5,6 +5,7 @@ set -Ux DOTFILES_PATH $XDG_CONFIG_HOME/lytedev-dotfiles
set -Ux ENV_PATH $HOME/.env
source $DOTFILES_PATH/apps/shell/fish/paths.fish
source $DOTFILES_PATH/apps/nnn/config.fish
status --is-interactive || exit


+ 0
- 25
apps/shell/inputrc View File

@ -1,25 +0,0 @@
set editing-mode vi
# bindings
"\eOd": backward-word
"\eOc": forward-word
"\C-p": history-search-backward
"\C-n": history-search-forward
"\C-a": beginning-of-line
"\C-e": end-of-line
"\C-d": delete-char
"\e\C-p": " \C-e\C-u`__fzf_cd__`\n"
"\e\C-s": " \C-e\C-uscwd\n"
"\e\C-g": " \C-e\C-u. gcwd\n"
# vi settings
$if mode=vi
set keymap vi-insert
"jk": vi-movement-mode
"Jk": vi-movement-mode
"JK": vi-movement-mode
"jj": vi-movement-mode
"Jj": vi-movement-mode
"JJ": vi-movement-mode
$endif

+ 3
- 0
bin/setup-dotfiles View File

@ -64,6 +64,9 @@ links=(
# libinput configuration
"apps/de/libinput/gestures.conf" "$XDG_CONFIG_HOME/libinput-gestures.conf"
# nnn configuration
"apps/nnn/" "$XDG_CONFIG_HOME/nnn"
# kakoune editor configuration
"apps/kak/" "$XDG_CONFIG_HOME/kak"


+ 3
- 0
env/arch-linux/provision.d/20-install-packages.bash View File

@ -50,7 +50,9 @@ yay -Sy \
dmenu `# Application Launcher` \
ripgrep `# Code Search Utilities` \
fd `# File Search` \
exa `# Better ls` \
sd `# Easy Find/Replace` \
bat `# Better Cat` \
fzf `# Fuzzy File Finder` \
htop `# Process Management and System Resources Monitoring` \
openssh mosh `# Remote Access` \
@ -92,4 +94,5 @@ yay -Sy \
diff-so-fancy `# Fancy Diffs` \
oath-toolkit `# One-Time Passwords` \
sysstat `# System Statistics` \
man-db man-pages `# Come On, Man!` \
ripcord `# Discord and Slack Client`

+ 2
- 0
readme.md View File

@ -16,6 +16,8 @@ curl -s -L https://git.lyte.dev/lytedev/dotfiles/raw/branch/master/bin/init-dotf
# To Do
+ nnn FCOLORS
+ nvim statusline overflow
+ **Learn to use `journalctl`**
+ Vim sessions?
+ Fix sway workspaces on desktop


Loading…
Cancel
Save