From 19be132871d4eb6e12e632454d016726d0b48d8b Mon Sep 17 00:00:00 2001 From: Daanturo Date: Sat, 2 Jul 2022 17:55:57 +0700 Subject: [PATCH] Define file-parent-directory Get parent directory of a file. * doc/lispref/files.texi: Document the function. * etc/NEWS: Add its entry. * lisp/emacs-lisp/shortdoc.el: Add it to 'file-name' group. * lisp/files.el: implementation --- doc/lispref/files.texi | 6 ++++++ etc/NEWS | 3 +++ lisp/emacs-lisp/shortdoc.el | 7 +++++++ lisp/files.el | 17 +++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index ea8683a6d8..437a3001d3 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -2445,6 +2445,12 @@ Directory Names because it recognizes abbreviations even as part of the name. @end defun +@defun file-parent-directory filename +This function returns the parent directory of @var{filename}. If +@var{filename} is at the top-level, return nil. @var{filename} can be +relative to `default-directory'. +@end defun + @node File Name Expansion @subsection Functions that Expand Filenames @cindex expansion of file names diff --git a/etc/NEWS b/etc/NEWS index 30404cc13c..3bfebd6bb7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -317,6 +317,9 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +** New function 'file-parent-directory' +Get the parent directory of a file. + ** New config variable 'syntax-wholeline-max' to reduce the cost of long lines. This variable is used by some operations (mostly syntax-propertization and font-locking) to treat lines longer than this variable as if they diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index c82aa3365c..a410d6c2fb 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -353,6 +353,13 @@ file-name (abbreviate-file-name :no-eval (abbreviate-file-name "/home/some-user") :eg-result "~some-user") + (file-parent-directory + :eval (file-parent-directory "/foo/bar") + :eval (file-parent-directory "~") + :eval (file-parent-directory "/tmp/") + :eval (file-parent-directory "foo/bar") + :eval (file-parent-directory "foo") + :eval (file-parent-directory "/")) "Quoted File Names" (file-name-quote :args (name) diff --git a/lisp/files.el b/lisp/files.el index 1295c24c93..ccb3520d8c 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5145,6 +5145,23 @@ file-name-split (setq filename nil)))) components)) +(defun file-parent-directory (filename) + "Return the parent directory of FILENAME. +If FILENAME is at the top-level, return nil. FILENAME can be +relative to `default-directory'." + (let* ((expanded-filename (expand-file-name filename)) + (parent (file-name-directory (directory-file-name expanded-filename)))) + (cond + ;; filename is at top-level, therefore no parent + ((or (null parent) + (file-equal-p parent expanded-filename)) + nil) + ;; filename is relative, return relative parent + ((not (file-name-absolute-p filename)) + (file-relative-name parent)) + (t + parent)))) + (defcustom make-backup-file-name-function #'make-backup-file-name--default-function "A function that `make-backup-file-name' uses to create backup file names. -- 2.37.0