qutebrowser: Make use of dotter for dir structure
Since we now use dotter we can simplify the dir structure for qutebrowser a lot. Everything dot-filed earlier can now reside in simple directories called config (for ~/.config/qutebrowser), data (for ~/.local/share/qutebrowser), and scripts (for ~/.local/bin) files.
This commit is contained in:
parent
dcde027a67
commit
8681d34946
49 changed files with 9 additions and 5 deletions
7
qutebrowser/data/cookie-blockers/aol.com.xml
Normal file
7
qutebrowser/data/cookie-blockers/aol.com.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#consent-page > div > div > div > form > div.wizard-body > div.actions.couple > a"/>
|
||||
<wait/>
|
||||
<click element="#select-legit-all-purpose > span.toggleAll.toggle-accpet-all"/>
|
||||
<click element="#consent-page > div > form > div.page-footer > div > div > button"/>
|
||||
</block>
|
||||
17160
qutebrowser/data/cookie-blockers/blocklist.txt
Normal file
17160
qutebrowser/data/cookie-blockers/blocklist.txt
Normal file
File diff suppressed because it is too large
Load diff
9
qutebrowser/data/cookie-blockers/consent.youtube.com.xml
Normal file
9
qutebrowser/data/cookie-blockers/consent.youtube.com.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div.NIoIEf > div.G4njw > div.qqtRac > div > div > div > a"/>
|
||||
<wait/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > div:nth-child(3) > div.uScs5d > div > div.uScs5d > div:nth-child(1) > div > button"/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > div:nth-child(4) > div.uScs5d > div > div.uScs5d > div:nth-child(1) > div > button"/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > div:nth-child(5) > div.IgeUeb > div.uScs5d > div > div.uScs5d > div:nth-child(1) > div > button"/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > form > div > button"/>
|
||||
</block>
|
||||
5
qutebrowser/data/cookie-blockers/ebay.com.xml
Normal file
5
qutebrowser/data/cookie-blockers/ebay.com.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<!-- TODO: You cannot block cookies on ebay -->
|
||||
<click element="#gdpr-banner > div.gdpr-banner__wrapper > div > a"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/espn.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/espn.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#onetrust-reject-all-handler"/>
|
||||
</block>
|
||||
6
qutebrowser/data/cookie-blockers/etsy.com.xml
Normal file
6
qutebrowser/data/cookie-blockers/etsy.com.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#gdpr-single-choice-overlay > div > div.wt-overlay__footer.wt-pt-xs-3 > div.wt-overlay__footer__action.wt-display-flex-md.wt-flex-grow-md-1.wt-order-xs-1.wt-order-md-neg1.wt-justify-content-flex-end > button"/>
|
||||
<wait/>
|
||||
<click element="#gdpr-privacy-settings > div > div.wt-overlay__footer.wt-align-items-center > div.wt-overlay__footer__action > div > div:nth-child(3) > button"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/facebook.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/facebook.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<!-- TODO: Facebook changes IDs of buttons -->
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/foxnews.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/foxnews.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#wrapper > div.notification-banner > div > a"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/geeksforgeeks.org.xml
Normal file
4
qutebrowser/data/cookie-blockers/geeksforgeeks.org.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<remove element=".hide-consent"/>
|
||||
</block>
|
||||
9
qutebrowser/data/cookie-blockers/google.com.xml
Normal file
9
qutebrowser/data/cookie-blockers/google.com.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#EDu5ze > div"/>
|
||||
<wait/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > div:nth-child(4) > div.uScs5d > div > div.uScs5d > div:nth-child(1) > div > button"/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > div:nth-child(5) > div.uScs5d > div > div.uScs5d > div:nth-child(1) > div > button"/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > div:nth-child(6) > div.IgeUeb > div.uScs5d > div > div.uScs5d > div:nth-child(1) > div > button"/>
|
||||
<click element="#yDmH0d > c-wiz > div > div > div > div.VP4fnf > form > div > button"/>
|
||||
</block>
|
||||
7
qutebrowser/data/cookie-blockers/healthline.com.xml
Normal file
7
qutebrowser/data/cookie-blockers/healthline.com.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<!-- WARNING: The cookie-free version of this websites looks very different-->
|
||||
<click element="#modal-host > div > div > div > div > div > div > div.css-zndjj2 > a"/>
|
||||
<wait time="1000"/>
|
||||
<click element="#__next > div.css-qbih8b > div > button.css-1glzvq1"/>
|
||||
</block>
|
||||
5
qutebrowser/data/cookie-blockers/indeed.com.xml
Normal file
5
qutebrowser/data/cookie-blockers/indeed.com.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#onetrust-pc-btn-handler"/>
|
||||
<click element="#cookie-preferences > div.save-preference-btn-container > button"/>
|
||||
</block>
|
||||
5
qutebrowser/data/cookie-blockers/instagram.com.xml
Normal file
5
qutebrowser/data/cookie-blockers/instagram.com.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<!-- TODO: You cannot block cookies, only accept? -->
|
||||
<click element="body > div.RnEpo.Yx5HN > div > div > div > div.mt3GC > button.aOOlW.HoLwm"/>
|
||||
</block>
|
||||
6
qutebrowser/data/cookie-blockers/linkedin.com.xml
Normal file
6
qutebrowser/data/cookie-blockers/linkedin.com.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#artdeco-global-alert-container > div.artdeco-global-alert.artdeco-global-alert--NOTICE.artdeco-global-alert--COOKIE_CONSENT > section > div > div.artdeco-global-alert-action__wrapper > button:nth-child(1)"/>
|
||||
<wait time="1500"/>
|
||||
<click element="body > header > a:nth-child(1) > li-icon"/>
|
||||
</block>
|
||||
6
qutebrowser/data/cookie-blockers/medicalnews.com.xml
Normal file
6
qutebrowser/data/cookie-blockers/medicalnews.com.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#modal-host > div > div > div > div > div > div > div.css-zndjj2 > a"/>
|
||||
<wait time="1000"/>
|
||||
<click element="#__next > div.css-1m0hjq0 > div > button.css-1mzn52w"/>
|
||||
</block>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#modal-host > div > div > div > div > div > div > div.css-zndjj2 > a"/>
|
||||
<wait/>
|
||||
<click element="#__next > div.css-1m0hjq0 > div > button.css-1mzn52w"/>
|
||||
</block>
|
||||
9
qutebrowser/data/cookie-blockers/microsoft.com.xml
Normal file
9
qutebrowser/data/cookie-blockers/microsoft.com.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#wcpConsentBannerCtrl > div._2j0fmugLb1FgYz6KPuB91w > button:nth-child(2)"/>
|
||||
<wait/>
|
||||
<click element="#_1dp8Vp5m3HwAqGx8qBmFV2_c1_reject"/>
|
||||
<click element="#_1dp8Vp5m3HwAqGx8qBmFV2_c2_reject"/>
|
||||
<click element="#_1dp8Vp5m3HwAqGx8qBmFV2_c3_reject"/>
|
||||
<click element="#wcpCookiePreferenceCtrl > div.AFsJE948muYyzCMktdzuk > div > div.nohp3sIG12ZBhzcMnPala > button._3tOu1FJ59c_xz_PmI1lKV5._1zNQOqxpBFSokeCLGi_hGr"/>
|
||||
</block>
|
||||
7
qutebrowser/data/cookie-blockers/netflix.com.xml
Normal file
7
qutebrowser/data/cookie-blockers/netflix.com.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<!-- TODO: Clicking on the button does not work -->
|
||||
<!-- <click element="#cookie-disclosure > div.cta-btn-container > button:nth-child(2)"/> -->
|
||||
<!-- TODO: Workaround: Close -->
|
||||
<click element="#cookie-disclosure > div.btn-container > button > span.icon-close"/>
|
||||
</block>
|
||||
54
qutebrowser/data/cookie-blockers/nytimes.com.xml
Normal file
54
qutebrowser/data/cookie-blockers/nytimes.com.xml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<!-- CANNOT OPT OUT OF EVERYTHING -->
|
||||
<!-- TODO: Does not work? -->
|
||||
<click element="#site-content > div.gdpr.shown.expanded.expanded-dock.css-17nqy7q.e1x0szx60 > div.css-183a15u.ejw0p350 > div > div.css-1s2i4vk > a"/>
|
||||
<debug/>
|
||||
<wait/>
|
||||
<debug msg="After"/>
|
||||
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(1) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(2) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(3) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(4) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(5) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(6) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(7) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(8) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(9) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(10) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(11) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(12) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-2 > tbody > tr:nth-child(14) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(1) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(2) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(3) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(4) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(5) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(6) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(7) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(8) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(9) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(10) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(11) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(12) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(13) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(14) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(15) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(16) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(17) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(18) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-3 > tbody > tr:nth-child(19) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
|
||||
<click element="#gdpr-faq-cookie-table-4 > tbody > tr:nth-child(1) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-4 > tbody > tr:nth-child(2) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-4 > tbody > tr:nth-child(3) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-4 > tbody > tr:nth-child(4) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-4 > tbody > tr:nth-child(7) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#gdpr-faq-cookie-table-4 > tbody > tr:nth-child(8) > td:nth-child(5) > a:nth-child(2)"/>
|
||||
<click element="#opt-out-of-new-york-times-nonessential-trackers"/>
|
||||
|
||||
<!-- TODO: Close the new tab -->
|
||||
<!-- TODO: Close the banner -->
|
||||
</block>
|
||||
8
qutebrowser/data/cookie-blockers/paypal.com.xml
Normal file
8
qutebrowser/data/cookie-blockers/paypal.com.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#manageCookiesLink"/>
|
||||
<wait time="1000"/>
|
||||
<click element="#performance"/>
|
||||
<click element="#functional"/>
|
||||
<click element="#submitCookiesBtn"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/reddit.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/reddit.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#SHORTCUT_FOCUSABLE_DIV > div:nth-child(6) > div._3q-XSJ2vokDQrvdG6mR__k > section > div > section > section > form:nth-child(1) > button"/>
|
||||
</block>
|
||||
6
qutebrowser/data/cookie-blockers/roblox.com.xml
Normal file
6
qutebrowser/data/cookie-blockers/roblox.com.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#cookie-link-manage"/>
|
||||
<!-- TODO: Not sure clicking the right thing -->
|
||||
<click element="#cookie-btn-allow"/>
|
||||
</block>
|
||||
6
qutebrowser/data/cookie-blockers/stackoverflow.com.xml
Normal file
6
qutebrowser/data/cookie-blockers/stackoverflow.com.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="body > div.ff-sans.ps-fixed.z-nav-fixed.ws4.sm\\:w-auto.p32.bg-black-750.fc-white.bar-lg.b16.l16.r16.js-consent-banner > div > button.grid--cell.s-btn.s-btn__filled.js-cookie-settings"/>
|
||||
<wait time="1000"/>
|
||||
<click element="#onetrust-pc-sdk > div > div.s-modal--footer.mt0.grid.gs8.gsx > button.grid--cell.s-btn.s-btn__primary.save-preference-btn-handler.onetrust-close-btn-handler.js-consent-banner-hide.js-consent-save"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/steampowered.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/steampowered.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#rejectAllButton"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/twitter.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/twitter.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#react-root > div > div > div.css-1dbjc4n.r-13qz1uu.r-417010 > main > div > div > div.css-1dbjc4n.r-1awozwy.r-1m3jxhj.r-1upvrn0.r-18u37iz.r-1d7fvdj.r-d9fdf6.r-tvv088.r-13qz1uu > div.css-18t94o4.css-1dbjc4n.r-1niwhzg.r-11mg6pl.r-sdzlij.r-1phboty.r-rs99b7.r-18kxxzh.r-1q142lx.r-1w2pmg.r-19u6a5r.r-1mnahxq.r-ero68b.r-1gg2371.r-1ny4l3l.r-1fneopy.r-o7ynqc.r-6416eg.r-lrvibr > div > span"/>
|
||||
</block>
|
||||
4
qutebrowser/data/cookie-blockers/wolframalpha.com.xml
Normal file
4
qutebrowser/data/cookie-blockers/wolframalpha.com.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<remove element=".oaDry"/>
|
||||
</block>
|
||||
8
qutebrowser/data/cookie-blockers/yahoo.com.xml
Normal file
8
qutebrowser/data/cookie-blockers/yahoo.com.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<block>
|
||||
<click element="#consent-page > div > div > div > form > div.wizard-body > div.actions.couple > a"/>
|
||||
<wait time="2000"/>
|
||||
<!-- This is not my spelling mistake :) vvvvvv -->
|
||||
<click element="#select-legit-all-purpose > span.toggleAll.toggle-accpet-all"/>
|
||||
<click element="#consent-page > div > form > div.page-footer > div > div > button"/>
|
||||
</block>
|
||||
54
qutebrowser/data/userscripts/code_select.py
Executable file
54
qutebrowser/data/userscripts/code_select.py
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import html
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
try:
|
||||
import pyperclip
|
||||
except ImportError:
|
||||
PYPERCLIP = False
|
||||
else:
|
||||
PYPERCLIP = True
|
||||
|
||||
|
||||
def parse_text_content(element) -> str:
|
||||
root = ET.fromstring(element)
|
||||
text = ET.tostring(root, encoding="unicode", method="text")
|
||||
text = html.unescape(text)
|
||||
return text
|
||||
|
||||
|
||||
def send_command_to_qute(command) -> None:
|
||||
if fifo := os.environ.get("QUTE_FIFO"):
|
||||
with open(fifo, "w") as f:
|
||||
f.write(command)
|
||||
|
||||
|
||||
def main():
|
||||
delimiter = sys.argv[1] if len(sys.argv) > 1 else ";"
|
||||
# For info on qute environment vairables, see
|
||||
# https://github.com/qutebrowser/qutebrowser/blob/master/doc/userscripts.asciidoc
|
||||
element = os.environ.get("QUTE_SELECTED_HTML")
|
||||
code_text = parse_text_content(element)
|
||||
if pyperclip and PYPERCLIP:
|
||||
pyperclip.copy(code_text)
|
||||
send_command_to_qute(
|
||||
"message-info 'copied to clipboard: {info}{suffix}'".format(
|
||||
info=code_text.splitlines()[0],
|
||||
suffix="..." if len(code_text.splitlines()) > 1 else "",
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Qute's yank command won't copy accross multiple lines so we
|
||||
# compromise by placing lines on a single line seperated by the
|
||||
# specified delimiter
|
||||
code_text = re.sub("(\n)+", delimiter, code_text)
|
||||
code_text = code_text.replace("'", '"')
|
||||
send_command_to_qute("yank inline '{code}'\n".format(code=code_text))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
116
qutebrowser/data/userscripts/doi2scihub
Executable file
116
qutebrowser/data/userscripts/doi2scihub
Executable file
|
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Goes to the sci-hub page for the current article, based on DOI.
|
||||
|
||||
|
||||
Based on the work in
|
||||
https://github.com/cadadr/configuration/blob/4b6a241d04d113f322b960890a0d0a0ab783a7b3/dotfiles/qutebrowser/userscripts/doi
|
||||
with much gratitude.
|
||||
|
||||
The program can be invoked with DOI on a page selected, through the hinting mode when selecting a DOI link or on a publisher page (any page where doi meta-tags are set) - works on ScienceDirect, Taylor&Francis, Springer, etc.
|
||||
That means you can give it a doi through a link or on the current page, for example with the following mappings:
|
||||
|
||||
```python
|
||||
config.bind('"p', "spawn --userscript doi2scihub")
|
||||
config.bind(';p', "hint links userscript doi2scihub")
|
||||
```
|
||||
|
||||
You can also pass the doi as the (only) argument to the userscript:
|
||||
|
||||
```
|
||||
:spawn --userscript doi2scihub https://doi.org/10.37394/23207.2021.18.68
|
||||
`
|
||||
|
||||
Updates its sci-hub link based on the one listed on sci-hub wiki page.
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import html.parser
|
||||
import requests
|
||||
|
||||
|
||||
mode = os.getenv("QUTE_MODE")
|
||||
|
||||
text = None
|
||||
|
||||
class DoiTagParser(html.parser.HTMLParser):
|
||||
doi = None
|
||||
|
||||
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
||||
if self.doi == None and tag == "meta":
|
||||
if (
|
||||
("name", "citation_doi") in attrs
|
||||
or ("name", "dc.identifier") in attrs
|
||||
or ("scheme", "doi") in attrs
|
||||
):
|
||||
for att in attrs:
|
||||
if att[0] == "content":
|
||||
self.doi = att[1]
|
||||
break
|
||||
|
||||
|
||||
class SciHubLinkParser(html.parser.HTMLParser):
|
||||
current = None
|
||||
link_patt = re.compile(r"^(?P<url>https?://sci-hub\..+)/about$")
|
||||
|
||||
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
||||
if self.current == None and tag == "a":
|
||||
for att in attrs:
|
||||
if att[0] == "href" and self.link_patt.match(att[1] or ""):
|
||||
match = self.link_patt.match(att[1] or "")
|
||||
self.current = match["url"] if match and match["url"] else None
|
||||
|
||||
|
||||
def get_scihub_url(wiki_page: str = "https://wikiless.org/wiki/Sci-Hub"):
|
||||
resp = requests.get(wiki_page)
|
||||
parser = SciHubLinkParser()
|
||||
parser.feed(resp.text)
|
||||
return parser.current or "https://sci-hub.ru"
|
||||
|
||||
|
||||
# use doi argument if we got one
|
||||
if len(sys.argv) > 1:
|
||||
text = sys.argv[1]
|
||||
# use the hinted url
|
||||
elif mode == "hints":
|
||||
text = os.getenv("QUTE_URL", "").strip()
|
||||
# use the current selection
|
||||
elif mode == "command" and os.getenv("QUTE_SELECTED_TEXT"):
|
||||
text = os.getenv("QUTE_SELECTED_TEXT", "").strip()
|
||||
# just try to find a doi on current page
|
||||
elif os.getenv("QUTE_HTML"):
|
||||
with open(os.getenv("QUTE_HTML", ""), "r") as source:
|
||||
parser = DoiTagParser()
|
||||
parser.feed(source.read())
|
||||
text = parser.doi
|
||||
|
||||
with open(os.getenv("QUTE_FIFO", ""), "w") as fifo:
|
||||
if not text:
|
||||
fifo.write(f'message-warning "Could not find a valid DOI"')
|
||||
sys.exit()
|
||||
|
||||
# DOI syntax: https://www.doi.org/doi_handbook/2_Numbering.html#2.2.
|
||||
#
|
||||
# Note that this probably matches a subset of possible DOIs, as it
|
||||
# seems that there’s no practical limitation on neither the length nor
|
||||
# the contents of the DOI. But IMHO this is a healthy subset.
|
||||
doi_re = re.compile(
|
||||
# match possible URI prefix
|
||||
r"(?P<blah>((https?)?://)?doi\.org/)?"
|
||||
# match actual DOI
|
||||
r"(?P<meat>[a-zA-Z0-9\./\-_]+)"
|
||||
)
|
||||
|
||||
match = doi_re.match(text)
|
||||
if match is None or match["meat"] is None:
|
||||
fifo.write(
|
||||
f"message-warning \"'{text}' is probably not a DOI, or update regexp\""
|
||||
)
|
||||
|
||||
else:
|
||||
url = get_scihub_url()
|
||||
doi = match["meat"]
|
||||
fifo.write(f"open -t {url}/{doi}")
|
||||
10
qutebrowser/data/userscripts/pagetopdf.sh
Executable file
10
qutebrowser/data/userscripts/pagetopdf.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#! /usr/bin/bash
|
||||
# Download current page as pdf file
|
||||
|
||||
# use title of current page / selected text as filename
|
||||
filename=${QUTE_SELECTED_TEXT:-$QUTE_TITLE}
|
||||
# revert to default name if nothing else is set; remove special chars
|
||||
filename=$(echo "${filename:-downloaded.pdf}" | sed 's/[<>,/]/_/g')
|
||||
|
||||
# print to pdf
|
||||
echo "print --pdf '$QUTE_DOWNLOAD_DIR/${1:-$filename}.pdf'" >>"$QUTE_FIFO"
|
||||
BIN
qutebrowser/data/userscripts/qute-cookie-block
Executable file
BIN
qutebrowser/data/userscripts/qute-cookie-block
Executable file
Binary file not shown.
398
qutebrowser/data/userscripts/qute-gemini
Executable file
398
qutebrowser/data/userscripts/qute-gemini
Executable file
|
|
@ -0,0 +1,398 @@
|
|||
#!/usr/bin/env python3
|
||||
# qute-gemini - Open Gemini links in qutebrowser and render them as HTML
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2019-2020 solderpunk
|
||||
# SPDX-FileCopyrightText: 2020 Aaron Janse
|
||||
# SPDX-FileCopyrightText: 2020 petedussin
|
||||
# SPDX-FileCopyrightText: 2020-2021 Sotiris Papatheodorou
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# 2022-2023 Marty Oehme (added stand-alone script capability)
|
||||
|
||||
# Use it as a qutebrowser userscript to open gemini pages:
|
||||
# Put this file in qutebrowser userscript folder and call command
|
||||
# `:spawn --userscript qute-gemini "gemini://my-gemini-url.org"`
|
||||
# or
|
||||
# `:hint links userscript qute-gemini` to open from selected link
|
||||
# Rename file to `qute-gemini-tab` (or create symlink) to open
|
||||
# any gemini url as a new tab.
|
||||
|
||||
# Since the script also opens normal URLs you can even replace your
|
||||
# normal link hint mapping with it (usually f or F for tabbed) and
|
||||
# continue surfing like normal, only that you can now also access
|
||||
# any gemini pages as if they were part of the normal http protocol.
|
||||
|
||||
import cgi
|
||||
import html
|
||||
import os
|
||||
import socket
|
||||
import ssl
|
||||
import sys
|
||||
import tempfile
|
||||
import urllib.parse
|
||||
|
||||
from typing import Tuple
|
||||
|
||||
_version = "1.0.0"
|
||||
|
||||
_max_redirects = 5
|
||||
|
||||
_error_page_template = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<title>Error opening page: URL</title>
|
||||
<style>
|
||||
CSS
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>qute-gemini error</h1>
|
||||
<p>Error while opening:<br/><a href="URL">URL_TEXT</a></p>
|
||||
<p>DESCRIPTION</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
_status_code_desc = {
|
||||
"1": "Gemini status code 1 Input. This is not implemented in qute-gemini.",
|
||||
"10": "Gemini status code 10 Input. This is not implemented in qute-gemini.",
|
||||
"11": """Gemini status code 11 Sensitive Input. This is not implemented
|
||||
in qute-gemini.""",
|
||||
"3": "Gemini status code 3 Redirect. Stopped after "
|
||||
+ str(_max_redirects)
|
||||
+ " redirects.",
|
||||
"30": "Gemini status code 30 Temporary Redirect. Stopped after "
|
||||
+ str(_max_redirects)
|
||||
+ " redirects.",
|
||||
"31": "Gemini status code 31 Permanent Redirect. Stopped after "
|
||||
+ str(_max_redirects)
|
||||
+ " redirects.",
|
||||
"4": "Gemini status code 4 Temporary Failure. Server message: META",
|
||||
"40": "Gemini status code 40 Temporary Failure. Server message: META",
|
||||
"41": """Gemini status code 41 Server Unavailable.
|
||||
The server is unavailable due to overload or maintenance. Server message: META""",
|
||||
"42": """Gemini status code 42 CGI Error.
|
||||
A CGI process, or similar system for generating dynamic content,
|
||||
died unexpectedly or timed out. Server message: META""",
|
||||
"43": """Gemini status code 43 Proxy Error.
|
||||
A proxy request failed because the server was unable to successfully
|
||||
complete a transaction with the remote host. Server message: META""",
|
||||
"44": """Gemini status code 44 Slow Down. Rate limiting is in effect.
|
||||
Please wait META seconds before making another request to this server.""",
|
||||
"5": "Gemini status code 5 Permanent Failure. Server message: META",
|
||||
"50": "Gemini status code 50 Permanent Failure. Server message: META",
|
||||
"51": """Gemini status code 51 Not Found. The requested resource could
|
||||
not be found but may be available in the future. Server message: META""",
|
||||
"52": """Gemini status code 52 Gone. The resource requested is no longer
|
||||
available and will not be available again. Server message: META""",
|
||||
"53": """Gemini status code 53 Proxy Request Refused. The request was for
|
||||
a resource at a domain not served by the server and the server does
|
||||
not accept proxy requests. Server message: META""",
|
||||
"59": """Gemini status code 59 Bad Request. The server was unable to
|
||||
parse the client's request, presumably due to a malformed request.
|
||||
Server message: META""",
|
||||
"6": """Gemini status code 6 Client Certificate Required.
|
||||
This is not implemented in qute-gemini.""",
|
||||
}
|
||||
|
||||
|
||||
def qute_url() -> str:
|
||||
"""Get the URL passed to the script by qutebrowser."""
|
||||
return os.environ.get("QUTE_URL", "")
|
||||
|
||||
|
||||
def qute_fifo() -> str:
|
||||
"""Get the FIFO or file to write qutebrowser commands to."""
|
||||
return os.environ.get("QUTE_FIFO", "")
|
||||
|
||||
|
||||
def html_href(url: str, description: str) -> str:
|
||||
return "".join(['<a href="', url, '">', description, "</a>"])
|
||||
|
||||
|
||||
def qute_gemini_css_path() -> str:
|
||||
"""Return the path where the custom CSS file is expected to be."""
|
||||
try:
|
||||
base_dir = os.environ["XDG_DATA_HOME"]
|
||||
except KeyError:
|
||||
base_dir = os.path.join(os.environ["HOME"], ".local/share")
|
||||
return os.path.join(base_dir, "qutebrowser/userscripts/qute-gemini.css")
|
||||
|
||||
|
||||
def gemini_absolutise_url(base_url: str, relative_url: str) -> str:
|
||||
"""Absolutise relative gemini URLs.
|
||||
|
||||
Adapted from gcat: https://github.com/aaronjanse/gcat
|
||||
"""
|
||||
if "://" not in relative_url:
|
||||
# Python's URL tools somehow only work with known schemes?
|
||||
base_url = base_url.replace("gemini://", "http://")
|
||||
relative_url = urllib.parse.urljoin(base_url, relative_url)
|
||||
relative_url = relative_url.replace("http://", "gemini://")
|
||||
return relative_url
|
||||
|
||||
|
||||
def gemini_fetch_url(url: str) -> Tuple[str, str, str, str, str]:
|
||||
"""Fetch a Gemini URL and return the content as a string.
|
||||
|
||||
url: URL with gemini:// or no scheme.
|
||||
Returns 4 strings: the content, the URL the content was fetched from, the
|
||||
Gemini status code, the value of the meta field and an error message.
|
||||
|
||||
Adapted from gcat: https://github.com/aaronjanse/gcat
|
||||
"""
|
||||
# Parse the URL to get the hostname and port
|
||||
parsed_url = urllib.parse.urlparse(url)
|
||||
if not parsed_url.scheme:
|
||||
url = "gemini://" + url
|
||||
parsed_url = urllib.parse.urlparse(url)
|
||||
if parsed_url.scheme != "gemini":
|
||||
return "", "Received non-gemini:// URL: " + url, "59", "", "Non-gemini URL"
|
||||
if parsed_url.port is not None:
|
||||
useport = parsed_url.port
|
||||
else:
|
||||
useport = 1965
|
||||
# Do the Gemini transaction, looping for redirects
|
||||
redirects = 0
|
||||
while True:
|
||||
# Send the request
|
||||
s = socket.create_connection((parsed_url.hostname, useport))
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
||||
context.check_hostname = False
|
||||
context.verify_mode = ssl.CERT_NONE
|
||||
s = context.wrap_socket(s, server_hostname=parsed_url.netloc)
|
||||
s.sendall((url + "\r\n").encode("UTF-8"))
|
||||
# Get the status code and meta
|
||||
fp = s.makefile("rb")
|
||||
header = fp.readline().decode("UTF-8").strip()
|
||||
status, meta = header.split()[:2]
|
||||
# Follow up to 5 redirects
|
||||
if status.startswith("3"):
|
||||
url = gemini_absolutise_url(url, meta)
|
||||
parsed_url = urllib.parse.urlparse(url)
|
||||
redirects += 1
|
||||
if redirects > _max_redirects:
|
||||
# Too many redirects
|
||||
break
|
||||
# Otherwise we're done
|
||||
else:
|
||||
break
|
||||
# Process the response
|
||||
content = ""
|
||||
error_msg = ""
|
||||
# 2x Success
|
||||
if status.startswith("2"):
|
||||
media_type, media_type_opts = cgi.parse_header(meta)
|
||||
# Decode according to declared charset defaulting to UTF-8
|
||||
if meta.startswith("text/gemini"):
|
||||
charset = media_type_opts.get("charset", "UTF-8")
|
||||
content = fp.read().decode(charset)
|
||||
else:
|
||||
error_msg = "Expected media type text/gemini but received " + media_type
|
||||
# Handle errors
|
||||
else:
|
||||
# Try matching a 2-digit and then a 1-digit status code
|
||||
try:
|
||||
error_msg = _status_code_desc[status[0:2]]
|
||||
except KeyError:
|
||||
try:
|
||||
error_msg = _status_code_desc[status[0]]
|
||||
except KeyError:
|
||||
error_msg = "The server sent back something weird."
|
||||
# Substitute the contents of meta into the error message if needed
|
||||
error_msg = error_msg.replace("META", meta)
|
||||
return content, url, status, meta, error_msg
|
||||
|
||||
|
||||
def gemtext_to_html(
|
||||
gemtext: str, url: str, original_url: str, status: str, meta: str
|
||||
) -> str:
|
||||
"""Convert gemtext to HTML.
|
||||
|
||||
title: Used as the document title.
|
||||
url: The URL the gemtext was received from. Used to resolve
|
||||
relative URLs in the gemtext content.
|
||||
original_url: The URL the original request was made at.
|
||||
status: The Gemini status code returned by the server.
|
||||
meta: The meta returned by the server.
|
||||
Returns the HTML representation as a string.
|
||||
"""
|
||||
# Accumulate converted gemtext lines
|
||||
lines = [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">',
|
||||
"\t<head>",
|
||||
"\t\t<title>" + html.escape(url) + "</title>",
|
||||
"\t\t<style>",
|
||||
get_css(),
|
||||
"\t\t</style>",
|
||||
"\t</head>",
|
||||
"\t<body>",
|
||||
"\t<article>",
|
||||
]
|
||||
in_pre = False
|
||||
in_list = False
|
||||
# Add an extra newline to ensure list tags are closed properly
|
||||
for line in (gemtext + "\n").splitlines():
|
||||
# Add the list closing tag
|
||||
if not line.startswith("*") and in_list:
|
||||
lines.append("\t\t</ul>")
|
||||
in_list = False
|
||||
# Blank line, ignore
|
||||
if not line:
|
||||
pass
|
||||
# Link
|
||||
elif line.startswith("=>"):
|
||||
ln = line[2:].split(None, 1)
|
||||
# Use the URL itself as the description if there is none
|
||||
if len(ln) == 1:
|
||||
ln.append(ln[0])
|
||||
# Encode the link description
|
||||
ln[1] = html.escape(ln[1])
|
||||
# Resolve relative URLs
|
||||
ln[0] = gemini_absolutise_url(url, ln[0])
|
||||
lines.append("\t\t<p>" + html_href(ln[0], ln[1]) + "</p>")
|
||||
# Preformated toggle
|
||||
elif line.startswith("```"):
|
||||
if in_pre:
|
||||
lines.append("\t\t</pre>")
|
||||
else:
|
||||
lines.append("\t\t<pre>")
|
||||
in_pre = not in_pre
|
||||
# Preformated
|
||||
elif in_pre:
|
||||
lines.append(line)
|
||||
# Header
|
||||
elif line.startswith("###"):
|
||||
lines.append("\t\t<h3>" + html.escape(line[3:].strip()) + "</h3>")
|
||||
elif line.startswith("##"):
|
||||
lines.append("\t\t<h2>" + html.escape(line[2:].strip()) + "</h2>")
|
||||
elif line.startswith("#"):
|
||||
lines.append("\t\t<h1>" + html.escape(line[1:].strip()) + "</h1>")
|
||||
# List
|
||||
elif line.startswith("*"):
|
||||
if not in_list:
|
||||
lines.append("\t\t<ul>")
|
||||
in_list = True
|
||||
lines.append("\t\t\t<li>" + html.escape(line[1:].strip()) + "</li>")
|
||||
# Quote
|
||||
elif line.startswith(">"):
|
||||
lines.extend(
|
||||
[
|
||||
"\t\t<blockquote>",
|
||||
"\t\t\t<p>" + line[1:].strip() + "</p>",
|
||||
"\t\t</blockquote>",
|
||||
]
|
||||
)
|
||||
# Normal text
|
||||
else:
|
||||
lines.append("\t\t<p>" + html.escape(line.strip()) + "</p>")
|
||||
url_html = html_href(url, html.escape(url))
|
||||
original_url_html = html_href(original_url, html.escape(original_url))
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
"\t</article>",
|
||||
"\t<details>",
|
||||
"\t\t<summary>",
|
||||
"\t\t\tContent from " + url_html,
|
||||
"\t\t</summary>",
|
||||
"\t\t<dl>",
|
||||
"\t\t\t<dt>Original URL</dt>",
|
||||
"\t\t\t<dd>" + original_url_html + "</dd>",
|
||||
"\t\t\t<dt>Status</dt>",
|
||||
"\t\t\t<dd>" + status + "</dd>",
|
||||
"\t\t\t<dt>Meta</dt>",
|
||||
"\t\t\t<dd>" + meta + "</dd>",
|
||||
"\t\t\t<dt>Fetched by</dt>",
|
||||
'\t\t\t<dd><a href="https://git.sr.ht/~sotirisp/qute-gemini">qute-gemini '
|
||||
+ str(_version)
|
||||
+ "</a></dd>",
|
||||
"\t\t</dl>",
|
||||
"\t</details>",
|
||||
"\t</body>",
|
||||
"</html>",
|
||||
]
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def get_css() -> str:
|
||||
# Search for qute-gemini.css in the directory this script is located in
|
||||
css_file = qute_gemini_css_path()
|
||||
if os.path.isfile(css_file):
|
||||
# Return the file contents
|
||||
with open(css_file, "r") as f:
|
||||
return f.read().strip()
|
||||
else:
|
||||
# Use no CSS
|
||||
return ""
|
||||
|
||||
|
||||
def qute_error_page(url: str, description: str) -> str:
|
||||
"""Return a data URI error page like qutebrowser does.
|
||||
|
||||
url: The URL of the page that failed to load.
|
||||
description: A description of the error.
|
||||
Returns a data URI containing the error page.
|
||||
"""
|
||||
# Generate the HTML error page
|
||||
html_page = _error_page_template.replace("URL", url)
|
||||
html_page = html_page.replace("URL_TEXT", html.escape(url))
|
||||
html_page = html_page.replace("DESCRIPTION", html.escape(description))
|
||||
html_page = html_page.replace("CSS", get_css())
|
||||
# URL encode and return as a data URI
|
||||
return "data:text/html;charset=UTF-8," + urllib.parse.quote(html_page)
|
||||
|
||||
|
||||
def open_gemini(url: str) -> str:
|
||||
"""Open Gemini URL in qutebrowser."""
|
||||
# Get the Gemini content
|
||||
content, content_url, status, meta, error_msg = gemini_fetch_url(url)
|
||||
if error_msg:
|
||||
# Generate an error page in a data URI
|
||||
open_url = qute_error_page(url, error_msg)
|
||||
else:
|
||||
# Success, convert to HTML in a temporary file
|
||||
tmpf = tempfile.NamedTemporaryFile("w", suffix=".html", delete=False)
|
||||
tmp_filename = tmpf.name
|
||||
tmpf.close()
|
||||
if not tmp_filename:
|
||||
return ""
|
||||
with open(tmp_filename, "w") as f:
|
||||
f.write(gemtext_to_html(content, content_url, url, status, meta))
|
||||
open_url = " file://" + tmp_filename
|
||||
# Open the HTML file in qutebrowser
|
||||
return open_url
|
||||
|
||||
|
||||
def open_url(url: str, open_args: str) -> None:
|
||||
parsed_url = urllib.parse.urlparse(url)
|
||||
if parsed_url.scheme == "gemini":
|
||||
to_open = open_gemini(url)
|
||||
else:
|
||||
to_open = url
|
||||
if not to_open:
|
||||
return
|
||||
|
||||
fifo = qute_fifo()
|
||||
if fifo and fifo != "":
|
||||
with open(fifo, "w") as qfifo:
|
||||
qfifo.write(f"open {open_args} {to_open}")
|
||||
return
|
||||
os.system(f"xdg-open {to_open}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Open in the current or a new tab depending on the script name
|
||||
if sys.argv[0].endswith("-tab"):
|
||||
open_args = "-b -r"
|
||||
else:
|
||||
open_args = ""
|
||||
|
||||
# Take url to open as argument or from qutebrowser url
|
||||
if len(sys.argv) > 1:
|
||||
url = sys.argv[1]
|
||||
else:
|
||||
url = qute_url()
|
||||
# Select how to open the URL depending on its scheme
|
||||
open_url(url, open_args)
|
||||
1
qutebrowser/data/userscripts/qute-gemini-tab
Symbolic link
1
qutebrowser/data/userscripts/qute-gemini-tab
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
qute-gemini
|
||||
1
qutebrowser/data/userscripts/qutedmenu
Symbolic link
1
qutebrowser/data/userscripts/qutedmenu
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../scripts/qutedmenu
|
||||
1
qutebrowser/data/userscripts/recently-downloaded
Symbolic link
1
qutebrowser/data/userscripts/recently-downloaded
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../scripts/recently-downloaded
|
||||
27
qutebrowser/data/userscripts/shaarli_add.sh
Executable file
27
qutebrowser/data/userscripts/shaarli_add.sh
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
#! /usr/bin/env bash
|
||||
#
|
||||
# Send current page/link to a shaarli instance.
|
||||
#
|
||||
# Can be used for sending the current page via:
|
||||
# :spawn --userscript shaarli_add.sh
|
||||
# for sending an arbitrary page passed as argument:
|
||||
# :spawn --userscript shaarli_add.sh https://myinterestingpage.com
|
||||
# or for sending a hinted link:
|
||||
# :hint links userscript shaarli_add.sh
|
||||
#
|
||||
# Configure your shaarli instance with this:
|
||||
SHAARLI_INSTANCE="https://links.martyoeh.me"
|
||||
|
||||
# send page to shaarli instance and open the 'post' page to edit it
|
||||
if [ "$#" -gt 0 ]; then
|
||||
BM="$SHAARLI_INSTANCE/?post=$*"
|
||||
else
|
||||
BM="$SHAARLI_INSTANCE/?post=$QUTE_URL"
|
||||
fi
|
||||
|
||||
if [ -n "$QUTE_FIFO" ]; then
|
||||
echo "open -t -r $BM" >>"$QUTE_FIFO"
|
||||
else
|
||||
xdg-open "$BM"
|
||||
fi
|
||||
|
||||
51
qutebrowser/data/userscripts/translate_google.sh
Executable file
51
qutebrowser/data/userscripts/translate_google.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env sh
|
||||
#
|
||||
# Translate the page, or if `--text` argument is given the current selection, with google translate.
|
||||
#
|
||||
# Adapted code from https://github.com/AckslD/Qute-Translate, with much gratitude.
|
||||
PAGE="https://lingva.garudalinux.org/SOURCELANGUAGE/TARGETLANGUAGE/TRANSLATETEXT"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-s | --source)
|
||||
QUTE_TRANS_SOURCE=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
-t | --target)
|
||||
QUTE_TRANS_TARGET=$2
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--url)
|
||||
QUTE_TRANS_URL="true"
|
||||
shift
|
||||
;;
|
||||
--text)
|
||||
QUTE_TRANS_URL="false"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$QUTE_TRANS_SOURCE" ]; then
|
||||
# Default use automatic language for source
|
||||
QUTE_TRANS_SOURCE="auto"
|
||||
fi
|
||||
if [ -z "$QUTE_TRANS_TARGET" ]; then
|
||||
# Default use English for target
|
||||
QUTE_TRANS_TARGET="en"
|
||||
fi
|
||||
|
||||
if [ "$QUTE_TRANS_URL" = "false" ]; then
|
||||
# Translate selected text
|
||||
PAGE=$(echo "$PAGE" | sed -e "s/SOURCELANGUAGE/$QUTE_TRANS_SOURCE/" -e "s/TARGETLANGUAGE/$QUTE_TRANS_TARGET/" -e "s/TRANSLATETEXT/$QUTE_SELECTED_TEXT/")
|
||||
echo "open -t ${PAGE}" >>"$QUTE_FIFO"
|
||||
else
|
||||
# Default translate URL
|
||||
PAGE="https://translate.google.com/translate?"
|
||||
CONT_KEY="u"
|
||||
CONTENT="$QUTE_URL"
|
||||
echo "open -t ${PAGE}sl=${QUTE_TRANS_SOURCE}&tl=${QUTE_TRANS_TARGET}&${CONT_KEY}=\"${CONTENT}\"" >>"$QUTE_FIFO"
|
||||
fi
|
||||
|
||||
26
qutebrowser/data/userscripts/wallabag_add.sh
Executable file
26
qutebrowser/data/userscripts/wallabag_add.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#! /usr/bin/env bash
|
||||
#
|
||||
# Send current page/link to a wallabag instance.
|
||||
#
|
||||
# Can be used for sending the current page via:
|
||||
# :spawn --userscript wallabag_add.sh
|
||||
# for sending an arbitrary page passed as argument:
|
||||
# :spawn --userscript wallabag_add.sh https://myinterestingtext.com
|
||||
# or for sending a hinted link:
|
||||
# :hint links userscript wallabag_add.sh
|
||||
#
|
||||
# Configure your wallabag instance with this:
|
||||
WALLABAG_INSTANCE="https://read.martyoeh.me"
|
||||
|
||||
# only works for wallabag v2.*
|
||||
if [ "$#" -gt 0 ]; then
|
||||
BM="$WALLABAG_INSTANCE/bookmarklet?url=$*"
|
||||
else
|
||||
BM="$WALLABAG_INSTANCE/bookmarklet?url=$QUTE_URL"
|
||||
fi
|
||||
|
||||
if [ -n "$QUTE_FIFO" ]; then
|
||||
echo "open -b -r $BM" >>"$QUTE_FIFO"
|
||||
else
|
||||
xdg-open "$BM"
|
||||
fi
|
||||
Loading…
Add table
Add a link
Reference in a new issue