;;; eev-brxxx.el -- define families of browse-url-like functions.
;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
;;
;; This file is part of GNU eev.
;;
;; GNU eev 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.
;;
;; GNU eev 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 GNU Emacs. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 20210208
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;;
;; (find-eev-intro)
;; (find-psne-intro)
;; (find-brxxx-intro)
;;; Commentary:
;; The section
;;
;; (find-eev-quick-intro "3.1. Non-elisp hyperlinks")
;;
;; of the main tutorial mentions the functions `brff' and `brg', that
;; are eev-ish variants of `browse-url'. They are explained in more
;; details here:
;;
;; (find-brxxx-intro)
;;
;; These `brxxx's are "mass-produced" by the functions `code-brurl'
;; and `code-brfile', that work similarly to `code-c-d'. Try these
;; tests to see the code that they generate:
;;
;; (find-code-brfile 'find-FOO :local 'brFOOL :dired 'brFOOD)
;; (find-code-brurl 'find-QUX :remote 'brQUX :local 'brQUXL :dired 'brQUXD)
;;
;; The first argument of `code-brurl' and `find-code-brurl' is the
;; name of a function that expects a URL; the first argument of
;; `code-brfile' and `find-code-brfile' is the name of a function that
;; expects a filename. The other arguments are pairs made of a keyword
;; and a name of a function to define.
;;
;; Here is a simple test. Let's define `find-FOO' as function that
;; expects a filename and displays it in the right window, and
;; `find-QUX' as a function that expects a URL and displays it in the
;; right window:
;;
;; (defun find-FOO (url) (find-2a nil '(find-estring url)))
;; (defun find-QUX (fname) (find-2a nil '(find-estring fname)))
;; (find-FOO "/tmp/a-filename")
;; (find-QUX "http://some/url")
;;
;; Now let's define the `brFOO*' and `brQUX*' functions:
;;
;; (find-code-brfile 'find-FOO :local 'brFOOL :dired 'brFOOD)
;; (code-brfile 'find-FOO :local 'brFOOL :dired 'brFOOD)
;; (find-code-brurl 'find-QUX :remote 'brQUX :local 'brQUXL :dired 'brQUXD)
;; (code-brurl 'find-QUX :remote 'brQUX :local 'brQUXL :dired 'brQUXD)
;;
;; The function `brQUX', that was defined with `:remote', acts like
;; `browse-url', but using `find-QUX' as its "browser": it calls
;; `find-QUX' on a "remote" URL.
;;
;; The functions `brFOOL' and `brQUXL', that were defined with
;; `:local', act on a "local copy" of the URL, in the sense of:
;;
;; (find-psne-intro "1. Local copies of files from the internet")
;;
;; You can try them either by typing `M-x brFOOL' and `M-x brQUXL' on
;; the URLs below or by running the sexps with `M-e'. Their action is
;; to show on the right window the argument that was passed to
;; `find-FOO' and `find-QUX':
;;
;; (brFOOL "http://some/url")
;; (brQUXL "http://some/url")
;;
;; that are that URL converted to a local file name in the first case,
;; and that URL converted to a "file:///" URL corresponding that local
;; file name in the second case. More precisely, what happens is:
;;
;; (brFOOL "http://some/url")
;; --> (find-FOO (ee-url-to-fname "http://some/url"))
;; --> (find-FOO (ee-expand "$S/http/some/url"))
;;
;; (brQUXL "http://some/url")
;; --> (find-QUX (ee-url-to-local-url "http://some/url"))
;; --> (find-QUX (concat "file://" (ee-expand "$S/http/some/url")))
;;
;; The functions `brFOOD' and `brQUXD' are intended to be called
;; interactively from dired mode. If you call them on a dired buffer
;; showing "/tmp/" and with the point on the line that shows a file
;; called "a-filename" their actions would be the same as the sexps
;; below:
;;
;; (brFOOL "/tmp/a-filename")
;; --> (find-FOO "/tmp/a-filename")
;;
;; (brQUXL "/tmp/a-filename")
;; --> (find-QUX (ee-fname-to-url "/tmp/a-filename"))
;; --> (find-QUX (concat "file://" "/tmp/a-filename"))
;;
;; This file, i.e.: (find-eev "eev-brxxx.el")
;; supersedes: (find-eev "eev-browse-url.el")
;; but eev-browse-url.el still has some nice comments that I would
;; like to bring here.
;; «.code-brurl» (to "code-brurl")
;; «.ee-code-brurl-rest» (to "ee-code-brurl-rest")
;; «.code-brfile» (to "code-brfile")
;; «.ee-code-brfile-rest» (to "ee-code-brfile-rest")
;; «.code-brxxxs» (to "code-brxxxs")
(require 'eev-code) ; (find-eev "eev-code.el")
(autoload 'browse-url-interactive-arg "browse-url")
;;; _
;;; ___ ___ _ ____ _____ _ __ ___(_) ___ _ __ ___
;;; / __/ _ \| '_ \ \ / / _ \ '__/ __| |/ _ \| '_ \/ __|
;;; | (_| (_) | | | \ V / __/ | \__ \ | (_) | | | \__ \
;;; \___\___/|_| |_|\_/ \___|_| |___/_|\___/|_| |_|___/
;;;
;; Here we define some conversion functions that are used by
;; `code-brurl' and `code-brfile'.
;;
;; The `brxxx' functions call the conversion functions defined below,
;; that convert between four kinds of strings: "dired", "url",
;; "fname", and "local-url". The table below explains which function
;; does what; note that "<$S>" means the expansion of "$S", and that
;; if the point is on the file name "b" in a dired buffer visiting the
;; directory "/foo/bar" then `(ee-dired-to-fname)' returns
;; "/foo/bar/b", not something that starts with "$S".
;;
;; dired url fname local-url
;; "b" "/foo/bar/b" "file:///foo/bar/b"
;; "http://a/b" "$S/http/a/b" "file:///<$S>/http/a/b"
;; ==========================================================
;; * (code-brurl _ :remote _)
;; * |-----------------------------> * (code-brurl _ :local _)
;; * |--------------------------------------> * (code-brurl _ :dired _)
;;
;; * |----------> * (code-brfile _ :local _)
;; * |-------------------> * (code-brfile _ :dired _)
;;
;; * |----------> * ee-url-to-fname
;; * |--------------> * ee-fname-to-url
;; * |-----------------------------> * ee-url-to-local-url
;; * |-------------------> * ee-dired-to-fname
;; * |--------------------------------------> * ee-dired-to-url
(defun ee-url-to-fname0 (url)
"Convert an url like http://foo/bar to a filename like $S/http/foo/bar."
(replace-regexp-in-string "^\\(https?\\|ftp\\)://" "$S/\\1/" url))
(defun ee-url-to-fname (url)
"Convert an url like http://foo/bar to a filename like <$S>/http/foo/bar.
\(The \"<$S>\" above means the expansion of \"$S\"; see `ee-expand')."
(ee-expand (ee-url-to-fname0 url)))
(defun ee-fname-to-url (fname)
"Convert a filename to a \"file://\" url (after running `ee-expand' on it)."
(concat "file://" (expand-file-name (ee-expand fname))))
(defun ee-url-to-local-url (url)
"Convert a url like http://foo/bar to a url like file://<$S>/http/foo/bar.
This should be made smarter - file:// urls should be returned unchanged."
;; Add comments about psne and the snarf directory
(ee-fname-to-url (ee-url-to-fname url)))
(defun ee-dired-to-fname (&optional no-error-if-not-filep)
"Convert the file name at point (in dired mode) to an absolute file name."
(if (eq major-mode 'dired-mode)
(file-name-sans-versions (dired-get-filename nil no-error-if-not-filep) t)
(error "Not in dired mode")))
(defun ee-dired-to-url (&optional no-error-if-not-filep)
"Convert the file name at point (in dired mode) to a url like file://<$S>/___."
(ee-fname-to-url (ee-dired-to-fname no-error-if-not-filep)))
;; An internal function used by `ee-code-brurl-rest' and
;; `ee-code-brfile-rest'. Similar to:
;; (find-eev "eev-code.el" "ee-tail-call2")
(defun ee-tail-call1 (fmt f rest)
"An internal function used to support keyword-argument pairs."
(cond ((null rest) "")
((keywordp (car rest))
(apply (intern (format fmt (car rest)))
f (cdr rest)))
(t (error "Wrong rest: %S" rest))))
;;; _ _ _
;;; ___ ___ __| | ___ | |__ _ __ _ _ _ __| |
;;; / __/ _ \ / _` |/ _ \_____| '_ \| '__| | | | '__| |
;;; | (_| (_) | (_| | __/_____| |_) | | | |_| | | | |
;;; \___\___/ \__,_|\___| |_.__/|_| \__,_|_| |_|
;;;
;; «code-brurl» (to ".code-brurl")
;; See: (find-brxxx-intro "6. `code-brfile'")
;; Test: (find-code-brurl 'find-foo :remote 'brfoo :local 'brfool :dired 'brfood)
;;
(defun code-brurl (f &rest rest)
"Define a family of brxxx functions from a function that operates on URLs"
(eval (ee-read (apply 'ee-code-brurl f rest))))
(defun find-code-brurl (f &rest rest)
(find-estring-elisp (apply 'ee-code-brurl f rest)))
(defun ee-code-brurl (f &rest rest)
"Generate code for a family of functions from a function that operates on URLs"
(concat (ee-template0 "\
;; {(ee-S `(find-code-brurl ',f ,@(mapcar 'ee-add-quote rest)))}
;; See: (find-brxxx-intro \"5. `code-brurl'\")
") (ee-code-brurl-rest f rest)))
;; «ee-code-brurl-rest» (to ".ee-code-brurl-rest")
;; Support for extra arguments. Similar to:
;; (find-eev-quick-intro "9.2. Extra arguments to `code-c-d'")
(defun ee-code-brurl-rest (f rest)
(cond ((null rest) "")
((keywordp (car rest))
(apply (intern (format "ee-code-brurl-%S" (car rest)))
f (cdr rest)))
(t (error "Wrong rest: %S" rest))))
(defun ee-code-brurl-:remote (f brxxx &rest rest)
(concat (ee-template0 "
\(defun {brxxx} (url &rest ignore)
\"Apply `{f}' on URL.\"
(interactive (browse-url-interactive-arg \"URL: \"))
;; (setq browse-url-browser-function '{brxxx})
(message \"(%S %S) -> %S\" '{f} url
({f} url)))
") (ee-code-brurl-rest f rest)))
(defun ee-code-brurl-:local (f brxxxl &rest rest)
(concat (ee-template0 "
\(defun {brxxxl} (url &rest ignore)
\"Apply `{f}' on the local url associated to URL.\"
(interactive (browse-url-interactive-arg \"URL: \"))
;; (setq browse-url-browser-function '{brxxxl})
(setq url (ee-url-to-local-url url))
(message \"(%S %S) -> %S\" '{f} url
({f} url)))
") (ee-code-brurl-rest f rest)))
(defun ee-code-brurl-:dired (f brxxxd &rest rest)
(concat (ee-template0 "
\(defun {brxxxd} (&rest ignore)
\"Apply `{f}' on the url of the dired file at point.\"
(interactive)
(let ((url (ee-dired-to-url)))
(message \"(%S %S) -> %S\" '{f} url
({f} url))))
") (ee-code-brurl-rest f rest)))
;; Test:
;; (find-code-brurl 'pluc :remote 'brpluc :local 'brplucl :dired 'brplucd)
;; (code-brurl 'pluc :remote 'brpluc :local 'brplucl :dired 'brplucd)
;;
;; (find-efunction 'find-brxxx-intro)
;; (find-brxxx-intro "M-x brpluc")
;;; _ _ __ _ _
;;; ___ ___ __| | ___ | |__ _ __ / _(_) | ___
;;; / __/ _ \ / _` |/ _ \_____| '_ \| '__| |_| | |/ _ \
;;; | (_| (_) | (_| | __/_____| |_) | | | _| | | __/
;;; \___\___/ \__,_|\___| |_.__/|_| |_| |_|_|\___|
;;;
;; «code-brfile» (to ".code-brfile")
;; `code-brfile': top-level functions.
;; Test: (find-code-brfile 'find-BAR :local 'brBARL :dired 'brBARD)
;; See: (find-brxxx-intro "6. `code-brfile'")
;;
(defun code-brfile (f &rest rest)
"Define a family of brxxx functions from a function that operates on files"
(eval (ee-read (apply 'ee-code-brfile f rest))))
(defun find-code-brfile (f &rest rest)
(find-estring-elisp (apply 'ee-code-brfile f rest)))
(defun ee-code-brfile (f &rest rest)
"Generate code for a family of functions from a function that operates on files"
(concat (ee-template0 "\
;; {(ee-S `(find-code-brfile ',f ,@(mapcar 'ee-add-quote rest)))}
;; See: (find-brxxx-intro \"6. `code-brfile'\")
") (ee-code-brfile-rest f rest)))
;; «ee-code-brfile-rest» (to ".ee-code-brfile-rest")
;; `code-brfile': support for extra arguments.
;;
;; Similar to:
;; (find-eev-quick-intro "9.2. Extra arguments to `code-c-d'")
(defun ee-code-brfile-rest (f rest)
(cond ((null rest) "")
((keywordp (car rest))
(apply (intern (format "ee-code-brfile-%S" (car rest)))
f (cdr rest)))
(t (error "Wrong rest: %S" rest))))
(defun ee-code-brfile-:local (f brxxxl &rest rest)
(concat (ee-template0 "
\(defun {brxxxl} (url &rest ignore)
\"Apply `{f}' on the local file name associated to URL.\"
(interactive (browse-url-interactive-arg \"URL: \"))
;; (setq browse-url-browser-function '{brxxxl})
(let ((fname (ee-url-to-fname url)))
(message \"(%S %S) -> %S\" '{f} fname
({f} fname))))
") (ee-code-brfile-rest f rest)))
(defun ee-code-brfile-:dired (f brxxxd &rest rest)
(concat (ee-template0 "
\(defun {brxxxd} (&rest ignore)
\"Apply `{f}' on the dired file at point.\"
(interactive)
(let ((fname (ee-dired-to-fname)))
(message \"(%S %S) -> %S\" '{f} fname
({f} fname))))
") (ee-code-brfile-rest f rest)))
;;; _ _
;;; ___ ___ __| | ___ | |__ _ ____ ____ ____ _____
;;; / __/ _ \ / _` |/ _ \_____| '_ \| '__\ \/ /\ \/ /\ \/ / __|
;;; | (_| (_) | (_| | __/_____| |_) | | > < > < > <\__ \
;;; \___\___/ \__,_|\___| |_.__/|_| /_/\_\/_/\_\/_/\_\___/
;;;
;; «code-brxxxs» (to ".code-brxxxs")
;; See: (find-eev-quick-intro "3.1. Non-elisp hyperlinks")
;; (find-eev-quick-intro "3.1. Non-elisp hyperlinks" "brg")
;; (find-eev "eev-pdflike.el" "code-brxxxs")
;; (find-eev "eev-audiovideo.el" "code-brxxxs")
;; (find-eev "eev-blinks.el" "find-w3m")
;; (find-efile "net/browse-url.el")
(defun find-googlechrome (url) (find-bgprocess `("google-chrome" ,url)))
(defun find-firefox (url) (find-bgprocess `("firefox" ,url)))
;; (find-code-brurl 'find-psne-links :remote 'brep)
(code-brurl 'find-psne-links :remote 'brep)
;; (find-code-brurl 'find-firefox :remote 'brm :local 'brml :dired 'brmd)
(code-brurl 'find-firefox :remote 'brm :local 'brml :dired 'brmd)
;; (find-code-brurl 'find-firefox :remote 'brff :local 'brffl :dired 'brffd)
(code-brurl 'find-firefox :remote 'brff :local 'brffl :dired 'brffd)
;; (find-code-brurl 'find-googlechrome :remote 'brg :local 'brgl :dired 'brgd)
(code-brurl 'find-googlechrome :remote 'brg :local 'brgl :dired 'brgd)
;; (find-code-brurl 'find-w3m :remote 'brw :local 'brwl :dired 'brwd)
(code-brurl 'find-w3m :remote 'brw :local 'brwl :dired 'brwd)
;; (find-code-brurl 'find-eww :remote 'breww :local 'brewwl :dired 'brewwd)
(code-brurl 'find-eww :remote 'breww :local 'brewwl :dired 'brewwd)
;; (find-code-brurl 'find-eww :remote 'brew :local 'brewl :dired 'brewd)
(code-brurl 'find-eww :remote 'brew :local 'brewl :dired 'brewd)
;; (find-code-brurl 'find-wget :remote 'brwget)
(code-brurl 'find-wget :remote 'brwget)
;; (find-code-brfile 'find-fline :local 'brfl)
(code-brfile 'find-fline :local 'brfl)
;; Obsolete:
;; (code-brurl 'browse-url-firefox :remote 'brm :local 'brml :dired 'brmd)
;; (code-brurl 'browse-url-firefox :remote 'brff :local 'brffl :dired 'brffd)
;; These are defined elsewhere.
;; (code-brfile 'find-xpdf-page :local 'brxpdfl :dired 'brxpdfd)
;; (code-brfile 'find-evince-page :local 'brevincel :dired 'brevinced)
;; (code-brfile 'find-xdvi-page :local 'brxdvil :dired 'brxdvid)
;; (code-brfile 'find-pdf-text :local 'brpdftextl :dired 'brpdftextd)
;; (code-brfile 'find-djvu-text :local 'brdjvutextl :dired 'brdjvutextd)
;; See: (find-eev "eev-pdflike.el")
;; These too...
;; (code-brfile 'find-video :local 'brvideol :dired 'brvideod)
;; (code-brfile 'find-audio :local 'braudiol :dired 'braudiod)
;; See: (find-eev "eev-audiovideo.el")
;; Some obsolete definitions (with the old syntax):
;; (eeurl-define-from :fname->action: 'eecd :local: 'brcdl)
;; (eeurl-define-from :url->action: 'eepsne :remote: 'brp)
;; (eeurl-define-from :url->action: 'eetmpwget :remote: 'brtmpwget)
;; (find-eevgrep "grep -nH -e brg *.el")
(provide 'eev-brxxx)
;; Local Variables:
;; coding: utf-8-unix
;; no-byte-compile: t
;; End: