Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor install docset functions #176

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 60 additions & 57 deletions helm-dash.el
Original file line number Diff line number Diff line change
Expand Up @@ -299,104 +299,107 @@ If doesn't exist, it asks to create it."
(when (helm-dash--ensure-created-docsets-path (helm-dash-docsets-path))
(helm-dash--install-docset (car (assoc-default docset-name (helm-dash-unofficial-docsets))) docset-name)))

(defmacro helm-dash-extract-docset-into (docset-archive docsets-path docset-name)
"Extract DOCSET-ARCHIVE into DOCSETS-PATH/DOCSET-NAME, removing top directory."
`(let ((docset-dir (concat (file-name-as-directory docsets-path) docset-name ".docset")))
(mkdir docset-dir t)
(shell-command (format "tar xvf %s -C %s --strip-components=1"
(shell-quote-argument (expand-file-name ,docset-archive))
(shell-quote-argument (expand-file-name docset-dir))))
docset-name))

(defmacro helm-dash-extract-docset (docset-archive docsets-path)
"Extract DOCSET-ARCHIVE to DOCSETS-PATH."
`(let* ((tar-output (shell-command-to-string
(format "tar xvf %s -C %s"
(shell-quote-argument (expand-file-name ,docset-archive))
(shell-quote-argument ,docsets-path))))
(last-line (car (last (split-string tar-output "\n" t)))))
(replace-regexp-in-string "^x " "" (car (split-string last-line "\\." t)))))

(defmacro helm-dash-get-docset-url (feed-path)
"Parse a xml feed with docset urls and return the first url.
The Argument FEED-PATH should be a string with the path of the xml file."
`(let* ((xml (xml-parse-file ,feed-path))
(urls (car xml))
(url (xml-get-children urls 'url)))
(caddr (car url))))

(defmacro helm-dash-docset-url (docset-name docsets-url)
"Fetch and parse docset feed returning the url for DOCSET-NAME located at DOCSETS-URL."
`(let* ((feed-url (format "%s/%s.xml" ,docsets-url ,docset-name))
(feed-path (url-file-local-copy feed-url)))
(helm-dash-get-docset-url feed-path)))

(defmacro helm-dash-download-install-docset (docset-name docsets-path docsets-url)
"Download and install DOCSET-NAME to DOCSETS-PATH, using feeds at DOCSETS-URL."
`(let ((docset-url (helm-dash-docset-url ,docset-name ,docsets-url)))
(helm-dash-extract-docset-into (url-file-local-copy docset-url) docsets-path docset-name)))

;;;###autoload
(defun helm-dash-install-docset-from-file (docset-tmp-path)
"Extract the content of DOCSET-TMP-PATH, move it to `helm-dash-docsets-path` and activate the docset."
(interactive
(list (car (find-file-read-args "Docset Tarball: " t))))
(let ((docset-folder
(helm-dash-docset-folder-name
(shell-command-to-string
(format "tar xvf %s -C %s"
(shell-quote-argument (expand-file-name docset-tmp-path))
(shell-quote-argument (helm-dash-docsets-path)))))))
(helm-dash-activate-docset docset-folder)
(message (format
"Docset installed. Add \"%s\" to helm-dash-common-docsets or helm-dash-docsets."
docset-folder))))
(let ((proc (helm-dash-async-install-docset-from-file docset-tmp-path)))
(when proc (async-wait proc))))

;;;###autoload
(defun helm-dash-install-docset (docset-name)
"Download an official docset with specified DOCSET-NAME and move its stuff to docsets-path."
(interactive (list (helm-dash-read-docset
"Install docset"
(helm-dash-official-docsets))))

(when (helm-dash--ensure-created-docsets-path (helm-dash-docsets-path))
(let ((feed-url (format "%s/%s.xml" helm-dash-docsets-url docset-name))
(feed-tmp-path (format "%s%s-feed.xml" temporary-file-directory docset-name)))
(url-copy-file feed-url feed-tmp-path t)
(helm-dash--install-docset (helm-dash-get-docset-url feed-tmp-path) docset-name))))
(let ((proc (helm-dash-async-install-docset docset-name)))
(when proc (async-wait proc))))

;;;###autoload
(defun helm-dash-async-install-docset (docset-name)
"Asynchronously download docset with specified DOCSET-NAME and move its stuff to docsets-path."
(interactive (list (helm-dash-read-docset "Install docset" (helm-dash-official-docsets))))
(when (helm-dash--ensure-created-docsets-path (helm-dash-docsets-path))
(let ((feed-url (format "%s/%s.xml" helm-dash-docsets-url docset-name)))

(message (concat "The docset \"" docset-name "\" will now be installed asynchronously."))

(message "The docset \"%s\" will now be installed." docset-name)
(let ((docsets-path helm-dash-docsets-path)
(docsets-url helm-dash-docsets-url))
(async-start ; First async call gets the docset meta data
(lambda ()
;; Beware! This lambda is run in it's own instance of emacs.
(url-file-local-copy feed-url))
(lambda (filename)
(let ((docset-url (helm-dash-get-docset-url filename)))
(async-start ; Second async call gets the docset itself
(lambda ()
;; Beware! This lambda is run in it's own instance of emacs.
(url-file-local-copy docset-url))
(lambda (docset-tmp-path)
(helm-dash-async-install-docset-from-file docset-tmp-path)))))))))
(ignore-errors
(require 'mm-decode) ;; needed by `url-file-local-copy'
(helm-dash-download-install-docset docset-name docsets-path docsets-url)))
(lambda (docset-folder)
(when (string= docset-folder "nil")
(user-error "Error installing docset \"%s\"" docset-name))
(helm-dash-activate-docset docset-name)
(message "Docset installed. Add \"%s\" to helm-dash-common-docsets or helm-dash-docsets."
docset-name))))))

;;;###autoload
(defun helm-dash-async-install-docset-from-file (docset-tmp-path)
"Asynchronously extract the content of DOCSET-TMP-PATH, move it to `helm-dash-docsets-path` and activate the docset."
(interactive (list (car (find-file-read-args "Docset Tarball: " t))))
(let ((docset-tar-path (expand-file-name docset-tmp-path))
(docset-out-path (helm-dash-docsets-path)))
(docsets-path helm-dash-docsets-path))
(async-start
(lambda ()
;; Beware! This lambda is run in it's own instance of emacs.
(shell-command-to-string
(format "tar xvf %s -C %s"
(shell-quote-argument docset-tar-path)
(shell-quote-argument docset-out-path))))
(lambda (shell-output)
(let ((docset-folder (helm-dash-docset-folder-name shell-output)))
(helm-dash-activate-docset docset-folder)
(message (format
"Docset installed. Add \"%s\" to helm-dash-common-docsets or helm-dash-docsets."
docset-folder)))))))
(helm-dash-extract-docset docset-tar-path docsets-path))
(lambda (docset-folder)
(helm-dash-activate-docset docset-folder)
(message "Docset installed. Add \"%s\" to helm-dash-common-docsets or helm-dash-docsets."
docset-folder)))))

(defalias 'helm-dash-update-docset 'helm-dash-install-docset)

(defun helm-dash-docset-installed-p (docset)
"Return true if DOCSET is installed."
(member (replace-regexp-in-string "_" " " docset) (helm-dash-installed-docsets)))
(member docset (helm-dash-installed-docsets)))

;;;###autoload
(defun helm-dash-ensure-docset-installed (docset)
"Install DOCSET if it is not currently installed."
(unless (helm-dash-docset-installed-p docset)
(helm-dash-install-docset docset)))

(defun helm-dash-docset-folder-name (tar-output)
"Return the name of the folder where the docset has been extracted.
The argument TAR-OUTPUT should be an string with the output of a tar command."
(let ((last-line
(car (last (split-string tar-output "\n" t)))))
(replace-regexp-in-string "^x " "" (car (split-string last-line "\\." t)))))

(defun helm-dash-get-docset-url (feed-path)
"Parse a xml feed with docset urls and return the first url.
The Argument FEED-PATH should be a string with the path of the xml file."
(let* ((xml (xml-parse-file feed-path))
(urls (car xml))
(url (xml-get-children urls 'url)))
(cl-caddr (cl-first url))))
(helm-dash-async-install-docset docset)))

(defvar helm-dash-sql-queries
'((DASH . (lambda (pattern)
Expand Down