mirror of
https://github.com/alrayyes/dotfiles/
synced 2023-11-14 15:56:30 +00:00
Compare commits
10 Commits
64bf663caf
...
2ea41ef558
Author | SHA1 | Date | |
---|---|---|---|
|
2ea41ef558 | ||
|
14402e59e4 | ||
|
6a1bfa115e | ||
|
7d925d1054 | ||
|
fcead6e50b | ||
|
fb61640641 | ||
|
aa3826776c | ||
|
a72816627d | ||
|
c6da54fbb6 | ||
|
f16edddced |
@ -91,8 +91,8 @@ A repository of my personal configuration files.
|
|||||||
- [[https://www.google.com/get/noto/][Noto]]
|
- [[https://www.google.com/get/noto/][Noto]]
|
||||||
- [[https://savannah.gnu.org/projects/unifont/][Unifont]]
|
- [[https://savannah.gnu.org/projects/unifont/][Unifont]]
|
||||||
** Libraries
|
** Libraries
|
||||||
*** Python
|
*** st / dmenu / dwm
|
||||||
- [[http://scorreia.com/software/panflute/][Panflute]]
|
- [[#+title: https://aur.archlinux.org/packages/libxft-bgra/][libxft-bgra]]
|
||||||
** LSP Backends
|
** LSP Backends
|
||||||
- [[https://github.com/mads-hartmann/bash-language-server][bash-language-server]]
|
- [[https://github.com/mads-hartmann/bash-language-server][bash-language-server]]
|
||||||
- [[https://github.com/MaskRay/ccls][ccls]]
|
- [[https://github.com/MaskRay/ccls][ccls]]
|
||||||
|
@ -100,6 +100,7 @@ bspc rule -a Zathura state=tiled
|
|||||||
bspc rule -a iceweasel desktop='^1'
|
bspc rule -a iceweasel desktop='^1'
|
||||||
bspc rule -a Brave-browser desktop='^1'
|
bspc rule -a Brave-browser desktop='^1'
|
||||||
bspc rule -a bashtop desktop='^2'
|
bspc rule -a bashtop desktop='^2'
|
||||||
|
bspc rule -a Slack='^3'
|
||||||
bspc rule -a Element desktop='^3'
|
bspc rule -a Element desktop='^3'
|
||||||
bspc rule -a Element-Nightly desktop='^3'
|
bspc rule -a Element-Nightly desktop='^3'
|
||||||
bspc rule -a weechat desktop='^3'
|
bspc rule -a weechat desktop='^3'
|
||||||
@ -128,6 +129,7 @@ start_if_not_running element-desktop-nightly
|
|||||||
|
|
||||||
if [ "$SCREENCOUNT" -eq 2 ]
|
if [ "$SCREENCOUNT" -eq 2 ]
|
||||||
start_shell_if_not_running castero
|
start_shell_if_not_running castero
|
||||||
|
start_if_not_running slack
|
||||||
end
|
end
|
||||||
|
|
||||||
pkill -f cleanfullscreen
|
pkill -f cleanfullscreen
|
||||||
|
330
dmenu/.local/bin/dmenu-frequency
Executable file
330
dmenu/.local/bin/dmenu-frequency
Executable 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
18
dmenu/.local/bin/dmenuunicode
Executable 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
3127
dmenu/.local/share/emoji
Normal file
File diff suppressed because it is too large
Load Diff
@ -1227,7 +1227,7 @@
|
|||||||
<alias>
|
<alias>
|
||||||
<family>monospace</family>
|
<family>monospace</family>
|
||||||
<prefer>
|
<prefer>
|
||||||
<family>Courier New</family>
|
<family>Noto Color Emoji</family>
|
||||||
</prefer>
|
</prefer>
|
||||||
</alias>
|
</alias>
|
||||||
-->
|
-->
|
||||||
|
@ -270,3 +270,5 @@ typings/
|
|||||||
.yarn/cache
|
.yarn/cache
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
# C
|
||||||
|
.ccls-cache/
|
||||||
|
6
install
6
install
@ -3,9 +3,9 @@
|
|||||||
# Prerequisite & inistalled apps
|
# 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 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 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 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 locales aspell-en hunspell-en_GB hunspell-en_US hunspell-nl
|
||||||
set golang go golangci-lint-bin
|
set golang go golangci-lint-bin
|
||||||
set shell shfmt shellcheck
|
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
|
ln -s /usr/lib/mpv/mpris.so ~/.config/mpv/scripts/mpris.so
|
||||||
end
|
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..."
|
echo "Linking $d..."
|
||||||
stow -t "$HOME" "$d"
|
stow -t "$HOME" "$d"
|
||||||
end
|
end
|
||||||
|
@ -77,14 +77,14 @@ super + Escape
|
|||||||
pkill -USR1 -x sxhkd
|
pkill -USR1 -x sxhkd
|
||||||
|
|
||||||
# Misc apps
|
# 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}
|
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}
|
super + ctrl + alt + {b, e, S}
|
||||||
{brave, emacs, spotify}
|
{brave, emacs, spotify}
|
||||||
super + ctrl + alt + {t}
|
super + ctrl + alt + {t}
|
||||||
~/.local/bin/tldr-dmenu
|
~/.local/bin/tldr-dmenu
|
||||||
super + ctrl + alt + {p}
|
super + ctrl + alt + {m}
|
||||||
playerctl play-pause
|
~/.local/bin/dmenuunicode
|
||||||
super + ctrl + alt + {w}
|
super + ctrl + alt + {w}
|
||||||
alacritty --class fullscreen,fullscreen -e ~/.config/polybar/bin/wttr-and-wait
|
alacritty --class fullscreen,fullscreen -e ~/.config/polybar/bin/wttr-and-wait
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user