shrink-path.el (5759B)
1 ;;; shrink-path.el --- fish-style path -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2017 Benjamin Andresen 4 5 ;; Author: Benjamin Andresen 6 ;; Version: 0.3.1 7 ;; URL: https://gitlab.com/bennya/shrink-path.el 8 ;; Package-Requires: ((emacs "24") (s "1.6.1") (dash "1.8.0") (f "0.10.0")) 9 10 ;; This file is NOT part of GNU Emacs. 11 12 ;; This program is free software; you can redistribute it and/or modify 13 ;; it under the terms of the GNU General Public License as published by 14 ;; the Free Software Foundation; either version 3, or (at your option) 15 ;; any later version. 16 17 ;; This program is distributed in the hope that it will be useful, 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 ;; GNU General Public License for more details. 21 22 ;; You should have received a copy of the GNU General Public License 23 ;; along with GNU Emacs; see the file LICENSE. If not, write to the 24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25 ;; Boston, MA 02110-1301, USA. 26 27 ;;; Commentary: 28 29 ;; Provides functions that offer fish shell[1] path truncation. 30 ;; Directory /usr/share/emacs/site-lisp => /u/s/e/site-lisp 31 ;; 32 ;; Also includes utility functions that make integration in eshell or the 33 ;; modeline easier. 34 ;; 35 ;; [1] https://fishshell.com/ 36 37 38 ;;; Code: 39 (require 'dash) 40 (require 's) 41 (require 'f) 42 (require 'rx) 43 44 (defun shrink-path--truncate (str) 45 "Return STR's first character or first two characters if hidden." 46 (substring str 0 (if (s-starts-with? "." str) 2 1))) 47 48 (defun shrink-path--dirs-internal (full-path &optional truncate-all) 49 "Return fish-style truncated string based on FULL-PATH. 50 Optional parameter TRUNCATE-ALL will cause the function to truncate the last 51 directory too." 52 (let* ((home (expand-file-name "~")) 53 (path (replace-regexp-in-string 54 (s-concat "^" home) "~" full-path)) 55 (split (s-split "/" path 'omit-nulls)) 56 (split-len (length split)) 57 shrunk) 58 (->> split 59 (--map-indexed (if (= it-index (1- split-len)) 60 (if truncate-all (shrink-path--truncate it) it) 61 (shrink-path--truncate it))) 62 (s-join "/") 63 (setq shrunk)) 64 (s-concat (unless (s-matches? (rx bos (or "~" "/")) shrunk) "/") 65 shrunk 66 (unless (s-ends-with? "/" shrunk) "/")))) 67 68 69 (defun shrink-path-dirs (&optional path truncate-tail) 70 "Given PATH return fish-styled shrunken down path. 71 TRUNCATE-TAIL will cause the function to truncate the last directory too." 72 (let* ((path (or path default-directory)) 73 (path (f-full path))) 74 (cond 75 ((s-equals? (f-short path) "/") "/") 76 ((s-matches? (rx bos (or "~" "/") eos) "~/")) 77 (t (shrink-path--dirs-internal path truncate-tail))))) 78 79 (defun shrink-path-expand (str &optional absolute-p) 80 "Return expanded path from STR if found or list of matches on multiple. 81 The path referred to by STR has to exist for this to work. 82 If ABSOLUTE-P is t the returned path will be absolute." 83 (let* ((str-split (s-split "/" str 'omit-nulls)) 84 (head (car str-split))) 85 (if (= (length str-split) 1) 86 (s-concat "/" str-split) 87 (--> (-drop 1 str-split) ;; drop head 88 (-map (lambda (e) (s-concat e "*")) it) 89 (-drop-last 1 it) ;; drop tail as it may not exist 90 (s-join "/" it) 91 (s-concat (if (s-equals? head "~") "~/" head) it) 92 (f-glob it) 93 (-map (lambda (e) (s-concat e "/" (-last-item str-split))) it) 94 (if absolute-p (-map #'f-full it) (-map #'f-abbrev it)) 95 (if (= (length it) 1) (car it) it))))) 96 97 (defun shrink-path-prompt (&optional pwd) 98 "Return cons of BASE and DIR for PWD. 99 If PWD isn't provided will default to `default-directory'." 100 (let* ((pwd (or pwd default-directory)) 101 (shrunk (shrink-path-dirs pwd)) 102 (split (--> shrunk (s-split "/" it 'omit-nulls))) 103 base dir) 104 (setq dir (or (-last-item split) "/")) 105 (setq base (if (s-equals? dir "/") "" 106 (s-chop-suffix (s-concat dir "/") shrunk))) 107 (cons base dir))) 108 109 (defun shrink-path-file (file &optional truncate-tail) 110 "Return FILE's shrunk down path and filename. 111 TRUNCATE-TAIL controls if the last directory should also be shortened." 112 (let ((filename (f-filename file)) 113 (dirname (f-dirname file))) 114 (s-concat (shrink-path-dirs dirname truncate-tail) filename))) 115 116 (defun shrink-path-file-expand (str &optional exists-p absolute-p) 117 "Return STR's expanded filename. 118 The path referred to by STR has to exist for this to work. 119 If EXISTS-P is t the filename also has to exist. 120 If ABSOLUTE-P is t the returned path will be absolute." 121 (let ((expanded (shrink-path-expand str absolute-p))) 122 (if (and expanded exists-p) 123 (if (f-exists? expanded) expanded) 124 expanded))) 125 126 (defun shrink-path-file-mixed (shrink-path rel-path filename) 127 "Returns list of mixed truncated file name locations. 128 129 Consists of SHRINK-PATH's parent, SHRINK-PATH basename, relative REL-PATH and 130 FILENAME. 131 For use in modeline or prompts, etc." 132 (let ((shrunk-dirs (shrink-path-prompt shrink-path)) 133 sp-parent sp-rel rel-rel nd-file) 134 135 (when (f-descendant-of? filename shrink-path) 136 (when shrunk-dirs 137 (setq sp-parent (car shrunk-dirs) 138 sp-rel (cdr shrunk-dirs))) 139 (setq rel-rel (if (or (f-same? rel-path shrink-path) 140 (s-equals? (f-relative rel-path shrink-path) ".")) 141 nil 142 (f-relative rel-path shrink-path))) 143 (setq nd-file (file-name-nondirectory filename)) 144 145 (list sp-parent sp-rel rel-rel nd-file)))) 146 147 (provide 'shrink-path) 148 ;;; shrink-path.el ends here