2019-10-02 16:31:34 +02:00
|
|
|
(in-package :next-user)
|
2018-12-02 20:32:28 +01:00
|
|
|
|
2018-12-10 12:53:58 +01:00
|
|
|
;; Use development platform port.
|
2020-02-22 15:39:48 +01:00
|
|
|
(when (boundp '+platform-port-command+)
|
|
|
|
(setf +platform-port-command+
|
|
|
|
"~/common-lisp/next/ports/gtk-webkit/next-gtk-webkit"))
|
2018-12-10 12:53:58 +01:00
|
|
|
|
2019-10-02 16:31:34 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defun eval-in-emacs (&rest s-exps)
|
|
|
|
"Evaluate S-exps with `emacsclient'."
|
2019-12-09 15:35:57 +01:00
|
|
|
(let ((s-exps-string (cl-ppcre:regex-replace-all
|
2019-10-02 16:31:34 +02:00
|
|
|
;; Discard the package prefix.
|
2019-12-09 15:35:57 +01:00
|
|
|
"next-user::?"
|
2019-10-02 16:31:34 +02:00
|
|
|
(write-to-string
|
2019-12-09 15:35:57 +01:00
|
|
|
`(progn ,@s-exps) :case :downcase)
|
|
|
|
"")))
|
|
|
|
(log:debug "Sending to Emacs: ~s" s-exps-string)
|
2019-10-02 16:31:34 +02:00
|
|
|
(ignore-errors (uiop:run-program
|
|
|
|
(list "emacsclient" "--eval" s-exps-string)))))
|
|
|
|
|
|
|
|
(defvar *my-keymap* (make-keymap)
|
|
|
|
"Keymap for `my-mode'.")
|
|
|
|
|
|
|
|
(define-command org-capture (&optional (buffer (current-buffer)))
|
|
|
|
"Org-capture current page."
|
|
|
|
(eval-in-emacs
|
|
|
|
`(org-link-set-parameters
|
|
|
|
"next"
|
|
|
|
:store (lambda ()
|
|
|
|
(org-store-link-props
|
|
|
|
:type "next"
|
|
|
|
:link ,(url buffer)
|
|
|
|
:description ,(title buffer))))
|
|
|
|
`(org-capture)))
|
|
|
|
(define-key :keymap *my-keymap* "C-M-o" #'org-capture)
|
|
|
|
|
|
|
|
(define-command youtube-dl-current-page (&optional (buffer (current-buffer)))
|
|
|
|
"Download a video in the currently open buffer."
|
|
|
|
(eval-in-emacs
|
|
|
|
(if (search "youtu" (url buffer))
|
|
|
|
`(progn (youtube-dl ,(url buffer)) (youtube-dl-list))
|
|
|
|
`(ambrevar/youtube-dl-url ,(url buffer)))))
|
|
|
|
(define-key :keymap *my-keymap* "C-M-c d" 'youtube-dl-current-page)
|
|
|
|
|
|
|
|
(define-command play-video-in-current-page (&optional (buffer (current-buffer)))
|
|
|
|
"Play video in the currently open buffer."
|
|
|
|
(uiop:run-program (list "mpv" (url buffer))))
|
|
|
|
(define-key :keymap *my-keymap* "C-M-c v" #'play-video-in-current-page)
|
|
|
|
|
|
|
|
(define-mode my-mode ()
|
|
|
|
"Dummy mode for the custom key bindings in `*my-keymap*'."
|
|
|
|
((keymap-schemes :initform (list :emacs-map *my-keymap*
|
|
|
|
:vi-normal *my-keymap*))))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2019-09-24 17:28:09 +02:00
|
|
|
(defvar +youtube-dl-command+ "youtube-dl"
|
|
|
|
"Path to the 'youtube-dl' program.")
|
|
|
|
|
|
|
|
(defun auto-yt-dl-handler (url)
|
|
|
|
"Download a Youtube URL asynchronously to /tmp/videos/.
|
|
|
|
Videos are downloaded with `+youtube-dl-command+'."
|
|
|
|
(let ((uri (quri:uri url)))
|
|
|
|
(when (and uri
|
|
|
|
(member-string (quri:uri-domain uri) '("youtube.com" "youtu.be"))
|
|
|
|
(string= (quri:uri-path uri) "/watch"))
|
|
|
|
(log:info "Youtube: downloading ~a" url)
|
|
|
|
(uiop:launch-program (list +youtube-dl-command+ url "-o" "/tmp/videos/%(title)s.%(ext)s"))))
|
|
|
|
url)
|
|
|
|
|
|
|
|
(defun old-reddit-handler (url)
|
2019-09-10 17:15:03 +02:00
|
|
|
(let* ((uri (quri:uri url)))
|
2020-03-14 16:35:43 +01:00
|
|
|
(if (search "reddit.com" (quri:uri-host uri))
|
2019-09-10 17:15:03 +02:00
|
|
|
(progn
|
|
|
|
(setf (quri:uri-host uri) "old.reddit.com")
|
|
|
|
(let ((new-url (quri:render-uri uri)))
|
|
|
|
(log:info "Switching to old Reddit: ~a" new-url)
|
|
|
|
new-url))
|
|
|
|
url)))
|
2019-09-24 17:28:09 +02:00
|
|
|
|
|
|
|
(defvar *my-unproxied-domains*
|
|
|
|
'("jit.si"
|
2019-10-03 15:55:42 +02:00
|
|
|
"steampowered.com"))
|
2019-09-24 17:28:09 +02:00
|
|
|
|
|
|
|
(defun auto-proxy-handler (url)
|
|
|
|
(let* ((uri (quri:uri url))
|
|
|
|
(domain (and uri (quri:uri-domain uri))))
|
2019-11-17 14:01:06 +01:00
|
|
|
;; TODO: Turn on/off proxy, not mode.
|
2019-09-24 17:28:09 +02:00
|
|
|
(when domain
|
|
|
|
(next/proxy-mode:proxy-mode
|
|
|
|
:activate
|
|
|
|
(not (member-string domain *my-unproxied-domains*)))))
|
|
|
|
url)
|
|
|
|
|
2019-10-02 16:31:34 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(defvar *my-blocked-hosts*
|
|
|
|
(next/blocker-mode:make-hostlist
|
|
|
|
:hosts '("platform.twitter.com"
|
|
|
|
"syndication.twitter.com"
|
|
|
|
"m.media-amazon.com")))
|
|
|
|
|
2019-10-03 15:55:32 +02:00
|
|
|
(defun no-cookies-handler (buffer)
|
2019-11-17 14:01:06 +01:00
|
|
|
;; TODO: Disable cookies for known hosts.
|
2019-10-03 15:55:32 +02:00
|
|
|
(setf (cookies-path buffer) #P""))
|
2019-10-02 16:31:34 +02:00
|
|
|
|
2019-11-17 14:01:06 +01:00
|
|
|
(define-mode my-blocker-mode (next/blocker-mode:blocker-mode)
|
|
|
|
"Blocker mode with custom hosts from `*my-blocked-hosts*'."
|
|
|
|
((next/blocker-mode::hostlists :initform (list *my-blocked-hosts* next/blocker-mode:*default-host-list*))))
|
2019-10-02 16:31:34 +02:00
|
|
|
|
2020-02-25 15:51:05 +01:00
|
|
|
(if (find-class 'gtk-buffer nil)
|
|
|
|
(defclass my-buffer (gtk-buffer)
|
|
|
|
((default-modes :initform (append
|
|
|
|
'(my-mode vi-normal-mode
|
|
|
|
my-blocker-mode
|
|
|
|
proxy-mode)
|
|
|
|
(get-default 'buffer 'default-modes)))
|
|
|
|
(load-hook :initform (next-hooks:make-hook-string->string
|
|
|
|
:handlers (list #'old-reddit-handler
|
|
|
|
#'auto-proxy-handler)
|
|
|
|
:combination #'next-hooks:combine-composed-hook))))
|
|
|
|
(defclass my-buffer (buffer)
|
|
|
|
((default-modes :initform (append
|
|
|
|
'(my-mode vi-normal-mode
|
|
|
|
my-blocker-mode
|
|
|
|
proxy-mode)
|
|
|
|
(get-default 'buffer 'default-modes)))
|
|
|
|
(load-hook :initform (next-hooks:make-hook-string->string
|
|
|
|
:handlers (list #'old-reddit-handler
|
|
|
|
#'auto-proxy-handler)
|
|
|
|
:combination #'next-hooks:combine-composed-hook)))))
|
2019-10-02 16:31:34 +02:00
|
|
|
|
2019-11-17 14:01:06 +01:00
|
|
|
(setf *buffer-class* 'my-buffer)
|
2019-10-02 16:31:34 +02:00
|
|
|
|
2020-02-22 15:39:48 +01:00
|
|
|
(defvar my-search-engines
|
|
|
|
'(("aa" . "https://aur.archlinux.org/packages.php?O=0&K=~a&do_Search=Go")
|
|
|
|
("ap" . "https://www.archlinux.org/packages/?sort=&q=~a&maintainer=&flagged=")
|
|
|
|
("aw" . "https://wiki.archlinux.org/index.php?search=~a")
|
|
|
|
("ctan" . "http://www.ctan.org/search?phrase=~a")
|
|
|
|
("dd" . "http://devdocs.io/#q=~a")
|
|
|
|
("dg" . "https://duckduckgo.com/?q=~a")
|
|
|
|
("eb" . "https://debbugs.gnu.org/cgi/pkgreport.cgi?package=emacs;include=subject%3A~a;repeatmerged=on;archive=both")
|
|
|
|
("ed" . "https://lists.gnu.org/archive/cgi-bin/namazu.cgi?idxname=emacs-devel&submit=Search&query=~a")
|
|
|
|
("ee" . "https://lists.gnu.org/archive/cgi-bin/namazu.cgi?idxname=emms-help&submit=Search!&query=~a")
|
|
|
|
("ge" . "https://wiki.gentoo.org/index.php?title=Special%3ASearch&search=~a&go=Go")
|
|
|
|
("gh" . "https://github.com/search?ref=simplesearch&q=~a")
|
|
|
|
("gr" . "https://www.goodreads.com/search?q=~a")
|
|
|
|
("gm" . "https://maps.google.com/maps?q=~a")
|
|
|
|
("gud" . "https://lists.gnu.org/archive/cgi-bin/namazu.cgi?idxname=guix-devel&submit=Search&query=~a")
|
|
|
|
("guh" . "https://lists.gnu.org/archive/cgi-bin/namazu.cgi?idxname=help-guix&submit=Search!&query=~a")
|
|
|
|
("gup" . "https://guix-hpc.bordeaux.inria.fr/package/~a")
|
|
|
|
("i" . "http://www.imdb.com/find?q=~a&s=all")
|
|
|
|
("mba" . "http://musicbrainz.org/search?query=~a&type=artist&method=indexed")
|
|
|
|
("mbr" . "http://musicbrainz.org/search?query=~a&type=release&method=indexed")
|
|
|
|
("osm" . "https://www.openstreetmap.org/search?query=~a")
|
|
|
|
("q" . "http://quickdocs.org/search?q=~a")
|
|
|
|
("s" . "http://stackoverflow.com/search?q=~a")
|
|
|
|
("wp" . "http://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=~a")
|
|
|
|
("wb" . "http://en.wikibooks.org/wiki/Special:Search?search=~a")
|
|
|
|
("wk" . "http://en.wiktionary.org/wiki/Special:Search?search=~a")
|
|
|
|
("wa" . "http://www.winehq.org/search/?q=~a")
|
|
|
|
("yt" . "https://www.youtube.com/results?search_query=~a")))
|
|
|
|
|
|
|
|
(if (find-class 'remote-interface nil)
|
|
|
|
(defclass my-remote-interface (remote-interface)
|
|
|
|
;; TODO: Fetch from Emacs' engine.el automatically?
|
|
|
|
((search-engines :initform
|
|
|
|
(append
|
|
|
|
my-search-engines
|
|
|
|
(get-default 'remote-interface 'search-engines)))))
|
2020-03-06 08:18:41 +01:00
|
|
|
(defclass my-browser (gtk-browser)
|
2020-02-22 15:39:48 +01:00
|
|
|
;; TODO: Fetch from Emacs' engine.el automatically?
|
|
|
|
((search-engines :initform
|
|
|
|
(append
|
|
|
|
my-search-engines
|
2020-03-06 08:18:41 +01:00
|
|
|
(get-default 'browser 'search-engines))))))
|
2020-02-22 15:39:48 +01:00
|
|
|
|
|
|
|
(if (boundp '*remote-interface-class*)
|
|
|
|
(setf *remote-interface-class* 'my-remote-interface)
|
2020-03-06 08:18:41 +01:00
|
|
|
(setf *browser-class* 'my-browser))
|
2019-10-02 16:31:34 +02:00
|
|
|
|
|
|
|
(defmethod deserialize-bookmarks (stream)
|
|
|
|
"This version of deserialize-bookmarks is compatibly with Ambrevar's EWW
|
|
|
|
format."
|
|
|
|
(handler-case
|
|
|
|
(let ((*standard-input* stream))
|
|
|
|
(let ((entries (read stream)))
|
|
|
|
(mapcar (lambda (entry)
|
|
|
|
(when (getf entry :date)
|
|
|
|
(setf (getf entry :date)
|
|
|
|
(local-time:parse-timestring (getf entry :date))))
|
|
|
|
(when (getf entry :time)
|
|
|
|
(let ((timestamp (asctime->timestamp (getf entry :time))))
|
|
|
|
(when timestamp
|
|
|
|
(setf (getf entry :date) timestamp)))
|
|
|
|
(remf entry :time))
|
|
|
|
(when (getf entry :search)
|
|
|
|
(setf (getf entry :search-url) (getf entry :search))
|
|
|
|
(remf entry :search))
|
|
|
|
(when (getf entry :mark)
|
|
|
|
(setf (getf entry :shortcut) (getf entry :mark))
|
|
|
|
(remf entry :mark))
|
|
|
|
(apply #'make-instance 'bookmark-entry
|
|
|
|
entry))
|
|
|
|
entries)))
|
|
|
|
(error (c)
|
|
|
|
(log:error "Error during bookmark deserialization: ~a" c)
|
|
|
|
nil)))
|
2020-02-22 15:39:48 +01:00
|
|
|
|
|
|
|
(setf next/vcs:*vcs-projects-roots* '("~/projects"
|
|
|
|
"~/common-lisp"
|
|
|
|
"~/.local/share/emacs/site-lisp"))
|