summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitalie Spinu <spinuvit@gmail.com>2018-08-30 17:21:18 +0200
committerBozhidar Batsov <bozhidar.batsov@gmail.com>2018-09-08 22:25:50 +0300
commit55740ea8e973fb1fcb90c65b068a076ab2022171 (patch)
treeeca5270de7efefed129148486a88c290f73be835
parent8996e699ae7dd140a9f74219940e2e30ff213fd9 (diff)
Open archive entries within AVFS directory
-rw-r--r--CHANGELOG.md3
-rw-r--r--cider-common.el80
-rw-r--r--doc/interactive_programming.md27
3 files changed, 70 insertions, 40 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 50d974cd..97f9faab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,13 @@
## master (unreleased)
+* [#2430](https://github.com/clojure-emacs/cider/issues/2375) `cider-find-var` opens archive files inside [AVFS](http://avf.sourceforge.net) folders if AVFS is detected.
+
## 0.18.0 (2018-09-02)
### New features
+* Open archive files within AVFS direcotires if AVFS has been detected.
* [#2375](https://github.com/clojure-emacs/cider/issues/2375): Move `cider-eval-toplevel-inside-comment-form` into clojure-mode as `clojure-toplevel-inside-comment-form` so `beginning-of-defun` is aware of comment forms.
* Add new `cider-session-name-template` variable for flexible customization of cider session and REPL buffer names.
* Bind `C-c M-r` to `cider-restart`.
diff --git a/cider-common.el b/cider-common.el
index 3bae267a..08414c63 100644
--- a/cider-common.el
+++ b/cider-common.el
@@ -286,10 +286,13 @@ If no local or remote file exists, return nil."
(defun cider-find-file (url)
"Return a buffer visiting the file URL if it exists, or nil otherwise.
If URL has a scheme prefix, it must represent a fully-qualified file path
-or an entry within a zip/jar archive. If URL doesn't contain a scheme
-prefix and is an absolute path, it is treated as such. Finally, if URL is
-relative, it is expanded within each of the open Clojure buffers till an
-existing file ending with URL has been found."
+or an entry within a zip/jar archive. If AVFS (archive virtual file
+system; see online docs) is mounted the archive entry is opened inside the
+AVFS directory, otherwise the entry is archived into a temporary read-only
+buffer. If URL doesn't contain a scheme prefix and is an absolute path, it
+is treated as such. Finally, if URL is relative, it is expanded within each
+of the open Clojure buffers till an existing file ending with URL has been
+found."
(require 'arc-mode)
(cond ((string-match "^file:\\(.+\\)" url)
(when-let* ((file (cider--url-to-file (match-string 1 url)))
@@ -297,42 +300,39 @@ existing file ending with URL has been found."
(find-file-noselect path)))
((string-match "^\\(jar\\|zip\\):\\(file:.+\\)!/\\(.+\\)" url)
(when-let* ((entry (match-string 3 url))
- (file (cider--url-to-file (match-string 2 url)))
- (path (cider--file-path file))
- ;; It is used for targeting useless intermediate buffer.
- ;; That buffer is made by (find-file path) below.
- ;; It has the name which is the last part of the path.
- (trash (replace-regexp-in-string "^/.+/" "" path))
- (name (format "%s:%s" path entry)))
- (or (find-buffer-visiting name)
- (if (tramp-tramp-file-p path)
- (progn
- ;; Use emacs built in archiving.
- ;; This makes a list of files in archived Zip or Jar.
- ;; That list buffer is useless after jumping to the
- ;; buffer which has the real definition.
- ;; It'll be removed by (kill-buffer trash) below.
- (find-file path)
- (goto-char (point-min))
- ;; Make sure the file path is followed by a newline to
- ;; prevent eg. clj matching cljs.
- (search-forward (concat entry "\n"))
- ;; moves up to matching line
- (forward-line -1)
- (archive-extract)
- ;; Remove useless buffer made by (find-file path) above.
- (kill-buffer trash)
- (current-buffer))
- ;; Use external zip program to just extract the single file
- (with-current-buffer (generate-new-buffer
- (file-name-nondirectory entry))
- (archive-zip-extract path entry)
- (set-visited-file-name name)
- (setq-local default-directory (file-name-directory path))
- (setq-local buffer-read-only t)
- (set-buffer-modified-p nil)
- (set-auto-mode)
- (current-buffer))))))
+ (file (cider--url-to-file (match-string 2 url)))
+ (path (cider--file-path file))
+ (name (format "%s:%s" path entry))
+ (avfs (format "%s%s#uzip/%s"
+ (expand-file-name (or (getenv "AVFSBASE") "~/.avfs/"))
+ path entry)))
+ (cond
+ ;; 1) use avfs
+ ((file-exists-p avfs)
+ (find-file-noselect avfs))
+ ;; 2) already uncompressed
+ ((find-buffer-visiting name))
+ ;; 3) on remotes use Emacs built-in archiving
+ ((tramp-tramp-file-p path)
+ (find-file path)
+ (goto-char (point-min))
+ ;; anchor to eol to prevent eg. clj matching cljs.
+ (re-search-forward (concat entry "$"))
+ (let ((archive-buffer (current-buffer)))
+ (archive-extract)
+ (kill-buffer archive-buffer))
+ (current-buffer))
+ ;; 4) Use external zip program to extract a single file
+ (t
+ (with-current-buffer (generate-new-buffer
+ (file-name-nondirectory entry))
+ (archive-zip-extract path entry)
+ (set-visited-file-name name)
+ (setq-local default-directory (file-name-directory path))
+ (setq-local buffer-read-only t)
+ (set-buffer-modified-p nil)
+ (set-auto-mode)
+ (current-buffer))))))
(t (if-let* ((path (cider--file-path url)))
(find-file-noselect path)
(unless (file-name-absolute-p url)
diff --git a/doc/interactive_programming.md b/doc/interactive_programming.md
index 92906d01..20d2c9bb 100644
--- a/doc/interactive_programming.md
+++ b/doc/interactive_programming.md
@@ -90,4 +90,31 @@ Here's a list of `cider-mode`'s keybindings:
![CIDER which-key](images/cider-which-key.png)
+
+!!! Tip
+
+ `cider-find-var` has built-in support for [AVFS](). AVFS is an a virtual
+ file system which allows seamless navigation within archives as if they were
+ normal directories. When AVFS is mounted, `cider-find-var` automatically
+ opens `jar` and `zip` files inside AVFS folder instead of attempting to
+ uncompressed the archive.
+
+ On linux based systems AVFS comes through the distribution managers. For
+ example on Debian derivatives:
+
+ `sudo apt-get install avfs`
+
+ Once installed mount with `mountavfs` in a place where it could be started
+ automatically during the startup (`.bash_profile` would do). Or initialize the
+ `avfsd` daemon directly like this
+
+ `/usr/bin/avfsd -o allow_root -o intr -o sync_read .avfs`
+
+ [AVFS]() is not available on Windows but could be installed on MacOS with [some
+ effort](http://blog.breadncup.com/tag/sunrise-commander/). Some other uses of
+ [AVFS]() in Emacs include
+ [dired-avfs](https://github.com/Fuco1/dired-hacks#dired-avfs) and
+ [sunrise-commander](https://www.emacswiki.org/emacs/Sunrise_Commander_Tips#toc12).
+
[which-key]: https://github.com/justbur/emacs-which-key
+[AVFS]: http://avf.sourceforge.net