first commit
This commit is contained in:
21
.config/alacritty/alacritty.toml
Normal file
21
.config/alacritty/alacritty.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[env]
|
||||
TERM = "xterm-256color"
|
||||
|
||||
[font]
|
||||
size = 16
|
||||
|
||||
[font.normal]
|
||||
family = "Monospace"
|
||||
style = "Regular"
|
||||
|
||||
[font.offset]
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
[window]
|
||||
opacity = 0.97
|
||||
|
||||
|
||||
[general]
|
||||
import = ["/home/opal/.config/alacritty/theme.toml"]
|
||||
|
||||
28
.config/alacritty/theme.toml
Normal file
28
.config/alacritty/theme.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
# Colors (Nord)
|
||||
|
||||
# Default colors
|
||||
[colors.primary]
|
||||
background = '#2E3440'
|
||||
foreground = '#D8DEE9'
|
||||
|
||||
# Normal colors
|
||||
[colors.normal]
|
||||
black = '#3B4252'
|
||||
red = '#BF616A'
|
||||
green = '#A3BE8C'
|
||||
yellow = '#EBCB8B'
|
||||
blue = '#81A1C1'
|
||||
magenta = '#B48EAD'
|
||||
cyan = '#88C0D0'
|
||||
white = '#E5E9F0'
|
||||
|
||||
# Bright colors
|
||||
[colors.bright]
|
||||
black = '#4C566A'
|
||||
red = '#BF616A'
|
||||
green = '#A3BE8C'
|
||||
yellow = '#EBCB8B'
|
||||
blue = '#81A1C1'
|
||||
magenta = '#B48EAD'
|
||||
cyan = '#8FBCBB'
|
||||
white = '#ECEFF4'
|
||||
49
.config/dunst/dunstrc
Normal file
49
.config/dunst/dunstrc
Normal file
@@ -0,0 +1,49 @@
|
||||
[global]
|
||||
monitor = 0
|
||||
follow = keyboard
|
||||
indicate_hidden = yes
|
||||
shrink = no
|
||||
separator_height = 0
|
||||
padding = 16
|
||||
horizontal_padding = 24
|
||||
frame_width = 2
|
||||
sort = no
|
||||
idle_threshold = 120
|
||||
font = Noto Sans 8
|
||||
line_height = 4
|
||||
markup = full
|
||||
format = "<b>%s</b>\n%b"
|
||||
alignment = left
|
||||
show_age_threshold = 60
|
||||
word_wrap = yes
|
||||
ignore_newline = no
|
||||
stack_duplicates = false
|
||||
hide_duplicate_count = yes
|
||||
show_indicators = no
|
||||
icon_position = off
|
||||
sticky_history = yes
|
||||
history_length = 20
|
||||
browser = /usr/bin/icecat -new-tab
|
||||
always_run_script = true
|
||||
title = Dunst
|
||||
class = Dunst
|
||||
close = ctrl+space
|
||||
close_all = ctrl+shift+space
|
||||
history = ctrl+grave
|
||||
context = ctrl+shift+period
|
||||
|
||||
[urgency_low]
|
||||
background = "#2f343f"
|
||||
foreground = "#d8dee8"
|
||||
timeout = 2
|
||||
|
||||
[urgency_normal]
|
||||
background = "#2f343f"
|
||||
foreground = "#d8dee8"
|
||||
timeout = 4
|
||||
|
||||
[urgency_critical]
|
||||
background = "#2f343f"
|
||||
foreground = "#d8dee8"
|
||||
frame_color = "#bf616a"
|
||||
timeout = 0
|
||||
3
.config/foot/foot.ini
Normal file
3
.config/foot/foot.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[main]
|
||||
font=monospace:size=18
|
||||
term=xterm-256color
|
||||
2
.config/gtk-3.0/settings.ini
Normal file
2
.config/gtk-3.0/settings.ini
Normal file
@@ -0,0 +1,2 @@
|
||||
[Settings]
|
||||
gtk-icon-theme-name = Papirus
|
||||
7
.config/lf/lfrc
Normal file
7
.config/lf/lfrc
Normal file
@@ -0,0 +1,7 @@
|
||||
# Basic vars
|
||||
set ifs "\n"
|
||||
set scrolloff 10
|
||||
set icons
|
||||
set period 1
|
||||
set hiddenfiles ".*:*.aux:*.log:*.bbl:*.bcf:*.blg:*.run.xml"
|
||||
set autoquit true
|
||||
46
.config/newsboat/config
Normal file
46
.config/newsboat/config
Normal file
@@ -0,0 +1,46 @@
|
||||
#show-read-feeds no
|
||||
auto-reload yes
|
||||
|
||||
bind-key j down
|
||||
bind-key k up
|
||||
bind-key j next articlelist
|
||||
bind-key k prev articlelist
|
||||
bind-key J next-feed articlelist
|
||||
bind-key K prev-feed articlelist
|
||||
bind-key G end
|
||||
bind-key g home
|
||||
bind-key d pagedown
|
||||
bind-key u pageup
|
||||
bind-key l open
|
||||
bind-key h quit
|
||||
bind-key a toggle-article-read
|
||||
bind-key n next-unread
|
||||
bind-key N prev-unread
|
||||
bind-key D pb-download
|
||||
bind-key U show-urls
|
||||
bind-key x pb-delete
|
||||
|
||||
color listnormal cyan default
|
||||
color listfocus black yellow standout bold
|
||||
color listnormal_unread blue default
|
||||
color listfocus_unread yellow default bold
|
||||
color info red black bold
|
||||
color article white default bold
|
||||
|
||||
highlight all "---.*---" yellow
|
||||
highlight feedlist ".*(0/0))" black
|
||||
highlight article "(^Feed:.*|^Title:.*|^Author:.*)" cyan default bold
|
||||
highlight article "(^Link:.*|^Date:.*)" default default
|
||||
highlight article "https?://[^ ]+" green default
|
||||
highlight article "^(Title):.*$" blue default
|
||||
highlight article "\\[[0-9][0-9]*\\]" magenta default bold
|
||||
highlight article "\\[image\\ [0-9]+\\]" green default bold
|
||||
highlight article "\\[embedded flash: [0-9][0-9]*\\]" green default bold
|
||||
highlight article ":.*\\(link\\)$" cyan default
|
||||
highlight article ":.*\\(image\\)$" blue default
|
||||
highlight article ":.*\\(embedded flash\\)$" magenta default
|
||||
|
||||
#urls-source "ttrss"
|
||||
#ttrss-url "https://rss.opal.sh/tt-rss/"
|
||||
#ttrss-login "ryan"
|
||||
#ttrss-passwordeval "gopass show -o self-hosted/rss.opal.sh"
|
||||
18
.config/newsboat/urls
Normal file
18
.config/newsboat/urls
Normal file
@@ -0,0 +1,18 @@
|
||||
---Reddit---
|
||||
https://www.reddit.com/r/stupidpol/.rss
|
||||
---News---
|
||||
https://thegrayzone.com/rss
|
||||
https://multipolarista.com/rss
|
||||
https://www.telesurenglish.net/feed/
|
||||
https://theintercept.com/feed/
|
||||
---Tech---
|
||||
https://landchad.net/rss.xml
|
||||
https://videos.lukesmith.xyz/feeds/videos.xml?videoChannelId=2 "~Luke Smith (Videos)"
|
||||
https://pluralistic.net/feed/
|
||||
https://blog.privacyguides.org/feed_rss_created.xml
|
||||
---Podcasts---
|
||||
https://feeds.simplecast.com/dCXMIpJz "Last Podcast On the Left"
|
||||
http://feeds.soundcloud.com/users/soundcloud:users:572119410/sounds.rss podcasts "Fall of Civilziation"
|
||||
https://feeds.feedburner.com/dancarlin/history?format=xml podcasts "Hardcore History"
|
||||
|
||||
https://www.darkdescentrecords.com/shop/shop/rss
|
||||
8
.config/nvim/init.lua
Normal file
8
.config/nvim/init.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
-- ~/.config/nvim/init.lua
|
||||
vim.o.number = true
|
||||
vim.o.relativenumber = true
|
||||
vim.o.clipboard = "unnamedplus"
|
||||
|
||||
vim.cmd [[highlight Normal guibg=NONE ctermbg=NONE]]
|
||||
vim.cmd [[highlight NormalNC guibg=NONE ctermbg=NONE]]
|
||||
vim.cmd [[highlight EndOfBuffer guibg=NONE ctermbg=NONE]]
|
||||
167
.config/qutebrowser/autoconfig.yml
Normal file
167
.config/qutebrowser/autoconfig.yml
Normal file
@@ -0,0 +1,167 @@
|
||||
# If a config.py file exists, this file is ignored unless it's explicitly loaded
|
||||
# via config.load_autoconfig(). For more information, see:
|
||||
# https://github.com/qutebrowser/qutebrowser/blob/main/doc/help/configuring.asciidoc#loading-autoconfigyml
|
||||
# DO NOT edit this file by hand, qutebrowser will overwrite it.
|
||||
# Instead, create a config.py - see :help for details.
|
||||
|
||||
config_version: 2
|
||||
settings:
|
||||
content.blocking.method:
|
||||
global: both
|
||||
content.javascript.enabled:
|
||||
'*://*.01.emailinboundprocessing.eu/*': true
|
||||
'*://*.127.0.0.1/*': true
|
||||
'*://*.4chanlit.fandom.com/*': true
|
||||
'*://*.account.proton.me/*': true
|
||||
'*://*.account.protonvpn.com/*': true
|
||||
'*://*.ancientdead.com/*': true
|
||||
'*://*.app.netdata.cloud/*': true
|
||||
'*://*.app.simplelogin.io/*': true
|
||||
'*://*.askubuntu.com/*': true
|
||||
'*://*.babeground.com/*': true
|
||||
'*://*.babeground.net/*': true
|
||||
'*://*.babegrounds.live/*': true
|
||||
'*://*.bandcamp.com/*': true
|
||||
'*://*.chmodcommand.com/*': true
|
||||
'*://*.codeberg.org/*': true
|
||||
'*://*.confluence.atg-corp.com/*': false
|
||||
'*://*.crontab.guru/*': true
|
||||
'*://*.customer.xfinity.com/*': true
|
||||
'*://*.demo.uptime.kuma.pet/*': true
|
||||
'*://*.docs.google.com/*': true
|
||||
'*://*.drop.download/*': true
|
||||
'*://*.duckduckgo.com/*': true
|
||||
'*://*.features.jellyfin.org/*': true
|
||||
'*://*.flathub.org/*': true
|
||||
'*://*.fleet.linuxserver.io/*': true
|
||||
'*://*.fmovies.to/*': true
|
||||
'*://*.framatube.org/*': true
|
||||
'*://*.get.adobe.com/*': true
|
||||
'*://*.github.com/*': true
|
||||
'*://*.gitlab.com/*': true
|
||||
'*://*.goauthentik.io/*': true
|
||||
'*://*.greyzone.com/*': true
|
||||
'*://*.heretic.camp/*': true
|
||||
'*://*.html.duckduckgo.com/*': true
|
||||
'*://*.hub.docker.com/*': true
|
||||
'*://*.id.atlassian.com/*': true
|
||||
'*://*.idcs-3359adb31e35415e8c1729c5c8098c6d.identity.oraclecloud.com/*': true
|
||||
'*://*.imgflip.com/*': true
|
||||
'*://*.inv.odyssey346.dev/*': true
|
||||
'*://*.jf.opal.sh/*': true
|
||||
'*://*.jira.atg-corp.com/*': true
|
||||
'*://*.layoffs.fyi/*': true
|
||||
'*://*.learningnetwork.cisco.com/*': true
|
||||
'*://*.listen.20buckspin.com/*': true
|
||||
'*://*.localhost/*': true
|
||||
'*://*.login.seattle.gov/*': true
|
||||
'*://*.login.xfinity.com/*': true
|
||||
'*://*.looking-glass.io/*': true
|
||||
'*://*.lotrproject.com/*': true
|
||||
'*://*.mail.proton.me/*': true
|
||||
'*://*.main.realsecure.flyingcroc.net/*': true
|
||||
'*://*.metalodyssey.8merch.com/*': true
|
||||
'*://*.my.uscis.gov/*': true
|
||||
'*://*.my.vultr.com/*': true
|
||||
'*://*.myaccount.standingstonegames.com/*': true
|
||||
'*://*.myutilities.seattle.gov/*': true
|
||||
'*://*.nagios.realsecure.flyingcroc.net/*': true
|
||||
'*://*.netbox.realsecure.flyingcroc.net/*': true
|
||||
'*://*.online.adp.com/*': true
|
||||
'*://*.onlinebanking.becu.org/*': true
|
||||
'*://*.onyxboox.com/*': true
|
||||
'*://*.openscrobbler.com/*': true
|
||||
'*://*.payments.xfinity.com/*': true
|
||||
'*://*.portainer.opal.sh/*': true
|
||||
'*://*.protesilaos.com/*': true
|
||||
'*://*.proton.me/*': true
|
||||
'*://*.rateyourmusic.com/*': true
|
||||
'*://*.register.be.xfinity.com/*': false
|
||||
'*://*.reverb.com/*': true
|
||||
'*://*.sack.realsecure.flyingcroc.net/*': true
|
||||
'*://*.search.brave.com/*': true
|
||||
'*://*.seattle.bibliocommons.com/*': true
|
||||
'*://*.seattle.craigslist.org/*': true
|
||||
'*://*.shop.bulletproof.com/*': true
|
||||
'*://*.spl.overdrive.com/*': true
|
||||
'*://*.stackoverflow.com/*': true
|
||||
'*://*.stash.atg-corp.com/*': true
|
||||
'*://*.superuser.com/*': true
|
||||
'*://*.support-acquia.force.com/*': true
|
||||
'*://*.thecirclemusic.gr/*': true
|
||||
'*://*.thegrayzone.com/*': true
|
||||
'*://*.translate.google.com/*': true
|
||||
'*://*.twitter.com/*': true
|
||||
'*://*.unix.stackexchange.com/*': true
|
||||
'*://*.uploadev.org/*': true
|
||||
'*://*.utilities-self-service.ebill.seattle.gov/*': true
|
||||
'*://*.veganmenshoes.com/*': true
|
||||
'*://*.vid.puffyan.us/*': true
|
||||
'*://*.wooddove.fciis.net/*': true
|
||||
'*://*.www.20buckspin.com/*': true
|
||||
'*://*.www.airplane.dev/*': true
|
||||
'*://*.www.amazon.com/*': true
|
||||
'*://*.www.astound.com/*': true
|
||||
'*://*.www.budgetbytes.com/*': true
|
||||
'*://*.www.calculator.net/*': true
|
||||
'*://*.www.carhartt.com/*': true
|
||||
'*://*.www.dancarlin.com/*': true
|
||||
'*://*.www.drmartens.com/*': true
|
||||
'*://*.www.duluthtrading.com/*': true
|
||||
'*://*.www.easyime.com/*': true
|
||||
'*://*.www.ebay.com/*': true
|
||||
'*://*.www.filson.com/*': true
|
||||
'*://*.www.foodnetwork.com/*': true
|
||||
'*://*.www.geoguessr.com/*': true
|
||||
'*://*.www.goodreads.com/*': true
|
||||
'*://*.www.google.com/*': true
|
||||
'*://*.www.harddrivesdirect.com/*': true
|
||||
'*://*.www.knoll.com/*': true
|
||||
'*://*.www.kobo.com/*': true
|
||||
'*://*.www.last.fm/*': true
|
||||
'*://*.www.lastpodcastontheleft.com/*': true
|
||||
'*://*.www.lotro.com/*': true
|
||||
'*://*.www.metal-archives.com/*': true
|
||||
'*://*.www.mmorpg.com/*': true
|
||||
'*://*.www.moddb.com/*': true
|
||||
'*://*.www.netaddictionrecovery.com/*': true
|
||||
'*://*.www.nightshiftmerch.com/*': true
|
||||
'*://*.www.openstreetmap.org/*': true
|
||||
'*://*.www.patagonia.com/*': true
|
||||
'*://*.www.paypal.com/*': true
|
||||
'*://*.www.raspberrypi.com/*': true
|
||||
'*://*.www.reddit.com/*': true
|
||||
'*://*.www.seattle.gov/*': true
|
||||
'*://*.www.startpage.com/*': true
|
||||
'*://*.www.thisisclassicalguitar.com/*': true
|
||||
'*://*.www.vegetarian-shoes.co.uk/*': true
|
||||
'*://*.www.vultr.com/*': true
|
||||
'*://*.www.wills-vegan-store.com/*': true
|
||||
'*://*.www.xfinity.com/*': true
|
||||
'*://*.www.youtube.com/*': true
|
||||
'*://*.www.zillow.com/*': true
|
||||
'*://chatgpt.com/*': true
|
||||
'*://digital.fidelity.com/*': true
|
||||
'*://gethomepage.dev/*': true
|
||||
'*://git.opal.sh/*': true
|
||||
'*://jf.opal.sh/*': true
|
||||
'*://jsonformatter.curiousconcept.com/*': true
|
||||
'*://lemmygrad.ml/*': true
|
||||
'*://login.becu.org/*': true
|
||||
'*://myaccounts.capitalone.com/*': true
|
||||
'*://rateyourmusic.com/*': true
|
||||
'*://revelationofdoom.com/*': true
|
||||
'*://safereddit.com/*': true
|
||||
'*://verified.capitalone.com/*': true
|
||||
'*://wiki.alpinelinux.org/*': true
|
||||
'*://www.duplicati.com/*': true
|
||||
'*://www.fidelity.com/*': true
|
||||
'*://www.newegg.com/*': true
|
||||
'*://www.vitamix.com/*': true
|
||||
'*://www.youtube.com/*': true
|
||||
'*://yewtu.be/*': true
|
||||
content.notifications.enabled:
|
||||
https://jf.opal.sh: false
|
||||
https://www.facebook.com: false
|
||||
content.register_protocol_handler:
|
||||
https://mail.proton.me#mailto=%25s: false
|
||||
0
.config/qutebrowser/bookmarks/urls
Normal file
0
.config/qutebrowser/bookmarks/urls
Normal file
50
.config/qutebrowser/config.py
Normal file
50
.config/qutebrowser/config.py
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from PyQt6.QtCore import QUrl
|
||||
from qutebrowser.api import interceptor
|
||||
|
||||
def rewrite(request: interceptor.Request):
|
||||
url = request.request_url
|
||||
host = url.host()
|
||||
|
||||
# Avoid redirect loops
|
||||
if "reddit.com" in host and "safereddit.com" not in host:
|
||||
new_url = QUrl("https://safereddit.com")
|
||||
new_url.setPath(url.path())
|
||||
new_url.setQuery(url.query())
|
||||
request.redirect(new_url)
|
||||
|
||||
#interceptor.register(rewrite)
|
||||
|
||||
# Load existing settings made via :set
|
||||
config.load_autoconfig()
|
||||
|
||||
c.qt.highdpi = True
|
||||
c.fonts.default_size = "15pt"
|
||||
c.fonts.tabs.selected = "13pt default_family"
|
||||
c.fonts.tabs.unselected = "13pt default_family"
|
||||
c.zoom.default = "130%"
|
||||
c.content.javascript.enabled = False
|
||||
c.downloads.location.directory = "~/dls"
|
||||
c.editor.command = ["alacritty", "-e", "nvim", "{}"]
|
||||
c.editor.encoding = "utf-8"
|
||||
c.auto_save.session = True
|
||||
c.colors.webpage.preferred_color_scheme = "dark"
|
||||
|
||||
# privacy
|
||||
c.content.cookies.accept = "no-3rdparty"
|
||||
c.content.webrtc_ip_handling_policy = "default-public-interface-only"
|
||||
c.content.site_specific_quirks.enabled = False
|
||||
c.content.headers.user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.79 Safari/537.36"
|
||||
|
||||
config.bind("j", "scroll-px 0 100")
|
||||
config.bind("k", "scroll-px 0 -100")
|
||||
config.bind("K", "tab-next")
|
||||
config.bind("J", "tab-prev")
|
||||
|
||||
c.url.searchengines = {
|
||||
"DEFAULT": "https://duckduckgo.com/?q={}",
|
||||
}
|
||||
|
||||
c.url.start_pages = ["https://start.duckduckgo.com"]
|
||||
|
||||
1712
.config/qutebrowser/old-stylesheet.css
Normal file
1712
.config/qutebrowser/old-stylesheet.css
Normal file
File diff suppressed because it is too large
Load Diff
8
.config/qutebrowser/qsettings/QtProject.conf
Normal file
8
.config/qutebrowser/qsettings/QtProject.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
[FileDialog]
|
||||
history=file:///home/opal/pictures
|
||||
lastVisited=file:///home/opal/pictures
|
||||
qtVersion=5.15.6
|
||||
shortcuts=file:, file:///home/opal
|
||||
sidebarWidth=87
|
||||
treeViewHeader="@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1\xd1\0\0\0\x4\x1\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x4\0\0\0\xf5\0\0\0\x1\0\0\0\0\0\0\0\x39\0\0\0\x1\0\0\0\0\0\0\0=\0\0\0\x1\0\0\0\0\0\0\0\x66\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\xff\xff\xff\xff)"
|
||||
viewMode=Detail
|
||||
1
.config/qutebrowser/quickmarks
Normal file
1
.config/qutebrowser/quickmarks
Normal file
@@ -0,0 +1 @@
|
||||
66h&!@Vj4n$cAfwN https://verified.capitalone.com/auth/signin
|
||||
1712
.config/qutebrowser/stylesheet.css
Normal file
1712
.config/qutebrowser/stylesheet.css
Normal file
File diff suppressed because it is too large
Load Diff
343
.config/qutebrowser/userscripts/importer.py
Executable file
343
.config/qutebrowser/userscripts/importer.py
Executable file
@@ -0,0 +1,343 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#!/usr/bin/env python3
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2014-2021 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
# Copyright 2014-2018 Claude (longneck) <longneck@scratchbook.ch>
|
||||
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""Tool to import data from other browsers.
|
||||
|
||||
Currently importing bookmarks from Netscape HTML Bookmark files, Chrome
|
||||
profiles, and Mozilla profiles is supported.
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
import textwrap
|
||||
import sqlite3
|
||||
import os
|
||||
import urllib.parse
|
||||
import json
|
||||
import string
|
||||
|
||||
|
||||
def main():
|
||||
args = get_args()
|
||||
bookmark_types = []
|
||||
output_format = None
|
||||
input_format = args.input_format
|
||||
if args.search_output:
|
||||
bookmark_types = ["search"]
|
||||
if args.oldconfig:
|
||||
output_format = "oldsearch"
|
||||
else:
|
||||
output_format = "search"
|
||||
else:
|
||||
if args.bookmark_output:
|
||||
output_format = "bookmark"
|
||||
elif args.quickmark_output:
|
||||
output_format = "quickmark"
|
||||
if args.import_bookmarks:
|
||||
bookmark_types.append("bookmark")
|
||||
if args.import_keywords:
|
||||
bookmark_types.append("keyword")
|
||||
if not bookmark_types:
|
||||
bookmark_types = ["bookmark", "keyword"]
|
||||
if not output_format:
|
||||
output_format = "quickmark"
|
||||
|
||||
import_function = {
|
||||
"html": import_html_bookmarks,
|
||||
"mozilla": import_moz_places,
|
||||
"chrome": import_chrome,
|
||||
}
|
||||
import_function[input_format](args.bookmarks, bookmark_types, output_format)
|
||||
|
||||
|
||||
def get_args():
|
||||
"""Get the argparse parser."""
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=textwrap.dedent(
|
||||
"""
|
||||
To import bookmarks, you'll need the path to your profile or an
|
||||
exported HTML file from your browser's bookmark manager. Redirect
|
||||
the output from this script to the appropriate file in your
|
||||
qutebrowser config directory (listed in the output of :version),
|
||||
usually done with the '>' operator; for example,
|
||||
./importer.py -i mozilla your_profile_path > ~/.config/qutebrowser/quickmarks
|
||||
|
||||
Common browsers with native input format support:
|
||||
chrome: Chrome, Chromium, Edge
|
||||
mozilla: Firefox, SeaMonkey, Pale Moon
|
||||
"""
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--input-format",
|
||||
help="Which input format? Defaults to html",
|
||||
choices=["html", "mozilla", "chrome"],
|
||||
default="html",
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--bookmark-output",
|
||||
help="Output in bookmark format.",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-q",
|
||||
"--quickmark-output",
|
||||
help="Output in quickmark format (default).",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--search-output",
|
||||
help="Output config.py search engine format (negates -B and -K)",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--oldconfig",
|
||||
help="Output search engine format for old qutebrowser.conf format",
|
||||
default=False,
|
||||
action="store_true",
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-B",
|
||||
"--import-bookmarks",
|
||||
help="Import plain bookmarks (can be combiend with -K)",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-K",
|
||||
"--import-keywords",
|
||||
help="Import keywords (can be combined with -B)",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"bookmarks",
|
||||
help="Bookmarks file (html format) or " "profile folder (Mozilla format)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def search_escape(url):
|
||||
"""Escape URLs such that preexisting { and } are handled properly.
|
||||
|
||||
Will obviously trash a properly-formatted qutebrowser URL.
|
||||
"""
|
||||
return url.replace("{", "{{").replace("}", "}}")
|
||||
|
||||
|
||||
def opensearch_convert(url):
|
||||
"""Convert a basic OpenSearch URL into something qutebrowser can use.
|
||||
|
||||
Exceptions:
|
||||
KeyError:
|
||||
An unknown and required parameter is present in the URL. This
|
||||
usually means there's browser/addon specific functionality needed
|
||||
to build the URL (I'm looking at you and your browser, Google) that
|
||||
obviously won't be present here.
|
||||
"""
|
||||
subst = {
|
||||
"searchTerms": "%s", # for proper escaping later
|
||||
"language": "*",
|
||||
"inputEncoding": "UTF-8",
|
||||
"outputEncoding": "UTF-8",
|
||||
}
|
||||
|
||||
# remove optional parameters (even those we don't support)
|
||||
for param in string.Formatter().parse(url):
|
||||
if param[1]:
|
||||
if param[1].endswith("?"):
|
||||
url = url.replace("{" + param[1] + "}", "")
|
||||
elif param[2] and param[2].endswith("?"):
|
||||
url = url.replace("{" + param[1] + ":" + param[2] + "}", "")
|
||||
return search_escape(url.format(**subst)).replace("%s", "{}")
|
||||
|
||||
|
||||
def import_html_bookmarks(bookmarks_file, bookmark_types, output_format):
|
||||
"""Import bookmarks from a NETSCAPE-Bookmark-file v1.
|
||||
|
||||
Generated by Chromium, Firefox, IE and possibly more browsers. Not all
|
||||
export all possible bookmark types:
|
||||
- Firefox mostly works with everything
|
||||
- Chrome doesn't support keywords at all; searches are a separate
|
||||
database
|
||||
"""
|
||||
import bs4
|
||||
|
||||
with open(bookmarks_file, encoding="utf-8") as f:
|
||||
soup = bs4.BeautifulSoup(f, "html.parser")
|
||||
bookmark_query = {
|
||||
"search": lambda tag: (
|
||||
(tag.name == "a") and ("shortcuturl" in tag.attrs) and ("%s" in tag["href"])
|
||||
),
|
||||
"keyword": lambda tag: (
|
||||
(tag.name == "a")
|
||||
and ("shortcuturl" in tag.attrs)
|
||||
and ("%s" not in tag["href"])
|
||||
),
|
||||
"bookmark": lambda tag: (
|
||||
(tag.name == "a") and ("shortcuturl" not in tag.attrs) and (tag.string)
|
||||
),
|
||||
}
|
||||
output_template = {
|
||||
"search": {
|
||||
"search": "c.url.searchengines['{tag[shortcuturl]}'] = "
|
||||
"'{tag[href]}' #{tag.string}"
|
||||
},
|
||||
"oldsearch": {
|
||||
"search": "{tag[shortcuturl]} = {tag[href]} #{tag.string}",
|
||||
},
|
||||
"bookmark": {
|
||||
"bookmark": "{tag[href]} {tag.string}",
|
||||
"keyword": "{tag[href]} {tag.string}",
|
||||
},
|
||||
"quickmark": {
|
||||
"bookmark": "{tag.string} {tag[href]}",
|
||||
"keyword": "{tag[shortcuturl]} {tag[href]}",
|
||||
},
|
||||
}
|
||||
bookmarks = []
|
||||
for typ in bookmark_types:
|
||||
tags = soup.findAll(bookmark_query[typ])
|
||||
for tag in tags:
|
||||
if typ == "search":
|
||||
tag["href"] = search_escape(tag["href"]).replace("%s", "{}")
|
||||
if tag["href"] not in bookmarks:
|
||||
bookmarks.append(output_template[output_format][typ].format(tag=tag))
|
||||
for bookmark in bookmarks:
|
||||
print(bookmark)
|
||||
|
||||
|
||||
def import_moz_places(profile, bookmark_types, output_format):
|
||||
"""Import bookmarks from a Mozilla profile's places.sqlite database."""
|
||||
place_query = {
|
||||
"bookmark": (
|
||||
"SELECT DISTINCT moz_bookmarks.title,moz_places.url "
|
||||
"FROM moz_bookmarks,moz_places "
|
||||
"WHERE moz_places.id=moz_bookmarks.fk "
|
||||
"AND moz_places.id NOT IN (SELECT place_id FROM moz_keywords) "
|
||||
"AND moz_places.url NOT LIKE 'place:%';"
|
||||
), # Bookmarks with no keywords assigned
|
||||
"keyword": (
|
||||
"SELECT moz_keywords.keyword,moz_places.url "
|
||||
"FROM moz_keywords,moz_places,moz_bookmarks "
|
||||
"WHERE moz_places.id=moz_bookmarks.fk "
|
||||
"AND moz_places.id=moz_keywords.place_id "
|
||||
"AND moz_places.url NOT LIKE '%!%s%' ESCAPE '!';"
|
||||
), # Bookmarks with keywords assigned but no %s substitution
|
||||
"search": (
|
||||
"SELECT moz_keywords.keyword, "
|
||||
" moz_bookmarks.title, "
|
||||
" search_conv(moz_places.url) AS url "
|
||||
"FROM moz_keywords,moz_places,moz_bookmarks "
|
||||
"WHERE moz_places.id=moz_bookmarks.fk "
|
||||
"AND moz_places.id=moz_keywords.place_id "
|
||||
"AND moz_places.url LIKE '%!%s%' ESCAPE '!';"
|
||||
), # bookmarks with keyword and %s substitution
|
||||
}
|
||||
out_template = {
|
||||
"bookmark": {"bookmark": "{url} {title}", "keyword": "{url} {keyword}"},
|
||||
"quickmark": {"bookmark": "{title} {url}", "keyword": "{keyword} {url}"},
|
||||
"oldsearch": {"search": "{keyword} {url} #{title}"},
|
||||
"search": {"search": "c.url.searchengines['{keyword}'] = '{url}' #{title}"},
|
||||
}
|
||||
|
||||
def search_conv(url):
|
||||
return search_escape(url).replace("%s", "{}")
|
||||
|
||||
places = sqlite3.connect(os.path.join(profile, "places.sqlite"))
|
||||
places.create_function("search_conv", 1, search_conv)
|
||||
places.row_factory = sqlite3.Row
|
||||
c = places.cursor()
|
||||
for typ in bookmark_types:
|
||||
c.execute(place_query[typ])
|
||||
for row in c:
|
||||
print(out_template[output_format][typ].format(**row))
|
||||
|
||||
|
||||
def import_chrome(profile, bookmark_types, output_format):
|
||||
"""Import bookmarks and search keywords from Chrome-type profiles.
|
||||
|
||||
On Chrome, keywords and search engines are the same thing and handled in
|
||||
their own database table; bookmarks cannot have associated keywords. This
|
||||
is why the dictionary lookups here are much simpler.
|
||||
"""
|
||||
out_template = {
|
||||
"bookmark": "{url} {name}",
|
||||
"quickmark": "{name} {url}",
|
||||
"search": "c.url.searchengines['{keyword}'] = '{url}'",
|
||||
"oldsearch": "{keyword} {url}",
|
||||
}
|
||||
|
||||
if "search" in bookmark_types:
|
||||
webdata = sqlite3.connect(os.path.join(profile, "Web Data"))
|
||||
c = webdata.cursor()
|
||||
c.execute("SELECT keyword,url FROM keywords;")
|
||||
for keyword, url in c:
|
||||
try:
|
||||
url = opensearch_convert(url)
|
||||
print(out_template[output_format].format(keyword=keyword, url=url))
|
||||
except KeyError:
|
||||
print(
|
||||
"# Unsupported parameter in url for {}; skipping....".format(
|
||||
keyword
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
with open(os.path.join(profile, "Bookmarks"), encoding="utf-8") as f:
|
||||
bookmarks = json.load(f)
|
||||
|
||||
def bm_tree_walk(bm, template):
|
||||
"""Recursive function to walk through bookmarks."""
|
||||
if not isinstance(bm, dict):
|
||||
return
|
||||
assert "type" in bm, bm
|
||||
if bm["type"] == "url":
|
||||
if urllib.parse.urlparse(bm["url"]).scheme != "chrome":
|
||||
print(template.format(**bm))
|
||||
elif bm["type"] == "folder":
|
||||
for child in bm["children"]:
|
||||
bm_tree_walk(child, template)
|
||||
|
||||
for root in bookmarks["roots"].values():
|
||||
bm_tree_walk(root, out_template[output_format])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
356
.config/qutebrowser/userscripts/qute-bitwarden
Executable file
356
.config/qutebrowser/userscripts/qute-bitwarden
Executable file
@@ -0,0 +1,356 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2017 Chris Braun (cryzed) <cryzed@googlemail.com>
|
||||
# Adapted for Bitwarden by Jonathan Haylett (JonnyHaystack) <jonathan@haylett.dev>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Insert login information using Bitwarden CLI and a dmenu-compatible application
|
||||
(e.g. dmenu, rofi -dmenu, ...).
|
||||
"""
|
||||
|
||||
USAGE = """The domain of the site has to be in the name of the Bitwarden entry, for example: "github.com/cryzed" or
|
||||
"websites/github.com". The login information is inserted by emulating key events using qutebrowser's fake-key command in this manner:
|
||||
[USERNAME]<Tab>[PASSWORD], which is compatible with almost all login forms.
|
||||
|
||||
If enabled, with the `--totp` flag, it will also move the TOTP code to the
|
||||
clipboard, much like the Firefox add-on.
|
||||
|
||||
You must log into Bitwarden CLI using `bw login` prior to use of this script.
|
||||
The session key will be stored using keyctl for the number of seconds passed to
|
||||
the --auto-lock option.
|
||||
|
||||
To use in qutebrowser, run: `spawn --userscript qute-bitwarden`
|
||||
"""
|
||||
|
||||
EPILOG = """Dependencies: tldextract (Python 3 module), pyperclip (optional
|
||||
Python module, used for TOTP codes), Bitwarden CLI (1.7.4 is known to work
|
||||
but older versions may well also work)
|
||||
|
||||
WARNING: The login details are viewable as plaintext in qutebrowser's debug log
|
||||
(qute://log) and might be shared if you decide to submit a crash report!"""
|
||||
|
||||
import argparse
|
||||
import enum
|
||||
import functools
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
import tldextract
|
||||
|
||||
argument_parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
usage=USAGE,
|
||||
epilog=EPILOG,
|
||||
)
|
||||
argument_parser.add_argument("url", nargs="?", default=os.getenv("QUTE_URL"))
|
||||
argument_parser.add_argument(
|
||||
"--dmenu-invocation",
|
||||
"-d",
|
||||
default="bemenu -x -b --prompt=Pass",
|
||||
help="Invocation used to execute a dmenu-provider",
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"--password-prompt-invocation",
|
||||
"-p",
|
||||
default='bemenu -x -b -p "Master Password"',
|
||||
help="Invocation used to prompt the user for their Bitwarden password",
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"--no-insert-mode",
|
||||
"-n",
|
||||
dest="insert_mode",
|
||||
action="store_false",
|
||||
help="Don't automatically enter insert mode",
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"--totp", "-t", action="store_true", help="Copy TOTP key to clipboard"
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"--io-encoding",
|
||||
"-i",
|
||||
default="UTF-8",
|
||||
help="Encoding used to communicate with subprocesses",
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"--merge-candidates",
|
||||
"-m",
|
||||
action="store_true",
|
||||
help="Merge pass candidates for fully-qualified and registered domain name",
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"--auto-lock",
|
||||
type=int,
|
||||
default=900,
|
||||
help="Automatically lock the vault after this many seconds",
|
||||
)
|
||||
|
||||
group = argument_parser.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
"--username-only", "-e", action="store_true", help="Only insert username"
|
||||
)
|
||||
group.add_argument(
|
||||
"--password-only", "-w", action="store_true", help="Only insert password"
|
||||
)
|
||||
group.add_argument(
|
||||
"--totp-only", "-T", action="store_true", help="Only insert totp code"
|
||||
)
|
||||
|
||||
stderr = functools.partial(print, file=sys.stderr)
|
||||
|
||||
|
||||
class ExitCodes(enum.IntEnum):
|
||||
SUCCESS = 0
|
||||
FAILURE = 1
|
||||
# 1 is automatically used if Python throws an exception
|
||||
NO_PASS_CANDIDATES = 2
|
||||
COULD_NOT_MATCH_USERNAME = 3
|
||||
COULD_NOT_MATCH_PASSWORD = 4
|
||||
|
||||
|
||||
def qute_command(command):
|
||||
with open(os.environ["QUTE_FIFO"], "w") as fifo:
|
||||
fifo.write(command + "\n")
|
||||
fifo.flush()
|
||||
|
||||
|
||||
def ask_password(password_prompt_invocation):
|
||||
process = subprocess.run(
|
||||
shlex.split(password_prompt_invocation),
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
if process.returncode > 0:
|
||||
raise Exception("Could not unlock vault")
|
||||
master_pass = process.stdout.strip()
|
||||
return subprocess.check_output(
|
||||
["bw", "unlock", "--raw", master_pass],
|
||||
text=True,
|
||||
).strip()
|
||||
|
||||
|
||||
def get_session_key(auto_lock, password_prompt_invocation):
|
||||
if auto_lock == 0:
|
||||
subprocess.call(["keyctl", "purge", "user", "bw_session"])
|
||||
return ask_password(password_prompt_invocation)
|
||||
else:
|
||||
process = subprocess.run(
|
||||
["keyctl", "request", "user", "bw_session"],
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
key_id = process.stdout.strip()
|
||||
if process.returncode > 0:
|
||||
session = ask_password(password_prompt_invocation)
|
||||
if not session:
|
||||
raise Exception("Could not unlock vault")
|
||||
key_id = subprocess.check_output(
|
||||
["keyctl", "add", "user", "bw_session", session, "@u"],
|
||||
text=True,
|
||||
).strip()
|
||||
|
||||
if auto_lock > 0:
|
||||
subprocess.call(["keyctl", "timeout", str(key_id), str(auto_lock)])
|
||||
return subprocess.check_output(
|
||||
["keyctl", "pipe", str(key_id)],
|
||||
text=True,
|
||||
).strip()
|
||||
|
||||
|
||||
def pass_(domain, encoding, auto_lock, password_prompt_invocation):
|
||||
session_key = get_session_key(auto_lock, password_prompt_invocation)
|
||||
process = subprocess.run(
|
||||
["bw", "list", "items", "--session", session_key, "--url", domain],
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
err = process.stderr.decode(encoding).strip()
|
||||
if err:
|
||||
msg = "Bitwarden CLI returned for {:s} - {:s}".format(domain, err)
|
||||
stderr(msg)
|
||||
|
||||
if process.returncode:
|
||||
return "[]"
|
||||
|
||||
out = process.stdout.decode(encoding).strip()
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_totp_code(
|
||||
selection_id, domain_name, encoding, auto_lock, password_prompt_invocation
|
||||
):
|
||||
session_key = get_session_key(auto_lock, password_prompt_invocation)
|
||||
process = subprocess.run(
|
||||
["bw", "get", "totp", "--session", session_key, selection_id],
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
err = process.stderr.decode(encoding).strip()
|
||||
if err:
|
||||
# domain_name instead of selection_id to make it more user-friendly
|
||||
msg = "Bitwarden CLI returned for {:s} - {:s}".format(domain_name, err)
|
||||
stderr(msg)
|
||||
|
||||
if process.returncode:
|
||||
return "[]"
|
||||
|
||||
out = process.stdout.decode(encoding).strip()
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def dmenu(items, invocation, encoding):
|
||||
command = shlex.split(invocation)
|
||||
process = subprocess.run(
|
||||
command, input="\n".join(items).encode(encoding), stdout=subprocess.PIPE
|
||||
)
|
||||
return process.stdout.decode(encoding).strip()
|
||||
|
||||
|
||||
def fake_key_raw(text):
|
||||
for character in text:
|
||||
# Escape all characters by default, space requires special handling
|
||||
sequence = '" "' if character == " " else r"\{}".format(character)
|
||||
qute_command("fake-key {}".format(sequence))
|
||||
|
||||
|
||||
def main(arguments):
|
||||
if not arguments.url:
|
||||
argument_parser.print_help()
|
||||
return ExitCodes.FAILURE
|
||||
|
||||
extract_result = tldextract.extract(arguments.url)
|
||||
|
||||
# Try to find candidates using targets in the following order: fully-qualified domain name (includes subdomains),
|
||||
# the registered domain name and finally: the IPv4 address if that's what
|
||||
# the URL represents
|
||||
candidates = []
|
||||
for target in filter(
|
||||
None,
|
||||
[
|
||||
extract_result.fqdn,
|
||||
extract_result.registered_domain,
|
||||
extract_result.subdomain + "." + extract_result.domain,
|
||||
extract_result.domain,
|
||||
extract_result.ipv4,
|
||||
],
|
||||
):
|
||||
target_candidates = json.loads(
|
||||
pass_(
|
||||
target,
|
||||
arguments.io_encoding,
|
||||
arguments.auto_lock,
|
||||
arguments.password_prompt_invocation,
|
||||
)
|
||||
)
|
||||
if not target_candidates:
|
||||
continue
|
||||
|
||||
candidates = candidates + target_candidates
|
||||
if not arguments.merge_candidates:
|
||||
break
|
||||
else:
|
||||
if not candidates:
|
||||
stderr("No pass candidates for URL {!r} found!".format(arguments.url))
|
||||
return ExitCodes.NO_PASS_CANDIDATES
|
||||
|
||||
if len(candidates) == 1:
|
||||
selection = candidates.pop()
|
||||
else:
|
||||
choices = []
|
||||
for c in candidates:
|
||||
if c["login"]["username"] is None:
|
||||
c["login"]["username"] = ""
|
||||
|
||||
choices.append("{:s} | {:s}".format(c["name"], c["login"]["username"]))
|
||||
|
||||
# choices = [
|
||||
# "{:s} | {:s}".format(c["name"], c["login"]["username"]) for c in candidates
|
||||
# ]
|
||||
choice = dmenu(choices, arguments.dmenu_invocation, arguments.io_encoding)
|
||||
choice_tokens = choice.split("|")
|
||||
choice_name = choice_tokens[0].strip()
|
||||
choice_username = choice_tokens[1].strip()
|
||||
selection = next(
|
||||
(
|
||||
c
|
||||
for (i, c) in enumerate(candidates)
|
||||
if c["name"] == choice_name
|
||||
and c["login"]["username"] == choice_username
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
# Nothing was selected, simply return
|
||||
if not selection:
|
||||
return ExitCodes.SUCCESS
|
||||
|
||||
username = selection["login"]["username"]
|
||||
password = selection["login"]["password"]
|
||||
totp = selection["login"]["totp"]
|
||||
|
||||
if arguments.username_only:
|
||||
fake_key_raw(username)
|
||||
elif arguments.password_only:
|
||||
fake_key_raw(password)
|
||||
elif arguments.totp_only:
|
||||
# No point in moving it to the clipboard in this case
|
||||
fake_key_raw(
|
||||
get_totp_code(
|
||||
selection["id"],
|
||||
selection["name"],
|
||||
arguments.io_encoding,
|
||||
arguments.auto_lock,
|
||||
arguments.password_prompt_invocation,
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Enter username and password using fake-key and <Tab> (which seems to work almost universally), then switch
|
||||
# back into insert-mode, so the form can be directly submitted by
|
||||
# hitting enter afterwards
|
||||
fake_key_raw(username)
|
||||
qute_command("fake-key <Tab>")
|
||||
fake_key_raw(password)
|
||||
|
||||
if arguments.insert_mode:
|
||||
qute_command("mode-enter insert")
|
||||
|
||||
# If it finds a TOTP code, it copies it to the clipboard,
|
||||
# which is the same behavior as the Firefox add-on.
|
||||
if not arguments.totp_only and totp and arguments.totp:
|
||||
# The import is done here, to make pyperclip an optional dependency
|
||||
import pyperclip
|
||||
|
||||
pyperclip.copy(
|
||||
get_totp_code(
|
||||
selection["id"],
|
||||
selection["name"],
|
||||
arguments.io_encoding,
|
||||
arguments.auto_lock,
|
||||
arguments.password_prompt_invocation,
|
||||
)
|
||||
)
|
||||
|
||||
return ExitCodes.SUCCESS
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
arguments = argument_parser.parse_args()
|
||||
sys.exit(main(arguments))
|
||||
313
.config/sway/config
Normal file
313
.config/sway/config
Normal file
@@ -0,0 +1,313 @@
|
||||
|
||||
output * bg /home/opal/.config/wallpapers/wall.jpg fill #0D0703
|
||||
|
||||
#######################
|
||||
# VARIABLES
|
||||
#######################
|
||||
# Directional Keys
|
||||
set $left h
|
||||
set $down j
|
||||
set $up k
|
||||
set $right l
|
||||
|
||||
# Mod Key
|
||||
set $mod Mod4
|
||||
|
||||
# Terminal
|
||||
set $term alacritty
|
||||
|
||||
# Application Launcher
|
||||
set $menu bemenu-run -p Run: -l 10 -c -M 500 --fn 'Monospace 17' --tf '#ff4e00' --ff '#dbc077' --hf '#ff4e00'
|
||||
|
||||
#######################
|
||||
# GENERAL KEYBINDS
|
||||
#######################
|
||||
|
||||
# Start a terminal
|
||||
bindsym $mod+Return exec $term
|
||||
|
||||
# Start wofi
|
||||
bindsym $mod+d exec $menu
|
||||
|
||||
# Kill focused window
|
||||
bindsym $mod+Shift+q kill
|
||||
|
||||
# Lock SwayWM
|
||||
bindsym Control+Shift+l exec swaylock
|
||||
|
||||
# Change normal to inverse to use left mouse button for resizing and right
|
||||
# mouse button for dragging.
|
||||
floating_modifier $mod normal
|
||||
|
||||
# Reload the configuration file
|
||||
bindsym $mod+Shift+c reload
|
||||
|
||||
# Log out menu
|
||||
bindsym $mod+Shift+x exec wlogout
|
||||
|
||||
# Moving around:
|
||||
# Move your focus around
|
||||
bindsym $mod+$left focus left
|
||||
bindsym $mod+$down focus down
|
||||
bindsym $mod+$up focus up
|
||||
bindsym $mod+$right focus right
|
||||
|
||||
# Or use $mod+[up|down|left|right]
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Right focus right
|
||||
|
||||
# Move the focused window with the same, but add Shift
|
||||
bindsym $mod+Shift+$left move left
|
||||
bindsym $mod+Shift+$down move down
|
||||
bindsym $mod+Shift+$up move up
|
||||
bindsym $mod+Shift+$right move right
|
||||
|
||||
# Ditto, with arrow keys
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
|
||||
# Layout stuff:
|
||||
#
|
||||
# You can "split" the current object of your focus with
|
||||
# $mod+b or $mod+v, for horizontal and vertical splits
|
||||
# respectively.
|
||||
bindsym $mod+b splith
|
||||
bindsym $mod+v splitv
|
||||
|
||||
# Switch the current container between different layout styles
|
||||
#bindsym $mod+s layout stacking
|
||||
#bindsym $mod+w layout tabbed
|
||||
#bindsym $mod+e layout toggle split
|
||||
|
||||
# Make the current focus fullscreen
|
||||
bindsym $mod+f fullscreen
|
||||
|
||||
# Toggle the current focus between tiling and floating mode
|
||||
bindsym $mod+Shift+space floating toggle
|
||||
|
||||
# Swap focus between the tiling area and the floating area
|
||||
bindsym $mod+space focus mode_toggle
|
||||
|
||||
# Move focus to the parent container
|
||||
bindsym $mod+a focus parent
|
||||
|
||||
# Scratchpad:
|
||||
#
|
||||
# Sway has a "scratchpad", which is a bag of holding for windows.
|
||||
# You can send windows there and get them back later.
|
||||
|
||||
# Move the currently focused window to the scratchpad
|
||||
bindsym $mod+Shift+minus move scratchpad
|
||||
|
||||
# Show the next scratchpad window or hide the focused scratchpad window.
|
||||
# If there are multiple scratchpad windows, this command cycles through them.
|
||||
bindsym $mod+minus scratchpad show
|
||||
|
||||
# Volume up
|
||||
bindsym XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5%
|
||||
|
||||
# Volume down
|
||||
bindsym XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5%
|
||||
|
||||
# Mute toggle
|
||||
bindsym XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle
|
||||
|
||||
|
||||
# Resizing containers:
|
||||
mode "resize" {
|
||||
# left will shrink the containers width
|
||||
# right will grow the containers width
|
||||
# up will shrink the containers height
|
||||
# down will grow the containers height
|
||||
bindsym $left resize shrink width 10px
|
||||
bindsym $down resize grow height 10px
|
||||
bindsym $up resize shrink height 10px
|
||||
bindsym $right resize grow width 10px
|
||||
|
||||
# Ditto, with arrow keys
|
||||
bindsym Left resize shrink width 10px
|
||||
bindsym Down resize grow height 10px
|
||||
bindsym Up resize shrink height 10px
|
||||
bindsym Right resize grow width 10px
|
||||
|
||||
# Return to default mode
|
||||
bindsym Return mode "default"
|
||||
bindsym Escape mode "default"
|
||||
}
|
||||
bindsym $mod+r mode "resize"
|
||||
|
||||
# Screenshot (Grimshot)
|
||||
# Captures the currently active window
|
||||
bindsym $mod+g exec grimshot save active
|
||||
# Allows manually selecting a rectangular region
|
||||
bindsym $mod+Shift+g exec grimshot save area
|
||||
# Captures currently active output
|
||||
bindsym $mod+Mod1+g exec grimshot save output
|
||||
# Allows manually selecting a single window
|
||||
bindsym $mod+Ctrl+g exec grimshot save window
|
||||
|
||||
# Bookmarks
|
||||
# Enter selected bookmark into target text field
|
||||
bindsym $mod+i exec wtype $(grep -v '^#' ~/.local/share/bookmarks/bookmarks | bemenu -p Bookmark: -l 50 -c -M 500 --fn 'Monospace 14' --tf '#ff4e00' --ff '#dbc077' --hf '#ff4e00' | cut -d ' ' -f1) wtype -k Return
|
||||
|
||||
# Insert bookmark into bookmark file (~/.local/share/bookmarks/bookmarks)
|
||||
bindsym $mod+Shift+i exec ~/.local/bin/bookmark_insert
|
||||
|
||||
# Emojis
|
||||
bindsym $mod+Shift+e exec wtype $(awk '{print $1, $0}' ~/.local/share/chars/emojis* | bemenu -p Emoji: -l 25 -c -M 500 --fn 'Noto Color Emoji,Monospace 14' --tf '#ff4e00' --ff '#dbc077' --hf '#ff4e00' | awk '{print $1}')
|
||||
|
||||
# Gopass
|
||||
bindsym $mod+y exec ~/.local/bin/pass_copy
|
||||
bindsym $mod+u exec ~/.local/bin/pass_user_copy
|
||||
bindsym $mod+p exec ~/.local/bin/pass_autofill
|
||||
|
||||
#######################
|
||||
# EXECS
|
||||
#######################
|
||||
|
||||
# Notifications
|
||||
exec_always pgrep -x dunst > /dev/null || dunst
|
||||
|
||||
# Wlsunset (Night Light)
|
||||
exec_always pgrep -x wlsunset > /dev/null || wlsunset -l 47.6 -L -122.3 -t 3500 -T 6000
|
||||
|
||||
# udiskie - auto usb mounting
|
||||
exec /usr/bin/udiskie &
|
||||
|
||||
# Network Manager tray applet
|
||||
#exec /usr/bin/nm-applet
|
||||
|
||||
# Bluetooth manager tray applet
|
||||
exec /usr/bin/blueman-applet
|
||||
|
||||
# Pipewire
|
||||
exec /usr/libexec/pipewire-launcher
|
||||
|
||||
|
||||
# Idle configuration
|
||||
#exec swayidle -w \
|
||||
# timeout 3200 'swaymsg "output * dpms off"' \
|
||||
# resume 'swaymsg "output * dpms on"' \
|
||||
# before-sleep 'swaylock -f'
|
||||
# timeout 15 'if pgrep -x swaylock; then swaymsg "output * dpms off"; fi' \
|
||||
|
||||
#######################
|
||||
# DECORATIONS
|
||||
#######################
|
||||
|
||||
# Gaps
|
||||
smart_gaps off
|
||||
gaps inner 5
|
||||
gaps outer 5
|
||||
|
||||
# Window Borders
|
||||
default_border pixel 3
|
||||
default_floating_border none
|
||||
client.focused "#D27A31" "#5F9EA0" "#000000" "#D27A31"
|
||||
|
||||
#######################
|
||||
# INPUTS
|
||||
#######################
|
||||
|
||||
input type:keyboard {
|
||||
# Capslock key should work as escape key
|
||||
# See /usr/share/X11/xkb/rules/xorg.lst for options
|
||||
xkb_layout "us(altgr-intl)"
|
||||
xkb_options caps:escape
|
||||
|
||||
repeat_delay 250
|
||||
repeat_rate 45
|
||||
}
|
||||
|
||||
# Disable trackpad by default
|
||||
#input "1739:52824:SYNA8008:00_06CB:CE58_Touchpad" {
|
||||
# events disable
|
||||
#}
|
||||
|
||||
# Set trackpoint sensitivity on Laptop
|
||||
input "2:10:TPPS/2_Elan_TrackPoint" {
|
||||
pointer_accel 1.0
|
||||
accel_profile "flat"
|
||||
}
|
||||
|
||||
# Set trackpoint sensitivity on Tex Shinobi USB
|
||||
input "1241:1031:USB-HID_Keyboard_Mouse" {
|
||||
pointer_accel 0.3
|
||||
accel_profile "flat"
|
||||
}
|
||||
|
||||
|
||||
# Hide mouse cursor after inactivity
|
||||
seat * hide_cursor 10000
|
||||
|
||||
seat seat0 xcursor_theme breeze_cursors 24
|
||||
|
||||
# Enable/disable trackpad
|
||||
bindsym $mod+t exec swaymsg input "1739:52824:SYNA8008:00_06CB:CE58_Touchpad" events disabled
|
||||
bindsym $mod+Shift+t exec swaymsg input "1739:52824:SYNA8008:00_06CB:CE58_Touchpad" events enabled
|
||||
|
||||
#######################
|
||||
# OUTPUTS
|
||||
#######################
|
||||
|
||||
# Lid stuff
|
||||
set $laptop eDP-1
|
||||
bindswitch --reload --locked lid:on output $laptop disable
|
||||
bindswitch --reload --locked lid:off output $laptop enable
|
||||
|
||||
#######################
|
||||
# WORKSPACES
|
||||
#######################
|
||||
|
||||
# Assign workspaces to numbers
|
||||
set $ws1 "1"
|
||||
set $ws2 "2"
|
||||
set $ws3 "3"
|
||||
set $ws4 "4"
|
||||
set $ws5 "5"
|
||||
set $ws6 "6"
|
||||
set $ws7 "7"
|
||||
|
||||
# Switch to workspace
|
||||
bindsym $mod+1 workspace $ws1
|
||||
bindsym $mod+2 workspace $ws2
|
||||
bindsym $mod+3 workspace $ws3
|
||||
bindsym $mod+4 workspace $ws4
|
||||
bindsym $mod+5 workspace $ws5
|
||||
bindsym $mod+6 workspace $ws6
|
||||
bindsym $mod+0 workspace $ws7
|
||||
|
||||
# Move focused container to workspace
|
||||
bindsym $mod+Shift+1 move container to workspace $ws1
|
||||
bindsym $mod+Shift+2 move container to workspace $ws2
|
||||
bindsym $mod+Shift+3 move container to workspace $ws3
|
||||
bindsym $mod+Shift+4 move container to workspace $ws4
|
||||
bindsym $mod+Shift+5 move container to workspace $ws5
|
||||
bindsym $mod+Shift+6 move container to workspace $ws6
|
||||
bindsym $mod+Shift+0 move container to workspace $ws7
|
||||
|
||||
|
||||
#######################
|
||||
# BAR
|
||||
#######################
|
||||
|
||||
bar {
|
||||
position top
|
||||
font "Monospace 17"
|
||||
height 40
|
||||
strip_workspace_numbers yes
|
||||
status_command ~/.config/sway/scripts/bar.sh
|
||||
|
||||
colors {
|
||||
statusline #c0c0c0
|
||||
background #1a1a1aAA
|
||||
inactive_workspace #2a2a2aAA #2a2a2aAA #555555AA
|
||||
focused_workspace #2a2a2aAA #555555AA #ddddddAA
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
37
.config/sway/scripts/bar.sh
Executable file
37
.config/sway/scripts/bar.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
get_date() {
|
||||
date '+%H:%M %a %d/%m/%y'
|
||||
}
|
||||
|
||||
get_battery() {
|
||||
BATTERY_PATH="/sys/class/power_supply/BAT0"
|
||||
|
||||
if [ -f "$BATTERY_PATH/capacity" ]; then
|
||||
BAT_PERCENT=$(cat "$BATTERY_PATH/capacity")
|
||||
BAT_STATUS=$(cat "$BATTERY_PATH/status")
|
||||
|
||||
printf "%s%%" "$BAT_PERCENT"
|
||||
|
||||
if [ "$BAT_STATUS" = "Charging" ] || [ "$BAT_STATUS" = "Unknown" ]; then
|
||||
printf "^"
|
||||
fi
|
||||
else
|
||||
printf "NoBat"
|
||||
fi
|
||||
}
|
||||
|
||||
get_volume() {
|
||||
SINK=$(pactl info | awk -F': ' '/Default Sink/ {print $2}')
|
||||
VOLUME=$(pactl get-sink-volume "$SINK" | awk '{print $5}' | head -n 1)
|
||||
MUTE_STATUS=$(pactl get-sink-mute "$SINK" | awk '{print $2}')
|
||||
|
||||
printf "%s" "$VOLUME"
|
||||
[ "$MUTE_STATUS" = "yes" ] && printf " (m)"
|
||||
}
|
||||
|
||||
while true; do
|
||||
printf "V: %s | %s | B: %s\n" "$(get_volume)" "$(get_date)" "$(get_battery)"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
6
.config/sway/scripts/clamshell.sh
Executable file
6
.config/sway/scripts/clamshell.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/bash
|
||||
if grep -q open /proc/acpi/button/lid/LID/state; then
|
||||
swaymsg output eDP-1 enable
|
||||
else
|
||||
swaymsg output eDP-1 disable
|
||||
fi
|
||||
32
.config/swaylock/config
Normal file
32
.config/swaylock/config
Normal file
@@ -0,0 +1,32 @@
|
||||
# Image
|
||||
image=~/.config/wallpapers/wall.jpg
|
||||
scaling=fill
|
||||
|
||||
# Indicator
|
||||
ignore-empty-password
|
||||
indicator-caps-lock
|
||||
indicator-radius=100
|
||||
indicator-thickness=20
|
||||
line-color=1f1d2e
|
||||
ring-color=191724
|
||||
inside-color=1f1d2e
|
||||
key-hl-color=eb6f92
|
||||
separator-color=00000000
|
||||
text-color=e0def4
|
||||
text-caps-lock-color=""
|
||||
line-ver-color=eb6f92
|
||||
ring-ver-color=eb6f92
|
||||
inside-ver-color=1f1d2e
|
||||
text-ver-color=e0def4
|
||||
ring-wrong-color=31748f
|
||||
text-wrong-color=31748f
|
||||
inside-wrong-color=1f1d2e
|
||||
inside-clear-color=1f1d2e
|
||||
text-clear-color=e0def4
|
||||
ring-clear-color=9ccfd8
|
||||
line-clear-color=1f1d2e
|
||||
line-wrong-color=1f1d2e
|
||||
bs-hl-color=31748f
|
||||
|
||||
# Behavior
|
||||
show-failed-attempts
|
||||
BIN
.config/wallpapers/wall.jpg
Normal file
BIN
.config/wallpapers/wall.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 477 KiB |
32
.local/bin/bookmark_insert
Executable file
32
.local/bin/bookmark_insert
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
bookmarks_file="$HOME/.local/share/bookmarks/bookmarks"
|
||||
|
||||
if [ ! -f "$bookmarks_file" ]; then
|
||||
notify-send "Error" "Bookmark file doesn't exist. Please pull the repo."
|
||||
echo "Bookmark file doesn't exist. Please pull the repo." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try clipboard first, fall back to primary
|
||||
clipboard_text=$(wl-paste --no-newline 2>/dev/null)
|
||||
[ -z "$clipboard_text" ] && clipboard_text=$(wl-paste -p --no-newline 2>/dev/null)
|
||||
|
||||
# Trim leading/trailing whitespace
|
||||
clipboard_text=$(echo "$clipboard_text" | xargs)
|
||||
|
||||
# Remove trailing slashes
|
||||
clipboard_text=$(echo "$clipboard_text" | sed 's#/$##')
|
||||
|
||||
# Check if clipboard is not empty
|
||||
if [ -n "$clipboard_text" ]; then
|
||||
if grep -Fxq "$clipboard_text" "$bookmarks_file"; then
|
||||
notify-send "Bookmark already exists!" "$clipboard_text"
|
||||
else
|
||||
echo "$clipboard_text" >> "$bookmarks_file"
|
||||
notify-send "Bookmark saved" "$clipboard_text"
|
||||
sh "$HOME/.local/bin/bookmark_update"
|
||||
fi
|
||||
else
|
||||
notify-send "No text to save" "Clipboard and primary selection are empty."
|
||||
fi
|
||||
29
.local/bin/bookmark_update
Executable file
29
.local/bin/bookmark_update
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Try to source keychain's environment file
|
||||
if [ -f "$HOME/.keychain/$(hostname)-sh" ]; then
|
||||
. "$HOME/.keychain/$(hostname)-sh"
|
||||
fi
|
||||
|
||||
# Define the paths and repository
|
||||
bookmarks_file="$HOME/.local/share/bookmarks/bookmarks"
|
||||
repo_path="$HOME/.local/share/bookmarks"
|
||||
|
||||
# Pull the latest changes
|
||||
cd "$repo_path" || exit
|
||||
git pull origin master
|
||||
|
||||
# Check if the bookmarks file has changed
|
||||
if [ -n "$(git status --porcelain "$bookmarks_file")" ]; then
|
||||
# Add and commit the bookmarks file
|
||||
git add "$bookmarks_file"
|
||||
git commit -m "Update bookmarks file"
|
||||
|
||||
# Push the changes and log output
|
||||
GIT_SSH_COMMAND="ssh -i ~/.ssh/ry_ecdsa" git push origin master 2>&1 | tee -a /tmp/bookmark_git_push.log
|
||||
|
||||
notify-send "Bookmarks updated" "Push your changes."
|
||||
else
|
||||
notify-send "No changes" "No changes to the bookmarks file."
|
||||
fi
|
||||
|
||||
22
.local/bin/pass_autofill
Executable file
22
.local/bin/pass_autofill
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
entry=$(gopass list --flat | bemenu -p Autofill: -l 25 -c -M 500 --fn 'Monospace 14' --tf '#ff4e00' --ff '#dbc077' --hf '#ff4e00')
|
||||
|
||||
if [ -n "$entry" ]; then
|
||||
username=$(gopass show "$entry" | grep '^username:' | cut -d' ' -f2-)
|
||||
password=$(gopass show -o "$entry")
|
||||
|
||||
if [ -z "$password" ]; then
|
||||
notify-send "Gopass Error" "No password for $entry"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
notify-send "Autofill in 1s: Focus username field in form"
|
||||
sleep 1
|
||||
|
||||
# Type username, press Tab, then password, then Enter
|
||||
wtype "$username"
|
||||
wtype -k Tab
|
||||
wtype "$password"
|
||||
wtype -k Return
|
||||
fi
|
||||
8
.local/bin/pass_copy
Executable file
8
.local/bin/pass_copy
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
entry=$(gopass list --flat | bemenu -p Password: -l 25 -c -M 500 --fn 'Monospace 14' --tf '#ff4e00' --ff '#dbc077' --hf '#ff4e00')
|
||||
|
||||
if [ -n "$entry" ]; then
|
||||
gopass show -c "$entry" 2>/dev/null || notify-send "Gopass Error" "Failed to copy: $entry"
|
||||
fi
|
||||
|
||||
8
.local/bin/pass_user_copy
Executable file
8
.local/bin/pass_user_copy
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
entry=$(gopass list --flat | bemenu -p Username: -l 25 -c -M 500 --fn 'Monospace 14' --tf '#ff4e00' --ff '#dbc077' --hf '#ff4e00')
|
||||
|
||||
if [ -n "$entry" ]; then
|
||||
gopass show -c "$entry" username 2>/dev/null || notify-send "Gopass Error" "Failed to copy username from: $entry"
|
||||
fi
|
||||
|
||||
47
.local/bin/todo
Executable file
47
.local/bin/todo
Executable file
@@ -0,0 +1,47 @@
|
||||
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
TODO_FILE="$HOME/docs/todo.txt"
|
||||
ARCHIVE_FILE="$HOME/docs/todo-archive.txt"
|
||||
TODAY="$(date +%Y-%m-%d)"
|
||||
|
||||
case "$1" in
|
||||
add)
|
||||
shift
|
||||
echo "($TODAY) $*" >> "$TODO_FILE"
|
||||
echo "Added: ($TODAY) $*"
|
||||
;;
|
||||
lsa)
|
||||
nl -w2 -s'. ' "$TODO_FILE"
|
||||
;;
|
||||
ls)
|
||||
grep -v '^x ' "$TODO_FILE" | nl -w2 -s'. '
|
||||
;;
|
||||
done)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Usage: $0 done <task-number>"
|
||||
exit 1
|
||||
fi
|
||||
TASK=$(sed -n "${2}p" "$TODO_FILE")
|
||||
[ -z "$TASK" ] && { echo "Invalid task number."; exit 1; }
|
||||
sed -i "${2}s/^/x ($TODAY) /" "$TODO_FILE"
|
||||
echo "Marked done: $TASK"
|
||||
;;
|
||||
archive)
|
||||
grep '^x ' "$TODO_FILE" >> "$ARCHIVE_FILE"
|
||||
sed -i '/^x /d' "$TODO_FILE"
|
||||
echo "Archived completed tasks to $ARCHIVE_FILE"
|
||||
;;
|
||||
tags)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Usage: $0 tags <+tag|@context>"
|
||||
exit 1
|
||||
fi
|
||||
grep "$2" "$TODO_FILE" | grep -v '^x ' | nl -w2 -s'. '
|
||||
;;
|
||||
help|*)
|
||||
echo "Usage: $0 {add <task> | list | done <number> | archive}"
|
||||
;;
|
||||
esac
|
||||
|
||||
50
.local/bin/vault
Executable file
50
.local/bin/vault
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONTAINER=${2:-"$HOME/vault.hc"}
|
||||
|
||||
BASENAME=$(basename "$CONTAINER")
|
||||
MAPPER_NAME="${BASENAME%.*}"
|
||||
MOUNT_POINT="/mnt/$MAPPER_NAME"
|
||||
|
||||
case "$1" in
|
||||
open)
|
||||
if [ ! -f "$CONTAINER" ]; then
|
||||
echo "Container not found: $CONTAINER"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "/dev/mapper/$MAPPER_NAME" ]; then
|
||||
echo "Already opened at /dev/mapper/$MAPPER_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$MOUNT_POINT" || exit 1
|
||||
|
||||
if sudo cryptsetup open --type tcrypt "$CONTAINER" "$MAPPER_NAME"; then
|
||||
sudo mount "/dev/mapper/$MAPPER_NAME" "$MOUNT_POINT" &&
|
||||
echo "Mounted at $MOUNT_POINT"
|
||||
else
|
||||
echo "Failed to open container."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
close)
|
||||
if mountpoint -q "$MOUNT_POINT"; then
|
||||
sudo umount "$MOUNT_POINT"
|
||||
fi
|
||||
|
||||
if [ -e "/dev/mapper/$MAPPER_NAME" ]; then
|
||||
sudo cryptsetup close "$MAPPER_NAME"
|
||||
echo "Closed and unmounted $MOUNT_POINT."
|
||||
else
|
||||
echo "Container is not open."
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {open|close} [path/to/container.hc]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
1630
.local/share/chars/emojis
Normal file
1630
.local/share/chars/emojis
Normal file
File diff suppressed because it is too large
Load Diff
19
.yash_env
Normal file
19
.yash_env
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Environment exports
|
||||
export XDG_CONFIG_HOME="$HOME/.config"
|
||||
export XDG_CACHE_HOME="$HOME/.cache"
|
||||
export XDG_DATA_HOME="$HOME/.local/share"
|
||||
export VISUAL=nvim
|
||||
export EDITOR=nvim
|
||||
export BROWSER=/usr/bin/librewolf
|
||||
export LANG=en_US.UTF-8
|
||||
export LC_ALL=en_US.UTF-8
|
||||
|
||||
export XDG_DATA_DIRS="/usr/share"
|
||||
export XDG_CURRENT_DESKTOP="sway"
|
||||
export XDG_SESSION_DESKTOP="sway"
|
||||
export XDG_SESSION_TYPE="wayland"
|
||||
export GTK_ICON_THEME="Papirus"
|
||||
export QT_QPA_PLATFORMTHEME=gtk3
|
||||
|
||||
9
.yash_profile
Normal file
9
.yash_profile
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -f "$HOME/.yash_env" ]; then
|
||||
. "$HOME/.yash_env"
|
||||
fi
|
||||
|
||||
if [ -z "$WAYLAND_DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then
|
||||
exec dbus-run-session sway
|
||||
fi
|
||||
69
.yashrc
Normal file
69
.yashrc
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
# Load global initialization script, if exists.
|
||||
if [ -f /etc/yashrc ]; then
|
||||
. /etc/yashrc
|
||||
fi
|
||||
|
||||
|
||||
#######################################################
|
||||
# Alias
|
||||
#######################################################
|
||||
|
||||
alias v='nvim'
|
||||
alias vim='nvim'
|
||||
alias vi='nvim'
|
||||
|
||||
alias add='doas apk add'
|
||||
alias del='doas apk del'
|
||||
alias search='apk search'
|
||||
alias info='doas apk info'
|
||||
alias update='doas apk update'
|
||||
alias upgrade='doas apk upgrade'
|
||||
|
||||
alias ll='ls -lF --color=auto'
|
||||
alias la='ls -A --color=auto'
|
||||
alias gs='git status'
|
||||
alias clr='clear'
|
||||
|
||||
#######################################################
|
||||
# Exports & Shell Vars
|
||||
#######################################################
|
||||
|
||||
export HISTFILE="$HOME/.yash_history"
|
||||
export HISTSIZE=99999
|
||||
export PATH="$HOME/bin:/sbin:/usr/sbin:/bin:/usr/bin:$PATH"
|
||||
|
||||
#######################################################
|
||||
# Prompt
|
||||
#######################################################
|
||||
|
||||
PS1='$(pwd) $ '
|
||||
|
||||
#######################################################
|
||||
# SSH
|
||||
#######################################################
|
||||
|
||||
keys() {
|
||||
eval "$(keychain --eval --quiet ry_ecdsa)"
|
||||
eval "$(keychain --eval --quiet id_rsa)"
|
||||
}
|
||||
|
||||
keys
|
||||
|
||||
#######################################################
|
||||
# WORK
|
||||
#######################################################
|
||||
|
||||
# Wireguard
|
||||
alias wgup='doas wg-quick up /etc/wireguard/wg0.conf'
|
||||
alias wgdown='doas wg-quick down /etc/wireguard/wg0.conf'
|
||||
|
||||
#######################################################
|
||||
# Misc
|
||||
#######################################################
|
||||
|
||||
# Uncomment if you want to clear the screen with Ctrl-L.
|
||||
bindkey --emacs '\^L' clear-and-redraw-all
|
||||
bindkey --vi-insert '\^L' clear-and-redraw-all
|
||||
bindkey --vi-command '\^L' clear-and-redraw-all
|
||||
|
||||
Reference in New Issue
Block a user