From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Mark Oteiza Newsgroups: gmane.emacs.devel Subject: Library for XDG things (was Re: [PATCH] checking eww download directory) Date: Sat, 28 Jan 2017 20:01:50 -0500 Message-ID: <20170129010150.GB16992@holos.localdomain> References: <87wpdgmi84.fsf@udel.edu> <66463069-a49f-1dc1-2399-a8e5c60af5ca@gmail.com> <87mvecntq1.fsf@udel.edu> <83r33nzkkx.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: blaine.gmane.org 1485651759 20465 195.159.176.226 (29 Jan 2017 01:02:39 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sun, 29 Jan 2017 01:02:39 +0000 (UTC) User-Agent: Mutt/1.7.2+27 (e4ad1dc9bfbd) (2016-11-26) Cc: cpitclaudel@gmail.com, emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Jan 29 02:02:33 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cXdsw-0004IJ-Po for ged-emacs-devel@m.gmane.org; Sun, 29 Jan 2017 02:02:27 +0100 Original-Received: from localhost ([::1]:53706 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cXdt1-0004he-VQ for ged-emacs-devel@m.gmane.org; Sat, 28 Jan 2017 20:02:31 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:45877) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cXdsT-0004hY-0S for emacs-devel@gnu.org; Sat, 28 Jan 2017 20:01:58 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cXdsP-0004qA-As for emacs-devel@gnu.org; Sat, 28 Jan 2017 20:01:57 -0500 Original-Received: from mail-qk0-x244.google.com ([2607:f8b0:400d:c09::244]:35200) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cXdsP-0004py-2s for emacs-devel@gnu.org; Sat, 28 Jan 2017 20:01:53 -0500 Original-Received: by mail-qk0-x244.google.com with SMTP id u25so14081443qki.2 for ; Sat, 28 Jan 2017 17:01:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=udel-edu.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=NsWQ12WHogmfHZ+vf2Abo5zJjw4J2whvrQI7PE6gMDQ=; b=q283FnDicaJJx1nHETn4zsPEQRlGaOsRwUsfQAgrCddr9G+2AbIv4nNIsmtP4Uq/0l EnGOFmQV8KyO6G+f5JUX6B+ZAYhRBTfyJ4G5mKwnVII5agCBBWrBDatqc72/HGlYQKRE KwPBlM+r0BTGNaFZc1ygs/mZLC5DWQ0zad/JIdiCxsB9+tu5zaOUo0b+FEiXrfNPW210 KeNO8jp9D+pD09cpkUfefUr9StWrq0O9yVtGNdinfsiL/SSguFOs96JHSK6zrWsU1QHj BWutdPN0SSMxSTELbt+dQvK0cLGo3T8M7U+ST3axJMdXV1GtCQhIRDT2qDe6FasFOGWl jBGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=NsWQ12WHogmfHZ+vf2Abo5zJjw4J2whvrQI7PE6gMDQ=; b=fYrDBHlJRf1DWeqTuJKTBaEqgdiz9RgcODdWW35QT5YvmSSp+eB8pHpyOtPMaXqPrJ Suw+UHeQ9SAr0FlHwQvIrnW3SFu9xAEnrN7OSgtvS5TB0NDfpQItnmL5nf0fXUSDfEft B2/sRBSRsmx7bDklwuCauMv4efgepV/eb49eXYSqq9sF8Bub41S+o2mkuPYuHySLHiXc 4PEuc+1+G0iAbEE8EMDBuBl/7NR2XdbNujSX1vfjbl3oGR+p0Z91fdUU6ynWGG3xz8os zPM0hCJtG656Lcn7uWWyqPqmfzfhv+/MWLdFCXG7xmannMJefldKTG7RYsOQ8rLUgJkF nayA== X-Gm-Message-State: AIkVDXK/fOwooY8DvV8BEpdj4ke5v1OQ3meweLhM7G1LzzaSuy98cqhaiChq31hyjs37yqco X-Received: by 10.55.22.77 with SMTP id g74mr16412889qkh.54.1485651712343; Sat, 28 Jan 2017 17:01:52 -0800 (PST) Original-Received: from holos.localdomain (pool-173-67-40-97.bltmmd.fios.verizon.net. [173.67.40.97]) by smtp.gmail.com with ESMTPSA id z123sm5485622qkd.45.2017.01.28.17.01.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 28 Jan 2017 17:01:51 -0800 (PST) Original-Received: by holos.localdomain (Postfix, from userid 1000) id 081126622C; Sat, 28 Jan 2017 20:01:50 -0500 (EST) Content-Disposition: inline In-Reply-To: <83r33nzkkx.fsf@gnu.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400d:c09::244 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:211715 Archived-At: On 28/01/17 at 09:53am, Eli Zaretskii wrote: > > From: Mark Oteiza > > Date: Fri, 27 Jan 2017 15:17:10 -0500 > > Cc: emacs-devel@gnu.org > > > > > How hard would it be to integrate with the xdg-user-dirs standard > > > instead? On many GNU/Linux systems, running "xdg-user-dir DOWNLOAD" is > > > enough (http://stackoverflow.com/questions/13161226/). This would > > > make eww consistent with Firefox, too (they take the slightly more > > > painful route of parsing ~/.config/user-dirs.dirs: > > > https://dxr.mozilla.org/mozilla-release/source/xpcom/io/SpecialSystemDirectory.cpp#256) > > > > An xdg.el would be nice to have for elisp that interfaces > > with XDG-following things. mpc.el and image-dired.el are two files that > > come to mind: mpd follows [0], image-dired > > supports [1]. Actually, it looks like those are the only two files with > > XDG bits, and I put them there. How about that. > > > > Anyways, these aren't difficult to implement. If it would be a welcome > > addition I'd have a go at writing it. > > > > [0] https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html > > [1] https://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html > > This has come up before. I think this would be welcome, but one issue > that didn't get resolved is how much of that should be automatic > (i.e. should Emacs automatically search certain directories for > certain kinds of files), and if so, how to split the imaginary xdg.el > into two parts, with the automatic part living in some preloaded file > (probably files.el). There's also the issue of whether users and/or > Lisp programs should be able to disable this search (e.g., by binding > some variable). Sounds like a daunting goal. I imagine having XDG bits preloaded would only really be necessary if Emacs decided it was going to follow the base directory spec (and probably only on GNU/Linux). In the mean time, the following is a small library of some useful functions. At least for the base directory spec it remains rather low level as the standard gives a lot of freedom to how applications want to handle multiple locations of config/data: ;;; xdg.el --- XDG specification and standard library -*- lexical-binding: t -*- ;; Copyright (C) 2017 Mark Oteiza ;; Author: Mark Oteiza ;; Keywords: files, data ;; This program 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. ;; This program 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 this program. If not, see . ;;; Commentary: ;; Library providing some convenience functions for the following XDG ;; standards and specifications ;; ;; - XDG Base Directory Specification ;; - Thumbnail Managing Standard ;; - xdg-user-dirs configuration ;;; Code: ;; XDG Base Directory Specification ;; https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html (defmacro xdg--dir-home (environ default-path) (declare (debug (stringp stringp))) (let ((env (make-symbol "env"))) `(let ((,env (getenv ,environ))) (if (or (null ,env) (not (file-name-absolute-p ,env))) (expand-file-name ,default-path) ,env)))) (defun xdg-config-home () "Return the base directory for user specific configuration files." (xdg--dir-home "XDG_CONFIG_HOME" "~/.config")) (defun xdg-cache-home () "Return the base directory for user specific cache files." (xdg--dir-home "XDG_CACHE_HOME" "~/.cache")) (defun xdg-data-home () "Return the base directory for user specific data files." (xdg--dir-home "XDG_DATA_HOME" "~/.local/share")) (defun xdg-runtime-dir () "Return the value of $XDG_RUNTIME_DIR." (getenv "XDG_RUNTIME_DIR")) (defun xdg-config-dirs () "Return the config directory search path as a list." (let ((env (getenv "XDG_CONFIG_DIRS"))) (if (or (null env) (string= env "")) '("/etc/xdg") (parse-colon-path env)))) (defun xdg-data-dirs () "Return the data directory search path as a list." (let ((env (getenv "XDG_CONFIG_DIRS"))) (if (or (null env) (string= env "")) '("/usr/local/share/" "/usr/share/") (parse-colon-path env)))) ;; Thumbnail Managing Standard ;; https://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html (defun xdg-thumb-uri (filename) "Return the canonical URI for FILENAME. If FILENAME has absolute path /foo/bar.jpg, its canonical URI is file:///foo/bar.jpg" (concat "file://" (expand-file-name filename))) (defun xdg-thumb-name (filename) "Return the appropriate thumbnail filename for FILENAME." (concat (md5 (xdg-thumb-uri filename)) ".png")) (defun xdg-thumb-mtime (filename) "Return modification time of FILENAME as integral seconds from the epoch." (floor (float-time (nth 5 (file-attributes filename))))) ;; XDG User Directories ;; https://www.freedesktop.org/wiki/Software/xdg-user-dirs/ (defconst xdg-line-regexp (eval-when-compile (rx "XDG_" (group-n 1 (or "DESKTOP" "DOWNLOAD" "TEMPLATES" "PUBLICSHARE" "DOCUMENTS" "MUSIC" "PICTURES" "VIDEOS")) "_DIR=\"" (group-n 2 (or "/" "$HOME/") (*? (or (not (any "\"")) "\\\""))) "\"")) "Regexp matching non-comment lines in xdg-user-dirs config files.") (defvar xdg-user-dirs nil "Alist of directory keys and values.") (defun xdg--user-dirs-parse-line () "Return pair of user-dirs key to directory value in LINE, otherwise nil. This should be called at the beginning of a line." (skip-chars-forward "[:blank:]") (when (and (/= (following-char) ?#) (looking-at xdg-line-regexp)) (let ((k (match-string 1)) (v (match-string 2))) (when (and k v) (cons k v))))) (defun xdg--user-dirs-parse-file (filename) "Return alist of xdg-user-dirs from FILENAME." (let (elt res) (with-temp-buffer (insert-file-contents filename) (goto-char (point-min)) (while (not (eobp)) (setq elt (xdg--user-dirs-parse-line)) (when (consp elt) (push elt res)) (forward-line))) res)) (defun xdg-user-dir (name) "Return the path of user directory referred to by NAME." (when (null xdg-user-dirs) (setq xdg-user-dirs (xdg--user-dirs-parse-file (expand-file-name "user-dirs.dirs" (xdg-config-home))))) (cdr (assoc name xdg-user-dirs))) (provide 'xdg) ;;; xdg.el ends here