config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

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