1
0
mirror of https://github.com/alrayyes/dotfiles/ synced 2023-11-14 15:56:30 +00:00

Compare commits

..

10 Commits

Author SHA1 Message Date
Ryan Kes
2ea41ef558 feat: added shortcut for dmenuunicode 2020-11-28 14:27:15 +01:00
Ryan Kes
14402e59e4 docs: added libxft-bra as depedency 2020-11-28 14:26:54 +01:00
Ryan Kes
6a1bfa115e feat: set new default monospace font 2020-11-28 14:13:51 +01:00
Ryan Kes
7d925d1054 feat: added dependency library for st/dmenu/dwm 2020-11-28 14:09:32 +01:00
Ryan Kes
fcead6e50b feat: replace emacs-gcc with emacs again 2020-11-28 14:07:52 +01:00
Ryan Kes
fb61640641 fix: removed install package to fix script 2020-11-28 14:07:18 +01:00
Ryan Kes
aa3826776c feat: ignore .ccls-cache directory 2020-11-28 14:05:58 +01:00
Ryan Kes
a72816627d feat: added dmenu emoji selection script 2020-11-28 14:05:29 +01:00
Ryan Kes
c6da54fbb6 fix: ignore node_modules when linking 2020-11-27 06:40:29 +01:00
Ryan Kes
f16edddced feat(bspwm): start slack on login on desktop 2020-11-25 06:21:38 +01:00
9 changed files with 3489 additions and 10 deletions

View File

@ -91,8 +91,8 @@ A repository of my personal configuration files.
- [[https://www.google.com/get/noto/][Noto]]
- [[https://savannah.gnu.org/projects/unifont/][Unifont]]
** Libraries
*** Python
- [[http://scorreia.com/software/panflute/][Panflute]]
*** st / dmenu / dwm
- [[#+title: https://aur.archlinux.org/packages/libxft-bgra/][libxft-bgra]]
** LSP Backends
- [[https://github.com/mads-hartmann/bash-language-server][bash-language-server]]
- [[https://github.com/MaskRay/ccls][ccls]]

View File

@ -100,6 +100,7 @@ bspc rule -a Zathura state=tiled
bspc rule -a iceweasel desktop='^1'
bspc rule -a Brave-browser desktop='^1'
bspc rule -a bashtop desktop='^2'
bspc rule -a Slack='^3'
bspc rule -a Element desktop='^3'
bspc rule -a Element-Nightly desktop='^3'
bspc rule -a weechat desktop='^3'
@ -128,6 +129,7 @@ start_if_not_running element-desktop-nightly
if [ "$SCREENCOUNT" -eq 2 ]
start_shell_if_not_running castero
start_if_not_running slack
end
pkill -f cleanfullscreen

330
dmenu/.local/bin/dmenu-frequency Executable file
View File

@ -0,0 +1,330 @@
#!/usr/bin/env python
"""Dmenu launcher with history sorted by frecency.
Usage:
dmenu-frecency [--read-apps]
Options:
--read-apps rereads all .desktop files.
"""
from docopt import docopt
import os
import sys
import xdg.BaseDirectory
from xdg.DesktopEntry import DesktopEntry
from subprocess import Popen, PIPE
from datetime import datetime
from collections import defaultdict
import pickle
import re
import gzip
import json
import tempfile
import shlex
CONFIG_DIR = xdg.BaseDirectory.save_config_path('dmenu-frecency')
# Python 2 compatibility
try:
FileNotFoundError
except NameError:
FileNotFoundError = IOError
class Application:
def __init__(self, name, command_line, mtime=None, path=None, is_desktop=False):
self.name = name
self.path = path
self.command_line = command_line
self.is_desktop = is_desktop
self.show_command = False
if mtime is None:
self.mtime = datetime.now()
else:
self.mtime = mtime
def run(self):
if os.fork() == 0:
if self.path:
os.chdir(self.path)
os.execvp(os.path.expanduser(self.command_line[0]), self.command_line)
def __lt__(self, other):
return (self.is_desktop, self.mtime) < (other.is_desktop, other.mtime)
def __eq__(self, other):
return self.name == other.name
def __hash__(self):
return hash(self.name)
def __str__(self):
return "<Application: {} {!r}>".format(self.name, self.command_line)
STATE_VERSION = 4
def get_command(desktop_entry):
tokens = []
for token in shlex.split(desktop_entry.getExec()):
if token == '%i':
if desktop_entry.getIcon():
tokens.append('--icon')
tokens.append(desktop_entry.getIcon())
else:
i = 0
newtok = ""
nc = len(token)
while i < nc:
c = token[i]
if c == '%' and i < nc - 1:
i += 1
code = token[i]
if code == 'c' and desktop_entry.getName():
newtok += desktop_entry.getName()
elif code == '%':
newtok += '%'
else:
newtok += c
i += 1
if newtok:
tokens.append(newtok)
return tuple(tokens)
class LauncherState:
STATE_FILENAME = os.path.join(CONFIG_DIR, 'state')
def __init__(self, config):
self.version = STATE_VERSION
self.config = config
self.find_apps()
self.apps_generated_at = datetime.now()
self.visits = defaultdict(list)
self.visit_count = defaultdict(int)
self.app_last_visit = None
self.frecency_cache = {}
def apps_by_frecency(self):
app_last_visit = self.app_last_visit if self.config['preselect-last-visit'] else None
if app_last_visit is not None:
yield app_last_visit
for app, frec in sorted(self.frecency_cache.items(), key=lambda x: (-x[1], x[0])):
if app_last_visit is None or app_last_visit != app:
yield app
for app in self.sorted_apps:
if app not in self.frecency_cache:
if app_last_visit is None or app_last_visit != app:
yield app
def add_visit(self, app):
if not app.is_desktop and app.command_line in self.command_apps:
app = self.command_apps[app.command_line]
app.show_command = True
try:
self.sorted_apps.remove(app)
except ValueError:
pass # not in list
vs = self.visits[app]
now = datetime.now()
vs.append(now)
self.visit_count[app] += 1
self.visits[app] = vs[-self.config['frecency-visits']:]
self.app_last_visit = app if self.config['preselect-last-visit'] else None
def update_frecencies(self):
for app in self.visits.keys():
self.frecency_cache[app] = self.frecency(app)
def frecency(self, app):
points = 0
for v in self.visits[app]:
days_ago = (datetime.now() - v).days
if days_ago < 4:
points += 100
elif days_ago < 14:
points += 70
elif days_ago < 31:
points += 50
elif days_ago < 90:
points += 30
else:
points += 10
return int(self.visit_count[app] * points / len(self.visits[app]))
@classmethod
def load(cls, config):
try:
with gzip.open(cls.STATE_FILENAME, 'rb') as f:
obj = pickle.load(f)
version = getattr(obj, 'version', 0)
if version < STATE_VERSION:
new_obj = cls(config)
if version <= 1:
for app, vs in obj.visits.items():
vc = obj.visit_count[app]
app.is_desktop = True
new_obj.visit_count[app] = vc
new_obj.visits[app] = vs
new_obj.find_apps()
new_obj.clean_cache()
new_obj.update_frecencies()
new_obj.config = config
return new_obj
else:
obj.config = config
return obj
except FileNotFoundError:
return cls(config)
def save(self):
with tempfile.NamedTemporaryFile(
'wb',
dir=os.path.dirname(self.STATE_FILENAME),
delete=False) as tf:
tempname = tf.name
with gzip.open(tempname, 'wb') as gzipf:
pickle.dump(self, gzipf)
os.rename(tempname, self.STATE_FILENAME)
def find_apps(self):
self.apps = {}
self.command_apps = {}
if self.config['scan-desktop-files']:
for applications_directory in xdg.BaseDirectory.load_data_paths("applications"):
if os.path.exists(applications_directory):
for dirpath, dirnames, filenames in os.walk(applications_directory):
for f in filenames:
if f.endswith('.desktop'):
full_filename = os.path.join(dirpath, f)
self.add_desktop(full_filename)
if self.config['scan-path']:
for pathdir in os.environ["PATH"].split(os.pathsep):
pathdir = pathdir.strip('"')
if not os.path.isdir(pathdir):
continue
for f in os.listdir(pathdir):
filename = os.path.join(pathdir, f)
if os.path.isfile(filename) and os.access(filename, os.X_OK):
app = Application(
name=f,
command_line=(f,),
mtime=datetime.fromtimestamp(os.path.getmtime(filename)))
self.add_app(app)
self.sorted_apps = sorted(self.apps.values(), reverse=True)
def add_desktop(self, filename):
try:
d = DesktopEntry(filename)
if d.getHidden() or d.getNoDisplay() or d.getTerminal() or d.getType() != 'Application':
return
app = Application(
name=d.getName(),
command_line=get_command(d),
mtime=datetime.fromtimestamp(os.path.getmtime(filename)),
is_desktop=True)
if d.getPath():
app.path = d.getPath()
self.add_app(app)
except (xdg.Exceptions.ParsingError,
xdg.Exceptions.DuplicateGroupError,
xdg.Exceptions.DuplicateKeyError,
ValueError) as e:
sys.stderr.write("Failed to parse desktop file '{}': {!r}\n".format(filename, e))
def add_app(self, app):
if app.command_line not in self.command_apps:
self.apps[app.name] = app
self.command_apps[app.command_line] = app
def clean_cache(self):
for app in list(self.frecency_cache.keys()):
if app.is_desktop and app.name not in self.apps:
del self.frecency_cache[app]
if self.app_last_visit is not None and self.app_last_visit.name not in self.apps:
self.app_last_visit = None
class DmenuFrecency:
CONFIG_FILENAME = os.path.join(CONFIG_DIR, 'config.json')
DEFAULT_CONFIG = {
'dmenu': 'dmenu',
'dmenu-args': ['-i'],
'cache-days': 1,
'frecency-visits': 10,
'preselect-last-visit': False,
'scan-desktop-files': True,
'scan-path': False,
}
NAME_WITH_COMMAND = re.compile(r"(.+) \([^()]+\)")
def __init__(self, arguments):
self.read_apps = arguments['--read-apps']
self.load_config()
self.state = LauncherState.load(self.config)
assert self.state, "Failed to load state."
def load_config(self):
self.config = {}
self.config.update(self.DEFAULT_CONFIG)
try:
with open(self.CONFIG_FILENAME, 'r') as f:
self.config.update(json.load(f))
except FileNotFoundError:
with open(self.CONFIG_FILENAME, 'w') as f:
json.dump(self.config, f, sort_keys=True, indent=4)
f.write('\n')
def main(self):
if self.read_apps:
self.state.find_apps()
self.state.clean_cache()
self.state.save()
return
dmenu = Popen([self.config['dmenu']] + self.config['dmenu-args'], stdin=PIPE, stdout=PIPE)
for app in self.state.apps_by_frecency():
app_name = app.name.encode('utf-8')
dmenu.stdin.write(app_name)
if app.show_command and app.name != app.command_line[0]:
dmenu.stdin.write(" ({})".format(' '.join(app.command_line)).encode('utf-8'))
dmenu.stdin.write(b'\n')
stdout, stderr = dmenu.communicate()
result = stdout.decode('utf-8').strip()
if not result:
return
if result in self.state.apps:
app = self.state.apps[result]
else:
m = self.NAME_WITH_COMMAND.match(result)
if m and m.group(1) in self.state.apps:
app = self.state.apps[m.group(1)]
else:
app = Application(
name=result,
command_line=tuple(shlex.split(result)))
app.run()
self.state.add_visit(app)
self.state.update_frecencies()
if (datetime.now() - self.state.apps_generated_at).days >= self.config['cache-days']:
self.state.find_apps()
self.state.clean_cache()
self.state.save()
if __name__ == '__main__':
arguments = docopt(__doc__, version="0.1")
DmenuFrecency(arguments).main()

18
dmenu/.local/bin/dmenuunicode Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
# The famous "get a menu of emojis to copy" script.
# Get user selection via dmenu from emoji file.
chosen=$(cut -d ';' -f1 ~/.local/share/emoji | dmenu -i -l 30 | sed "s/ .*//")
# Exit if none chosen.
[ -z "$chosen" ] && exit
# If you run this command with an argument, it will automatically insert the
# character. Otherwise, show a message that the emoji has been copied.
if [ -n "$1" ]; then
xdotool type "$chosen"
else
echo "$chosen" | tr -d '\n' | xclip -selection clipboard
notify-send "'$chosen' copied to clipboard." &
fi

3127
dmenu/.local/share/emoji Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1227,7 +1227,7 @@
<alias>
<family>monospace</family>
<prefer>
<family>Courier New</family>
<family>Noto Color Emoji</family>
</prefer>
</alias>
-->

View File

@ -270,3 +270,5 @@ typings/
.yarn/cache
.pnp.*
# C
.ccls-cache/

View File

@ -3,9 +3,9 @@
# Prerequisite & inistalled apps
set prerequisiteApps bat broot brave caffeine-ng exa fslint fzf graphviz isync imagemagick lightdm-gtk-greeter mailcap neofetch npm pandoc-bin pamixer playerctl pulseaudio pulsemixer python pywal ripgrep stow sxiv tldr trayer udisks2 xwallpaper yarn xprop zathura
set prerequisiteFonts otf-nerd-fonts-fira-code noto-fonts ttf-unifont
set prerequisiteLibraries python-panflute
set prerequisiteLibraries libxft-bgra
set prerequisiteLsp bash-language-server ccls php-language-server python-language-server typescript-language-server-bin vscode-css-languageserver-bin vscode-html-languageserver-bin nodejs-intelephense
set configuredApps alacritty bspwm castero emacs-native-comp firejail git gnupg gtk lf dunst mpd mpv mpv-mpris ncmpcpp neomutt neovim picom redshift sxhkd tmux tuir weechat
set configuredApps alacritty bspwm castero emacs firejail git gnupg gtk lf dunst mpd mpv mpv-mpris ncmpcpp neomutt neovim picom redshift sxhkd tmux tuir weechat
set locales aspell-en hunspell-en_GB hunspell-en_US hunspell-nl
set golang go golangci-lint-bin
set shell shfmt shellcheck
@ -98,7 +98,7 @@ if [ ! -h ~/.config/mpv/scripts/mpris.so ]
ln -s /usr/lib/mpv/mpris.so ~/.config/mpv/scripts/mpris.so
end
for d in (find -- */ -maxdepth 0 -type d | cut -f1 -d '/')
for d in (find -- */ -maxdepth 0 -type d | grep -v node_modules | cut -f1 -d '/')
echo "Linking $d..."
stow -t "$HOME" "$d"
end
@ -135,7 +135,7 @@ if [ ! -d ~/.config/nvim/plugged ]
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
end
# Install Neovim plugins
# Install Neovim plugins
nvim +PlugInstall +qall
# Install Neovim coc extensions

View File

@ -77,14 +77,14 @@ super + Escape
pkill -USR1 -x sxhkd
# Misc apps
super + ctrl + alt + {l, n, r, s, c, v, k, a, u}
super + ctrl + alt + {l, n, r, s, c, v, k, a, u, e}
alacritty --class float,float -e {lf, neomutt, /usr/bin/newsboat, spt, castero, nvim, ~/.local/bin/calendar-and-wait, ~/.local/bin/audit, ~/.local/bin/update-arch}
super + ctrl + alt + {b, e, S}
{brave, emacs, spotify}
super + ctrl + alt + {t}
~/.local/bin/tldr-dmenu
super + ctrl + alt + {p}
playerctl play-pause
super + ctrl + alt + {m}
~/.local/bin/dmenuunicode
super + ctrl + alt + {w}
alacritty --class fullscreen,fullscreen -e ~/.config/polybar/bin/wttr-and-wait