Add some new packages

This commit is contained in:
Gergely Polonkai 2016-09-16 16:37:59 +02:00
parent db73d9ac2c
commit c48ae18edb
9 changed files with 1659 additions and 0 deletions

View File

@ -0,0 +1,76 @@
;;; helm-projectile-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
;;;### (autoloads nil "helm-projectile" "helm-projectile.el" (22490
;;;;;; 46093 331336 211000))
;;; Generated autoloads from helm-projectile.el
(defvar helm-projectile-fuzzy-match t "\
Enable fuzzy matching for Helm Projectile commands.
This needs to be set before loading helm-projectile.")
(custom-autoload 'helm-projectile-fuzzy-match "helm-projectile" t)
(autoload 'helm-projectile-find-file-dwim "helm-projectile" "\
Find file at point based on context.
\(fn)" t nil)
(autoload 'helm-projectile-find-other-file "helm-projectile" "\
Switch between files with the same name but different extensions using Helm.
With FLEX-MATCHING, match any file that contains the base name of current file.
Other file extensions can be customized with the variable `projectile-other-file-alist'.
\(fn &optional FLEX-MATCHING)" t nil)
(autoload 'helm-projectile-on "helm-projectile" "\
Turn on helm-projectile key bindings.
\(fn)" t nil)
(autoload 'helm-projectile-off "helm-projectile" "\
Turn off helm-projectile key bindings.
\(fn)" t nil)
(autoload 'helm-projectile-grep "helm-projectile" "\
Helm version of `projectile-grep'.
DIR is the project root, if not set then current directory is used
\(fn &optional DIR)" t nil)
(autoload 'helm-projectile-ack "helm-projectile" "\
Helm version of projectile-ack.
\(fn &optional DIR)" t nil)
(autoload 'helm-projectile-ag "helm-projectile" "\
Helm version of projectile-ag.
\(fn &optional OPTIONS)" t nil)
(autoload 'helm-projectile-toggle "helm-projectile" "\
Toggle Helm version of Projectile commands.
\(fn TOGGLE)" nil nil)
(autoload 'helm-projectile "helm-projectile" "\
Use projectile with Helm instead of ido.
With a prefix ARG invalidates the cache first.
If invoked outside of a project, displays a list of known projects to jump.
\(fn &optional ARG)" t nil)
(eval-after-load 'projectile '(progn (define-key projectile-command-map (kbd "h") #'helm-projectile)))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; helm-projectile-autoloads.el ends here

View File

@ -0,0 +1 @@
(define-package "helm-projectile" "20160902.2236" "Helm integration for Projectile" '((helm "1.7.7") (projectile "0.14.0") (cl-lib "0.3")) :url "https://github.com/bbatsov/helm-projectile" :keywords '("project" "convenience"))

View File

@ -0,0 +1,877 @@
;;; helm-projectile.el --- Helm integration for Projectile
;; Copyright (C) 2011-2016 Bozhidar Batsov
;; Author: Bozhidar Batsov
;; URL: https://github.com/bbatsov/helm-projectile
;; Package-Version: 20160902.2236
;; Created: 2011-31-07
;; Keywords: project, convenience
;; Version: 0.14.0
;; Package-Requires: ((helm "1.7.7") (projectile "0.14.0") (cl-lib "0.3"))
;; This file is NOT part of GNU Emacs.
;;; License:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; This library provides easy project management and navigation. The
;; concept of a project is pretty basic - just a folder containing
;; special file. Currently git, mercurial and bazaar repos are
;; considered projects by default. If you want to mark a folder
;; manually as a project just create an empty .projectile file in
;; it. See the README for more details.
;;
;;; Code:
(require 'projectile)
(require 'cl-lib)
(require 'grep)
(require 'helm)
(require 'helm-types)
(require 'helm-locate)
(require 'helm-buffers)
(require 'helm-files)
(declare-function eshell "eshell")
(declare-function helm-do-ag "helm-ag")
(defvar helm-ag-base-command)
(defvar grep-find-ignored-directories)
(defvar grep-find-ignored-files)
(defgroup helm-projectile nil
"Helm support for projectile."
:prefix "helm-projectile-"
:group 'projectile
:link `(url-link :tag "helm-projectile homepage" "https://github.com/bbatsov/projectile"))
(defvar helm-projectile-current-project-root)
;;;###autoload
(defcustom helm-projectile-fuzzy-match t
"Enable fuzzy matching for Helm Projectile commands.
This needs to be set before loading helm-projectile."
:group 'helm-projectile
:type 'boolean)
(defun helm-projectile-coerce-file (candidate)
(with-current-buffer (helm-candidate-buffer)
(expand-file-name candidate (projectile-project-root))))
(defmacro helm-projectile-define-key (keymap key def &rest bindings)
"In KEYMAP, define key sequence KEY1 as DEF1, KEY2 as DEF2 ..."
(declare (indent defun))
(let ((ret '(progn)))
(while key
(push
`(define-key ,keymap ,key
(lambda ()
(interactive)
(helm-exit-and-execute-action ,def)))
ret)
(setq key (pop bindings)
def (pop bindings)))
(reverse ret)))
(defun helm-projectile-hack-actions (actions &rest prescription)
"Given a Helm action list and a prescription, return a hacked
Helm action list, after applying the PRESCRIPTION.
The Helm action list ACTIONS is of the form:
\(\(DESCRIPTION1 . FUNCTION1\)
\(DESCRIPTION2 . FUNCTION2\)
...
\(DESCRIPTIONn . FUNCTIONn\)\)
PRESCRIPTION is in the form:
\(INSTRUCTION1 INSTRUCTION2 ... INSTRUCTIONn\)
If an INSTRUCTION is a symbol, the action with function name
INSTRUCTION is deleted.
If an INSTRUCTION is of the form \(FUNCTION1 . FUNCTION2\), the
action with function name FUNCTION1 will change it's function to
FUNCTION2.
If an INSTRUCTION is of the form \(FUNCTION . DESCRIPTION\), and
if an action with function name FUNCTION exists in the original
Helm action list, the action in the Helm action list, with
function name FUNCTION will change it's description to
DESCRIPTION. Otherwise, (FUNCTION . DESCRIPTION) will be added to
the action list.
Please check out how `helm-projectile-file-actions' is defined
for an example of how this function is being used."
(let* ((to-delete (cl-remove-if (lambda (entry) (listp entry)) prescription))
(actions (cl-delete-if (lambda (action) (memq (cdr action) to-delete))
(copy-alist actions)))
new)
(cl-dolist (action actions)
(when (setq new (cdr (assq (cdr action) prescription)))
(if (stringp new)
(setcar action new)
(setcdr action new))))
;; Add new actions from PRESCRIPTION
(setq new nil)
(cl-dolist (instruction prescription)
(when (and (listp instruction)
(null (rassq (car instruction) actions))
(symbolp (car instruction)) (stringp (cdr instruction)))
(push (cons (cdr instruction) (car instruction)) new)))
(append actions (nreverse new))))
(defun helm-projectile-vc (dir)
"A Helm action for jumping to project root using `vc-dir' or Magit.
DIR is a directory to be switched"
(let ((projectile-require-project-root nil))
(projectile-vc dir)))
(defun helm-projectile-compile-project (dir)
"A Helm action for compile a project.
DIR is the project root."
(let ((helm--reading-passwd-or-string t)
(default-directory dir))
(projectile-compile-project helm-current-prefix-arg dir)))
(defun helm-projectile-test-project (dir)
"A Helm action for test a project.
DIR is the project root."
(let ((helm--reading-passwd-or-string t)
(default-directory dir))
(projectile-test-project helm-current-prefix-arg)))
(defun helm-projectile-run-project (dir)
"A Helm action for run a project.
DIR is the project root."
(let ((helm--reading-passwd-or-string t)
(default-directory dir))
(projectile-run-project helm-current-prefix-arg)))
(defun helm-projectile-remove-known-project (_ignore)
"Remove selected projects from projectile project list.
_IGNORE means the argument does not matter.
It is there because Helm requires it."
(let* ((projects (helm-marked-candidates :with-wildcard t))
(len (length projects)))
(with-helm-display-marked-candidates
helm-marked-buffer-name
projects
(if (not (y-or-n-p (format "Remove *%s projects(s)? " len)))
(message "(No removal performed)")
(progn
(mapc (lambda (p)
(delete p projectile-known-projects))
projects)
(projectile-save-known-projects))
(message "%s projects(s) removed" len)))))
(defvar helm-projectile-projects-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(helm-projectile-define-key map
(kbd "C-d") #'dired
(kbd "M-g") #'helm-projectile-vc
(kbd "M-e") #'helm-projectile-switch-to-eshell
(kbd "C-s") #'helm-projectile-grep
(kbd "M-c") #'helm-projectile-compile-project
(kbd "M-t") #'helm-projectile-test-project
(kbd "M-r") #'helm-projectile-run-project
(kbd "M-D") #'helm-projectile-remove-known-project)
map)
"Mapping for known projectile projects.")
(defvar helm-source-projectile-projects
(helm-build-in-buffer-source "Projectile projects"
:data (lambda ()
(if (projectile-project-p)
(cons (abbreviate-file-name (projectile-project-root))
(projectile-relevant-known-projects))
projectile-known-projects))
:fuzzy-match helm-projectile-fuzzy-match
:keymap helm-projectile-projects-map
:mode-line helm-read-file-name-mode-line-string
:action '(("Switch to project" .
(lambda (project)
(let ((projectile-completion-system 'helm))
(projectile-switch-project-by-name project))))
("Open Dired in project's directory `C-d'" . dired)
("Open project root in vc-dir or magit `M-g'" . helm-projectile-vc)
("Switch to Eshell `M-e'" . helm-projectile-switch-to-eshell)
("Grep in projects `C-s'" . helm-projectile-grep)
("Compile project `M-c'. With C-u, new compile command"
. helm-projectile-compile-project)
("Remove project(s) from project list `M-D'" . helm-projectile-remove-known-project)))
"Helm source for known projectile projects.")
(define-key helm-etags-map (kbd "C-c p f")
(lambda ()
(interactive)
(helm-run-after-exit 'helm-projectile-find-file nil)))
(defun helm-projectile-find-files-eshell-command-on-file-action (_candidate)
(interactive)
(let* ((helm-ff-default-directory (file-name-directory _candidate)))
(helm-find-files-eshell-command-on-file _candidate)))
(defun helm-projectile-ff-etags-select-action (_candidate)
(interactive)
(let* ((helm-ff-default-directory (file-name-directory _candidate)))
(helm-ff-etags-select _candidate)))
(defun helm-projectile-switch-to-eshell (dir)
(interactive)
(let* ((projectile-require-project-root nil)
(helm-ff-default-directory (file-name-directory (projectile-expand-root dir))))
(helm-ff-switch-to-eshell dir)))
(defun helm-projectile-files-in-current-dired-buffer ()
"Return a list of files (only) in the current dired buffer."
(let (flist)
(cl-flet ((fpush (fname) (push fname flist)))
(save-excursion
(let (file buffer-read-only)
(goto-char (point-min))
(while (not (eobp))
(save-excursion
(and (not (eolp))
(setq file (dired-get-filename t t)) ; nil on non-file
(progn (end-of-line)
(funcall #'fpush file))))
(forward-line 1)))))
(mapcar 'file-truename (nreverse flist))))
(defun helm-projectile-all-dired-buffers ()
"Get all current Dired buffers."
(mapcar (lambda (b)
(with-current-buffer b (buffer-name)))
(cl-remove-if-not
(lambda (b)
(with-current-buffer b
(and (eq major-mode 'dired-mode)
(buffer-name))))
(buffer-list))))
(defvar helm-projectile-virtual-dired-remote-enable nil
"Enable virtual Dired manager on remote host.
Disabled by default.")
(defun helm-projectile-dired-files-new-action (candidate)
"Create a Dired buffer from chosen files.
CANDIDATE is the selected file, but choose the marked files if available."
(if (and (file-remote-p (projectile-project-root))
(not helm-projectile-virtual-dired-remote-enable))
(message "Virtual Dired manager is disabled in remote host. Enable with %s."
(propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
(let ((files (cl-remove-if-not
(lambda (f)
(not (string= f "")))
(mapcar (lambda (file)
(replace-regexp-in-string (projectile-project-root) "" file))
(helm-marked-candidates :with-wildcard t))))
(new-name (completing-read "Select or enter a new buffer name: "
(helm-projectile-all-dired-buffers)))
(helm--reading-passwd-or-string t)
(default-directory (projectile-project-root)))
;; create a unique buffer that is unique to any directory in default-directory
;; or opened buffer; when Dired is passed with a non-existence directory name,
;; it only creates a buffer and insert everything. If a new name user supplied
;; exists as default-directory, Dired throws error when insert anything that
;; does not exist in current directory.
(with-current-buffer (dired (cons (make-temp-name new-name)
(if files
files
(list candidate))))
(when (get-buffer new-name)
(kill-buffer new-name))
(rename-buffer new-name)))))
(defun helm-projectile-dired-files-add-action (candidate)
"Add files to a Dired buffer.
CANDIDATE is the selected file. Used when no file is explicitly marked."
(if (and (file-remote-p (projectile-project-root))
(not helm-projectile-virtual-dired-remote-enable))
(message "Virtual Dired manager is disabled in remote host. Enable with %s."
(propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
(if (eq (with-helm-current-buffer major-mode) 'dired-mode)
(let* ((marked-files (helm-marked-candidates :with-wildcard t))
(helm--reading-passwd-or-string t)
(root (projectile-project-root)) ; store root for later use
(dired-buffer-name (or (and (eq major-mode 'dired-mode) (buffer-name))
(completing-read "Select a Dired buffer:"
(helm-projectile-all-dired-buffers))))
(dired-files (with-current-buffer dired-buffer-name
(helm-projectile-files-in-current-dired-buffer)))
(files (sort (mapcar (lambda (file)
(replace-regexp-in-string (projectile-project-root) "" file))
(cl-nunion (if marked-files
marked-files
(list candidate))
dired-files
:test #'string-equal))
'string-lessp)))
(kill-buffer dired-buffer-name)
;; Rebind default-directory because after killing a buffer, we
;; could be in any buffer and default-directory is set to that
;; random buffer
;;
;; Also use saved root directory, because after killing a buffer,
;; we could be outside of current project
(let ((default-directory root))
(with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
(if files
(mapcar (lambda (file)
(replace-regexp-in-string root "" file))
files)
(list candidate))))
(rename-buffer dired-buffer-name))))
(error "You're not in a Dired buffer to add"))))
(defun helm-projectile-dired-files-delete-action (candidate)
"Delete selected entries from a Dired buffer.
CANDIDATE is the selected file. Used when no file is explicitly marked."
(if (and (file-remote-p (projectile-project-root))
(not helm-projectile-virtual-dired-remote-enable))
(message "Virtual Dired manager is disabled in remote host. Enable with %s."
(propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
(let* ((helm--reading-passwd-or-string t)
(root (projectile-project-root))
(dired-buffer-name (with-helm-current-buffer (buffer-name)))
(dired-files (with-current-buffer dired-buffer-name
(helm-projectile-files-in-current-dired-buffer)))
(files (sort (cl-set-exclusive-or (helm-marked-candidates :with-wildcard t)
dired-files
:test #'string-equal) #'string-lessp)))
(kill-buffer dired-buffer-name)
;; similar reason to `helm-projectile-dired-files-add-action'
(let ((default-directory root))
(with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
(if files
(mapcar (lambda (file)
(replace-regexp-in-string root "" file))
files)
(list candidate))))
(rename-buffer dired-buffer-name))))))
(defvar helm-projectile-find-file-map
(let ((map (copy-keymap helm-find-files-map)))
(helm-projectile-define-key map
(kbd "C-c f") #'helm-projectile-dired-files-new-action
(kbd "C-c a") #'helm-projectile-dired-files-add-action
(kbd "M-e") #'helm-projectile-switch-to-eshell
(kbd "M-.") #'helm-projectile-ff-etags-select-action
(kbd "M-!") #'helm-projectile-find-files-eshell-command-on-file-action)
(define-key map (kbd "<left>") #'helm-previous-source)
(define-key map (kbd "<right>") #'helm-next-source)
map)
"Mapping for file commands in Helm Projectile.")
(defvar helm-projectile-file-actions
(helm-projectile-hack-actions
helm-find-files-actions
;; Delete these actions
'helm-ff-browse-project
'helm-insert-file-name-completion-at-point
'helm-ff-find-sh-command
'helm-ff-cache-add-file
;; Substitute these actions
'(helm-ff-switch-to-eshell . helm-projectile-switch-to-eshell)
'(helm-ff-etags-select . helm-projectile-ff-etags-select-action)
'(helm-find-files-eshell-command-on-file
. helm-projectile-find-files-eshell-command-on-file-action)
;; Change action descriptions
'(helm-find-file-as-root . "Find file as root `C-c r'")
;; New actions
'(helm-projectile-dired-files-new-action
. "Create Dired buffer from files `C-c f'")
'(helm-projectile-dired-files-add-action
. "Add files to Dired buffer `C-c a'"))
"Action for files.")
(defun helm-projectile-build-dwim-source (candidates)
"Dynamically build a Helm source definition for Projectile files based on context with CANDIDATES."
""
(helm-build-in-buffer-source "Projectile files"
:data candidates
:fuzzy-match helm-projectile-fuzzy-match
:coerce 'helm-projectile-coerce-file
:action-transformer 'helm-find-files-action-transformer
:keymap helm-projectile-find-file-map
:help-message helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-file-actions))
(defvar helm-source-projectile-files-list
(helm-build-in-buffer-source "Projectile files"
:data (lambda ()
(condition-case nil
(projectile-current-project-files)
(error nil)))
:fuzzy-match helm-projectile-fuzzy-match
:coerce 'helm-projectile-coerce-file
:keymap helm-projectile-find-file-map
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-file-actions
)
"Helm source definition for Projectile files.")
(defvar helm-source-projectile-files-in-all-projects-list
(helm-build-in-buffer-source "Projectile files in all Projects"
:data (lambda ()
(condition-case nil
(let ((projectile-require-project-root nil))
(projectile-all-project-files))
(error nil)))
:keymap helm-find-files-map
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-file-actions
)
"Helm source definition for all Projectile files in all projects.")
(defvar helm-projectile-dired-file-actions
(helm-projectile-hack-actions
helm-projectile-file-actions
;; New actions
'(helm-projectile-dired-files-delete-action . "Remove entry(s) from Dired buffer `C-c d'")))
(defvar helm-source-projectile-dired-files-list
(helm-build-in-buffer-source "Projectile files in current Dired buffer"
:data (lambda ()
(condition-case nil
(if (and (file-remote-p (projectile-project-root))
(not helm-projectile-virtual-dired-remote-enable))
nil
(let ((default-directory (projectile-project-root)))
(when (eq major-mode 'dired-mode)
(mapcar (lambda (file)
(replace-regexp-in-string default-directory "" file))
(helm-projectile-files-in-current-dired-buffer)))))
(error nil)))
:coerce 'helm-projectile-coerce-file
:filter-one-by-one (lambda (file)
(let ((default-directory (projectile-project-root)))
(helm-ff-filter-candidate-one-by-one file)))
:action-transformer 'helm-find-files-action-transformer
:keymap (let ((map (copy-keymap helm-projectile-find-file-map)))
(helm-projectile-define-key map
(kbd "C-c d") 'helm-projectile-dired-files-delete-action)
map)
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-dired-file-actions)
"Helm source definition for Projectile delete files.")
(defun helm-projectile-dired-find-dir (dir)
"Jump to a selected directory DIR from helm-projectile."
(dired (expand-file-name dir (projectile-project-root)))
(run-hooks 'projectile-find-dir-hook))
(defun helm-projectile-dired-find-dir-other-window (dir)
"Jump to a selected directory DIR from helm-projectile."
(dired-other-window (expand-file-name dir (projectile-project-root)))
(run-hooks 'projectile-find-dir-hook))
(defvar helm-source-projectile-directories-list
(helm-build-in-buffer-source "Projectile directories"
:data (lambda ()
(condition-case nil
(if projectile-find-dir-includes-top-level
(append '("./") (projectile-current-project-dirs))
(projectile-current-project-dirs))
(error nil)))
:fuzzy-match helm-projectile-fuzzy-match
:coerce 'helm-projectile-coerce-file
:action-transformer 'helm-find-files-action-transformer
:keymap (let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(helm-projectile-define-key map
(kbd "<left>") #'helm-previous-source
(kbd "<right>") #'helm-next-source
(kbd "C-c o") #'helm-projectile-dired-find-dir-other-window
(kbd "M-e") #'helm-projectile-switch-to-eshell
(kbd "C-c f") #'helm-projectile-dired-files-new-action
(kbd "C-c a") #'helm-projectile-dired-files-add-action
(kbd "C-s") #'helm-projectile-grep)
map)
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action '(("Open Dired" . helm-projectile-dired-find-dir)
("Open Dired in other window `C-c o'" . helm-projectile-dired-find-dir)
("Switch to Eshell `M-e'" . helm-projectile-switch-to-eshell)
("Grep in projects `C-s'" . helm-projectile-grep)
("Create Dired buffer from files `C-c f'" . helm-projectile-dired-files-new-action)
("Add files to Dired buffer `C-c a'" . helm-projectile-dired-files-add-action)))
"Helm source for listing project directories.")
(defvar helm-projectile-buffers-list-cache nil)
(defclass helm-source-projectile-buffer (helm-source-sync helm-type-buffer)
((init :initform (lambda ()
;; Issue #51 Create the list before `helm-buffer' creation.
(setq helm-projectile-buffers-list-cache (condition-case nil
(cdr (projectile-project-buffer-names))
(error nil)))
(let ((result (cl-loop for b in helm-projectile-buffers-list-cache
maximize (length b) into len-buf
maximize (length (with-current-buffer b
(symbol-name major-mode)))
into len-mode
finally return (cons len-buf len-mode))))
(unless helm-buffer-max-length
(setq helm-buffer-max-length (car result)))
(unless helm-buffer-max-len-mode
;; If a new buffer is longer that this value
;; this value will be updated
(setq helm-buffer-max-len-mode (cdr result))))))
(candidates :initform helm-projectile-buffers-list-cache)
(matchplugin :initform nil)
(match :initform 'helm-buffers-match-function)
(persistent-action :initform 'helm-buffers-list-persistent-action)
(keymap :initform helm-buffer-map)
(volatile :initform t)
(persistent-help
:initform
"Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))
(defvar helm-source-projectile-buffers-list (helm-make-source "Project buffers" 'helm-source-projectile-buffer))
(defvar helm-source-projectile-recentf-list
(helm-build-in-buffer-source "Projectile recent files"
:data (lambda ()
(condition-case nil
(projectile-recentf-files)
(error nil)))
:fuzzy-match helm-projectile-fuzzy-match
:coerce 'helm-projectile-coerce-file
:keymap helm-projectile-find-file-map
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-file-actions
)
"Helm source definition for recent files in current project.")
(defvar helm-source-projectile-files-and-dired-list
'(helm-source-projectile-dired-files-list
helm-source-projectile-files-list))
(defvar helm-source-projectile-directories-and-dired-list
'(helm-source-projectile-dired-files-list
helm-source-projectile-directories-list))
(defcustom helm-projectile-sources-list
'(helm-source-projectile-buffers-list
helm-source-projectile-files-list
helm-source-projectile-projects
)
"Default sources for `helm-projectile'."
:group 'helm-projectile)
(defmacro helm-projectile-command (command source prompt &optional not-require-root)
"Template for generic helm-projectile commands.
COMMAND is a command name to be appended with \"helm-projectile\" prefix.
SOURCE is a Helm source that should be Projectile specific.
PROMPT is a string for displaying as a prompt.
NOT-REQUIRE-ROOT specifies the command doesn't need to be used in a
project root."
`(defun ,(intern (concat "helm-projectile-" command)) (&optional arg)
"Use projectile with Helm for finding files in project
With a prefix ARG invalidates the cache first."
(interactive "P")
(if (projectile-project-p)
(projectile-maybe-invalidate-cache arg)
(unless ,not-require-root
(error "You're not in a project")))
(let ((helm-ff-transformer-show-only-basename nil)
;; for consistency, we should just let Projectile take care of ignored files
(helm-boring-file-regexp-list nil))
(helm :sources ,source
:buffer "*helm projectile*"
:prompt (projectile-prepend-project-name ,prompt)))))
(helm-projectile-command "switch-project" 'helm-source-projectile-projects "Switch to project: " t)
(helm-projectile-command "find-file" helm-source-projectile-files-and-dired-list "Find file: ")
(helm-projectile-command "find-file-in-known-projects" 'helm-source-projectile-files-in-all-projects-list "Find file in projects: " t)
(helm-projectile-command "find-dir" helm-source-projectile-directories-and-dired-list "Find dir: ")
(helm-projectile-command "recentf" 'helm-source-projectile-recentf-list "Recently visited file: ")
(helm-projectile-command "switch-to-buffer" 'helm-source-projectile-buffers-list "Switch to buffer: ")
;;;###autoload
(defun helm-projectile-find-file-dwim ()
"Find file at point based on context."
(interactive)
(let* ((project-files (projectile-current-project-files))
(files (projectile-select-files project-files)))
(if (= (length files) 1)
(find-file (expand-file-name (car files) (projectile-project-root)))
(helm :sources (helm-projectile-build-dwim-source (if (> (length files) 1)
files
project-files))
:buffer "*helm projectile*"
:prompt (projectile-prepend-project-name "Find file: ")))))
;;;###autoload
(defun helm-projectile-find-other-file (&optional flex-matching)
"Switch between files with the same name but different extensions using Helm.
With FLEX-MATCHING, match any file that contains the base name of current file.
Other file extensions can be customized with the variable `projectile-other-file-alist'."
(interactive "P")
(let ((other-files (projectile-get-other-files (buffer-file-name)
(projectile-current-project-files)
flex-matching)))
(if other-files
(if (= (length other-files) 1)
(find-file (expand-file-name (car other-files) (projectile-project-root)))
(progn
(let* ((helm-ff-transformer-show-only-basename nil))
(helm :sources (helm-build-in-buffer-source "Projectile other files"
:data other-files
:coerce 'helm-projectile-coerce-file
:keymap (let ((map (copy-keymap helm-find-files-map)))
(define-key map (kbd "<left>") 'helm-previous-source)
(define-key map (kbd "<right>") 'helm-next-source)
map)
:help-message helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-file-actions)
:buffer "*helm projectile*"
:prompt (projectile-prepend-project-name "Find other file: ")))))
(error "No other file found"))))
(defun helm-projectile-grep-or-ack (&optional dir use-ack-p ack-ignored-pattern ack-executable)
"Perform helm-grep at project root.
DIR directory where to search
USE-ACK-P indicates whether to use ack or not.
ACK-IGNORED-PATTERN is a file regex to exclude from searching.
ACK-EXECUTABLE is the actual ack binary name.
It is usually \"ack\" or \"ack-grep\".
If it is nil, or ack/ack-grep not found then use default grep command."
(let* ((default-directory (or dir (projectile-project-root)))
(helm-ff-default-directory default-directory)
(follow (and helm-follow-mode-persistent
(assoc-default 'follow helm-source-grep)))
(helm-grep-in-recurse t)
(helm-grep-ignored-files (cl-union (projectile-ignored-files-rel) grep-find-ignored-files))
(helm-grep-ignored-directories
(cl-union (mapcar 'directory-file-name (projectile-ignored-directories-rel))
grep-find-ignored-directories))
(helm-grep-default-command (if use-ack-p
(concat ack-executable " -H --no-group --no-color " ack-ignored-pattern " %p %f")
(if (and projectile-use-git-grep (eq (projectile-project-vcs) 'git))
"git --no-pager grep --no-color -n%c -e %p -- %f"
"grep -a -r %e -n%cH -e %p %f .")))
(helm-grep-default-recurse-command helm-grep-default-command))
(setq helm-source-grep
(helm-build-async-source
(capitalize (helm-grep-command t))
:header-name (lambda (name)
(let ((name (if use-ack-p
"Helm Projectile Ack"
"Helm Projectile Grep")))
(concat name " " "(C-c ? Help)")))
:candidates-process 'helm-grep-collect-candidates
:filter-one-by-one 'helm-grep-filter-one-by-one
:candidate-number-limit 9999
:nohighlight t
;; We need to specify keymap here and as :keymap arg [1]
;; to make it available in further resuming.
:keymap helm-grep-map
:history 'helm-grep-history
:action (helm-make-actions
"Find file" 'helm-grep-action
"Find file other frame" 'helm-grep-other-frame
(lambda () (and (locate-library "elscreen")
"Find file in Elscreen"))
'helm-grep-jump-elscreen
"Save results in grep buffer" 'helm-grep-save-results
"Find file other window" 'helm-grep-other-window)
:persistent-action 'helm-grep-persistent-action
:persistent-help "Jump to line (`C-u' Record in mark ring)"
:requires-pattern 2))
(helm
:sources 'helm-source-grep
:input (if (region-active-p)
(buffer-substring-no-properties (region-beginning) (region-end))
(thing-at-point 'symbol))
:buffer (format "*helm %s*" (if use-ack-p
"ack"
"grep"))
:default-directory default-directory
:keymap helm-grep-map
:history 'helm-grep-history
:truncate-lines t)))
;;;###autoload
(defun helm-projectile-on ()
"Turn on helm-projectile key bindings."
(interactive)
(message "Turn on helm-projectile key bindings")
(helm-projectile-toggle 1))
;;;###autoload
(defun helm-projectile-off ()
"Turn off helm-projectile key bindings."
(interactive)
(message "Turn off helm-projectile key bindings")
(helm-projectile-toggle -1))
;;;###autoload
(defun helm-projectile-grep (&optional dir)
"Helm version of `projectile-grep'.
DIR is the project root, if not set then current directory is used"
(interactive)
(let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
(funcall'run-with-timer 0.01 nil
#'helm-projectile-grep-or-ack project-root nil)))
;;;###autoload
(defun helm-projectile-ack (&optional dir)
"Helm version of projectile-ack."
(interactive)
(let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
(let ((ack-ignored (mapconcat
'identity
(cl-union (mapcar (lambda (path)
(concat "--ignore-dir=" (file-name-nondirectory (directory-file-name path))))
(projectile-ignored-directories))
(mapcar (lambda (path)
(concat "--ignore-file=match:" (shell-quote-argument path)))
(append (projectile-ignored-files) (projectile-patterns-to-ignore)))) " "))
(helm-ack-grep-executable (cond
((executable-find "ack") "ack")
((executable-find "ack-grep") "ack-grep")
(t (error "ack or ack-grep is not available.")))))
(funcall 'run-with-timer 0.01 nil
#'helm-projectile-grep-or-ack project-root t ack-ignored helm-ack-grep-executable))))
;;;###autoload
(defun helm-projectile-ag (&optional options)
"Helm version of projectile-ag."
(interactive (if current-prefix-arg (list (read-string "option: " "" 'helm-ag--extra-options-history))))
(if (require 'helm-ag nil 'noerror)
(if (projectile-project-p)
(let* ((grep-find-ignored-files (cl-union (projectile-ignored-files-rel) grep-find-ignored-files))
(grep-find-ignored-directories (cl-union (projectile-ignored-directories-rel) grep-find-ignored-directories))
(ignored (mapconcat (lambda (i)
(concat "--ignore " i))
(append grep-find-ignored-files grep-find-ignored-directories)
" "))
(helm-ag-command-option options)
(helm-ag-base-command (concat helm-ag-base-command " " ignored))
(current-prefix-arg nil))
(helm-do-ag (projectile-project-root) (car (projectile-parse-dirconfig-file))))
(error "You're not in a project"))
(error "helm-ag not available")))
(defun helm-projectile-commander-bindings ()
(def-projectile-commander-method ?a
"Run ack on project."
(call-interactively 'helm-projectile-ack))
(def-projectile-commander-method ?A
"Find ag on project."
(call-interactively 'helm-projectile-ag))
(def-projectile-commander-method ?f
"Find file in project."
(helm-projectile-find-file))
(def-projectile-commander-method ?b
"Switch to project buffer."
(helm-projectile-switch-to-buffer))
(def-projectile-commander-method ?d
"Find directory in project."
(helm-projectile-find-dir))
(def-projectile-commander-method ?g
"Run grep on project."
(helm-projectile-grep))
(def-projectile-commander-method ?s
"Switch project."
(helm-projectile-switch-project))
(def-projectile-commander-method ?e
"Find recently visited file in project."
(helm-projectile-recentf)))
;;;###autoload
(defun helm-projectile-toggle (toggle)
"Toggle Helm version of Projectile commands."
(if (> toggle 0)
(progn
(when (eq projectile-switch-project-action #'projectile-find-file)
(setq projectile-switch-project-action #'helm-projectile-find-file))
(define-key projectile-mode-map [remap projectile-find-other-file] #'helm-projectile-find-other-file)
(define-key projectile-mode-map [remap projectile-find-file] #'helm-projectile-find-file)
(define-key projectile-mode-map [remap projectile-find-file-in-known-projects] #'helm-projectile-find-file-in-known-projects)
(define-key projectile-mode-map [remap projectile-find-file-dwim] #'helm-projectile-find-file-dwim)
(define-key projectile-mode-map [remap projectile-find-dir] #'helm-projectile-find-dir)
(define-key projectile-mode-map [remap projectile-switch-project] #'helm-projectile-switch-project)
(define-key projectile-mode-map [remap projectile-recentf] #'helm-projectile-recentf)
(define-key projectile-mode-map [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer)
(define-key projectile-mode-map [remap projectile-grep] #'helm-projectile-grep)
(define-key projectile-mode-map [remap projectile-ack] #'helm-projectile-ack)
(define-key projectile-mode-map [remap projectile-ag] #'helm-projectile-ag)
(helm-projectile-commander-bindings))
(progn
(when (eq projectile-switch-project-action #'helm-projectile-find-file)
(setq projectile-switch-project-action #'projectile-find-file))
(define-key projectile-mode-map [remap projectile-find-other-file] nil)
(define-key projectile-mode-map [remap projectile-find-file] nil)
(define-key projectile-mode-map [remap projectile-find-file-in-known-projects] nil)
(define-key projectile-mode-map [remap projectile-find-file-dwim] nil)
(define-key projectile-mode-map [remap projectile-find-dir] nil)
(define-key projectile-mode-map [remap projectile-switch-project] nil)
(define-key projectile-mode-map [remap projectile-recentf] nil)
(define-key projectile-mode-map [remap projectile-switch-to-buffer] nil)
(define-key projectile-mode-map [remap projectile-grep] nil)
(define-key projectile-mode-map [remap projectile-ag] nil)
(projectile-commander-bindings))))
;;;###autoload
(defun helm-projectile (&optional arg)
"Use projectile with Helm instead of ido.
With a prefix ARG invalidates the cache first.
If invoked outside of a project, displays a list of known projects to jump."
(interactive "P")
(if (projectile-project-p)
(projectile-maybe-invalidate-cache arg))
(let ((helm-ff-transformer-show-only-basename nil))
(helm :sources helm-projectile-sources-list
:buffer "*helm projectile*"
:prompt (projectile-prepend-project-name (if (projectile-project-p)
"pattern: "
"Switch to project: ")))))
;;;###autoload
(eval-after-load 'projectile
'(progn
(define-key projectile-command-map (kbd "h") #'helm-projectile)))
(provide 'helm-projectile)
;;; helm-projectile.el ends here

View File

@ -0,0 +1,47 @@
;;; org-projectile-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
;;;### (autoloads nil "org-projectile" "org-projectile.el" (22490
;;;;;; 46092 579337 228000))
;;; Generated autoloads from org-projectile.el
(autoload 'org-projectile:toggle-subheading "org-projectile" "\
Toggle subheading setting for heading at point.
When a heading is considered a subheading it will appear in
org-projectile search commands.
\(fn)" t nil)
(autoload 'org-projectile:template-or-project "org-projectile" "\
Select a project or org capture template and record a TODO.
If ARG is provided use `org-projectile:linked-capture-template'
as the capture template.
\(fn &optional ARG)" t nil)
(autoload 'org-projectile:project-todo-completing-read "org-projectile" "\
Select a project using a `projectile-completing-read' and record a TODO.
If CAPTURE-TEMPLATE is provided use it as the capture template for the TODO.
\(fn &optional CAPTURE-TEMPLATE &rest ADDITIONAL-OPTIONS)" t nil)
(autoload 'org-projectile:capture-for-current-project "org-projectile" "\
Capture a TODO for the current active projectile project.
If CAPTURE-TEMPLATE is provided use it as the capture template for the TODO.
\(fn &optional CAPTURE-TEMPLATE &rest ADDITIONAL-OPTIONS)" t nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; org-projectile-autoloads.el ends here

View File

@ -0,0 +1 @@
(define-package "org-projectile" "20160822.2123" "Repository todo management for org-mode" '((projectile "0.11.0") (dash "2.10.0") (emacs "24")) :url "https://github.com/IvanMalison/org-projectile" :keywords '("org" "projectile" "todo"))

View File

@ -0,0 +1,559 @@
;;; org-projectile.el --- Repository todo management for org-mode -*- lexical-binding: t; -*-
;; Copyright (C) 2014-2016 Ivan Malison
;; Author: Ivan Malison <IvanMalison@gmail.com>
;; Keywords: org projectile todo
;; Package-Version: 20160822.2123
;; URL: https://github.com/IvanMalison/org-projectile
;; Version: 0.2.1
;; Package-Requires: ((projectile "0.11.0") (dash "2.10.0") (emacs "24"))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This package aims to provide an easy interface to creating per
;; project org-mode TODO headings.
;;; Code:
(require 'cl-lib)
(require 'org-capture)
(require 'projectile)
(defvar org-projectile:projects-file "~/org/projects.org")
(defvar org-projectile:per-repo-filename "todo.org")
(defvar org-projectile:capture-template "* TODO %?\n")
(defvar org-projectile:linked-capture-template "* TODO %? %A\n")
(defvar org-projectile:force-linked t)
(defvar org-projectile:counts-in-heading t)
(defvar org-projectile:subheading-selection t)
(defvar org-projectile:project-name-to-org-file
'org-projectile:project-name-to-org-file-one-file)
(defvar org-projectile:project-name-to-location
'org-projectile:project-name-to-location-one-file)
(defvar org-projectile:todo-files 'org-projectile:default-todo-files)
;; For a single projects file
(defun org-projectile:project-name-to-org-file-one-file (_project-name)
org-projectile:projects-file)
(defun org-projectile:project-name-to-location-one-file (project-name)
(org-projectile:project-heading project-name)
(when org-projectile:subheading-selection
(org-projectile:prompt-for-subheadings 'tree))
t)
(defun org-projectile:one-file ()
"Use org-projectile in one-file mode."
(interactive)
(setq org-projectile:todo-files 'org-projectile:default-todo-files)
(setq org-projectile:project-name-to-org-file
'org-projectile:project-name-to-org-file-one-file)
(setq org-projectile:project-name-to-location
'org-projectile:project-name-to-location-one-file))
;; For repo files in the projectile project path
(defun org-projectile:project-name-to-org-file-per-repo (project-name)
(concat (org-projectile:project-location-from-name project-name)
org-projectile:per-repo-filename))
(defun org-projectile:project-name-to-location-per-repo (_project-name)
(goto-char (point-max))
nil)
(defun org-projectile:per-repo ()
"Use org-projectile in per-repo mode."
(interactive)
(setq org-projectile:todo-files 'org-projectile:default-todo-files)
(setq org-projectile:project-name-to-org-file
'org-projectile:project-name-to-org-file-per-repo)
(setq org-projectile:project-name-to-location
'org-projectile:project-name-to-location-per-repo))
;; Hybrid of the two approaches mentioned above
(defvar org-projectile:project-to-approach nil)
(defvar org-projectile:default-approach 'one-file)
(defun org-projectile:get-approach-for-project (project-name)
(or (cdr (assoc project-name org-projectile:project-to-approach))
org-projectile:default-approach))
(defun org-projectile:project-name-to-org-file-hybrid (project-name)
(let ((approach (org-projectile:get-approach-for-project project-name)))
(cond
((equal approach 'one-file)
(org-projectile:project-name-to-org-file-one-file project-name))
((equal approach 'per-repo)
(org-projectile:project-name-to-org-file-per-repo project-name)))))
(defun org-projectile:project-name-to-location-hybrid (project-name)
(let ((approach (org-projectile:get-approach-for-project project-name)))
(cond
((equal approach 'one-file)
(org-projectile:project-name-to-location-one-file project-name))
((equal approach 'per-repo)
(org-projectile:project-name-to-location-per-repo project-name)))))
(defun org-projectile:hybrid ()
"Use org-projectile in hybrid mode."
(interactive)
(setq org-projectile:todo-files 'org-projectile:default-todo-files)
(setq org-projectile:project-name-to-org-file
'org-projectile:project-name-to-org-file-hybrid)
(setq org-projectile:project-name-to-location
'org-projectile:project-name-to-location-hybrid))
;; Prompt for org file location on a per project basis
(defvar org-projectile:find-org-file-for-project-function nil)
(defvar org-projectile:keep-project-to-org-filepath-in-memory nil)
(defvar org-projectile:project-to-org-filepath 'not-yet-read)
(defvar org-projectile:project-to-org-filepath-filepath
(concat (file-name-as-directory user-emacs-directory) "project-to-org-filepath"))
(defun org-projectile:write-project-to-org-filepath
(project-to-org-filepath &optional project-to-org-filepath-filepath)
(unless project-to-org-filepath-filepath
(setq project-to-org-filepath-filepath
org-projectile:project-to-org-filepath-filepath))
(with-temp-buffer
(insert (prin1-to-string project-to-org-filepath))
(write-region (point-min) (point-max) project-to-org-filepath-filepath nil)))
(defun org-projectile:read-project-to-org-filepath
(&optional project-to-org-filepath-filepath)
(unless project-to-org-filepath-filepath
(setq project-to-org-filepath-filepath
org-projectile:project-to-org-filepath-filepath))
(when (file-exists-p project-to-org-filepath-filepath)
(with-temp-buffer
(insert-file-contents project-to-org-filepath-filepath)
(read (buffer-string)))))
(defun org-projectile:update-project-to-org-filepath
(project-name org-file &optional project-to-org-filepath-filepath)
(let* ((project-to-org-filepath (org-projectile:get-project-to-org-filepath
project-to-org-filepath-filepath))
(org-file-truename (org-projectile:file-truename org-file))
(current-value (assoc project-name project-to-org-filepath)))
(when (or (not (file-exists-p org-file-truename)) (file-directory-p org-file-truename))
(throw "The provided filepath is invalid" org-file))
(if current-value
(setcdr current-value org-file-truename)
(push (cons project-name org-file-truename)
project-to-org-filepath))
(org-projectile:write-project-to-org-filepath
project-to-org-filepath project-to-org-filepath-filepath)))
(defun org-projectile:get-project-to-org-filepath
(&optional project-to-org-filepath-filepath)
(if org-projectile:keep-project-to-org-filepath-in-memory
(if (eq org-projectile:project-to-org-filepath 'not-yet-read)
(progn
(setq org-projectile:project-to-org-filepath
(org-projectile:read-project-to-org-filepath
project-to-org-filepath-filepath)))
org-projectile:project-to-org-filepath)
(org-projectile:read-project-to-org-filepath
project-to-org-filepath-filepath)))
(defun org-projectile:project-name-to-org-file-prompt
(project-name &optional project-to-org-filepath-filepath)
(let ((current (assoc project-name (org-projectile:get-project-to-org-filepath))))
(if current (cdr current)
(let ((org-filepath (org-projectile:find-project-in-known-files project-name)))
(unless org-filepath
(setq org-filepath
(org-projectile:no-org-file-for-project project-name
project-to-org-filepath-filepath)))
(org-projectile:update-project-to-org-filepath project-name org-filepath) org-filepath))))
(defun org-projectile:no-org-file-for-project
(project-name &optional project-to-org-filepath-filepath)
(let ((org-filepath (when org-projectile:find-org-file-for-project-function
(funcall
org-projectile:find-org-file-for-project-function
project-name))))
(unless org-filepath
(setq org-filepath (org-projectile:prompt-for-project-name
project-name project-to-org-filepath-filepath)))
org-filepath))
(defun org-projectile:prompt-for-project-name
(project-name &optional _project-to-org-filepath-filepath)
(read-file-name (concat "org-mode file for " project-name ": ")
(file-name-directory org-projectile:projects-file)))
(defun org-projectile:set-project-file-default
(&optional project-to-org-filepath-filepath)
"Set the filepath for any known projects that do not have a filepath.
If PROJECT-TO-ORG-FILEPATH-FILEPATH is provided use that as the
location of the filepath cache."
(interactive)
(let ((org-filepath
(read-file-name "org-mode file: "
(file-name-directory org-projectile:projects-file))))
(cl-loop for project-name being the elements of (org-projectile:known-projects)
do (org-projectile:update-project-to-org-filepath
project-name org-filepath project-to-org-filepath-filepath))
org-filepath))
(defun org-projectile:find-project-in-known-files (project-name)
(cl-loop for org-file in (funcall org-projectile:todo-files) when
(-contains-p
(org-map-entries (lambda ()
(org-projectile:get-link-description
(nth 4 (org-heading-components)))) nil
(list org-file)
(lambda ()
(when (< 1 (nth 1 (org-heading-components)))
(point)))) project-name)
return org-file))
(fset 'org-projectile:project-name-to-location-prompt
'org-projectile:project-name-to-location-one-file)
(defun org-projectile:todo-files-project-to-org-filepath ()
(delete-dups
(cl-loop for elem in (org-projectile:get-project-to-org-filepath)
collect (cdr elem))))
(defun org-projectile:set-org-file-for-project ()
"Set the org file to use for a projectile project."
(interactive)
(org-projectile:update-project-to-org-filepath
(org-projectile:prompt-for-project-name
(projectile-completing-read "Select project for which to set org file: "
(org-projectile:known-projects)))
(read-file-name "Select an org file: ")))
(defun org-projectile:prompt ()
"Use the prompt mode of org-projectile."
(interactive)
(setq org-projectile:todo-files
'org-projectile:todo-files-project-to-org-filepath)
(setq org-projectile:project-name-to-org-file
'org-projectile:project-name-to-org-file-prompt)
(setq org-projectile:project-name-to-location
'org-projectile:project-name-to-location-prompt))
(defun org-projectile:location-for-project (project-name)
(let* ((filename (funcall org-projectile:project-name-to-org-file project-name)))
(switch-to-buffer (find-file-noselect filename))
(funcall org-projectile:project-name-to-location project-name)))
(defun org-projectile:target-subheading-and-return-marker ()
(org-end-of-line)
(org-projectile:end-of-properties)
;; It sucks that this has to be done, but we have to insert a
;; subheading if the entry does not have one in order to convince
;; capture to actually insert the template as a subtree of the
;; selected entry. We return a marker where the dummy subheading
;; was created so that it can be deleted later.
(when (not (save-excursion (org-goto-first-child)))
(save-excursion (org-insert-subheading nil) (point-marker))))
(defun org-projectile:file-truename (filepath)
(when filepath
(if (find-file-name-handler filepath 'file-truename)
filepath ;; skip if the file requires special handling
(file-truename filepath))))
(defun org-projectile:project-root-of-filepath (filepath)
(org-projectile:file-truename
(let ((dir (file-name-directory filepath)))
(--some (let* ((cache-key (format "%s-%s" it dir))
(cache-value (gethash
cache-key projectile-project-root-cache)))
(if cache-value
cache-value
(let ((value (funcall it (org-projectile:file-truename dir))))
(puthash cache-key value projectile-project-root-cache)
value)))
projectile-project-root-files-functions))))
(defun org-projectile:project-todo-entry
(&optional capture-character capture-template capture-heading
&rest additional-options)
(unless capture-template (setq capture-template
org-projectile:capture-template))
(unless capture-character (setq capture-character "p"))
(unless capture-heading (setq capture-heading "Project Todo"))
`(,capture-character ,capture-heading entry
(function
(lambda () (org-projectile:location-for-project
(org-projectile:project-heading-from-file
(org-capture-get :original-file)))))
,capture-template ,@additional-options))
(defun org-projectile:project-heading-from-file (filename)
(let ((project-root (org-projectile:project-root-of-filepath filename)))
(when project-root
(file-name-nondirectory
(directory-file-name project-root)))))
(defun org-projectile:get-link-description (heading)
(with-temp-buffer
(insert heading)
(goto-char (point-min))
(if (re-search-forward org-any-link-re nil t)
(match-string-no-properties 4) heading)))
(defun org-projectile:known-projects ()
(remove-if
#'null
(delete-dups
`(,@(mapcar #'org-projectile:project-heading-from-file
(projectile-relevant-known-projects))
,@(org-map-entries
(lambda () (org-projectile:get-link-description
(nth 4 (org-heading-components)))) nil
(funcall org-projectile:todo-files)
(lambda ()
(when (< 1 (nth 1 (org-heading-components)))
(point))))))))
(defun org-projectile:todo-files ()
(funcall org-projectile:todo-files))
(defun org-projectile:default-todo-files ()
(cl-remove-if-not
#'file-exists-p
(delete-dups
(cl-loop for project-name in
(mapcar #'org-projectile:project-heading-from-file
(projectile-relevant-known-projects))
collect (funcall org-projectile:project-name-to-org-file
project-name)))))
(defun org-projectile:project-name-to-location-alist ()
(cl-loop for project-location in projectile-known-projects
collect `(,(file-name-nondirectory
(directory-file-name project-location)) .
,project-location)))
(defun org-projectile:project-location-from-name (name)
(cdr (assoc name (org-projectile:project-name-to-location-alist))))
(defvar dired-buffers)
(defun org-projectile:capture-for-project
(project-name &optional capture-template &rest additional-options)
(org-capture-set-plist
(apply #'org-projectile:project-todo-entry
nil capture-template nil additional-options))
;; TODO: super gross that this had to be copied from org-capture,
;; Unfortunately, it does not seem to be possible to call into org-capture
;; because it makes assumptions that make it impossible to set things up
;; properly
(let ((orig-buf (current-buffer))
(annotation (if (and (boundp 'org-capture-link-is-already-stored)
org-capture-link-is-already-stored)
(plist-get org-store-link-plist :annotation)
(ignore-errors (org-store-link nil))))
org-projectile:subheading-cleanup-marker
org-projectile:do-target-entry)
(org-capture-put :original-buffer orig-buf
:original-file (or (buffer-file-name orig-buf)
(and (featurep 'dired)
(car (rassq orig-buf dired-buffers))))
:original-file-nondirectory
(and (buffer-file-name orig-buf)
(file-name-nondirectory
(buffer-file-name orig-buf)))
:annotation annotation
:initial ""
:return-to-wconf (current-window-configuration)
:default-time
(or org-overriding-default-time
(org-current-time)))
(org-capture-put :template (org-capture-fill-template capture-template))
(org-capture-set-target-location
`(function ,(lambda () (setq org-projectile:do-target-entry
(org-projectile:location-for-project project-name)))))
;; Apparently this needs to be forced because (org-at-heading-p)
;; will not be true and so `org-capture-set-target-location` will
;; set this value to nil.
;; TODO(@IvanMalison): Perhaps there is a better way to do this?
;; Maybe something that would allow us to get rid of the horrible
;; subheading-cleanup-marker hack?
(org-capture-put :target-entry-p org-projectile:do-target-entry)
(when org-projectile:do-target-entry
(setq org-projectile:subheading-cleanup-marker
(org-projectile:target-subheading-and-return-marker)))
(org-capture-place-template)
(when org-projectile:subheading-cleanup-marker
(org-projectile:cleanup-subheading
org-projectile:subheading-cleanup-marker))))
(defun org-projectile:cleanup-subheading (marker)
(with-current-buffer (marker-buffer marker)
(save-excursion (goto-char (marker-position marker))
(kill-whole-line))))
(defun org-projectile:open-project (name)
(let* ((name-to-location (org-projectile:project-name-to-location-alist))
(entry (assoc name name-to-location)))
(when entry
(projectile-switch-project-by-name (cdr entry)))))
(defun org-projectile:insert-or-goto-heading (heading)
(goto-char (point-min))
(unless (derived-mode-p 'org-mode)
(error
"Target buffer \"%s\" for file+headline should be in Org mode"
(current-buffer)))
(let ((linked-heading (org-projectile:linked-heading heading)))
(if (re-search-forward
(format org-complex-heading-regexp-format
(format "%s\\|%s" (regexp-quote linked-heading)
(regexp-quote heading)))
nil t)
(progn
(goto-char (point-at-bol))
(when (and org-projectile:force-linked
(looking-at
(format org-complex-heading-regexp-format
(regexp-quote heading))))
(re-search-forward heading)
(org-show-subtree)
(delete-char (* (length heading) -1))
(insert linked-heading)
(goto-char (point-at-bol))))
(progn
(goto-char (point-max))
(or (bolp) (insert "\n"))
(let ((org-insert-heading-respect-content t))
(org-insert-heading nil nil t))
(insert linked-heading)
(when org-projectile:counts-in-heading (insert " [/]"))))
(nth 4 (org-heading-components))))
(defun org-projectile:linked-heading (heading)
(org-make-link-string
(format "elisp:(org-projectile:open-project \"%s\")" heading) heading))
(defun org-projectile:project-heading (heading)
(let ((heading-text (org-projectile:insert-or-goto-heading heading)))
(hide-subtree)
(org-beginning-of-line)
(org-set-property "CATEGORY" heading)
heading-text))
(defun org-projectile:end-of-properties ()
(let ((end-of-heading (save-excursion (outline-next-heading) (point)))
(last-match t))
(while last-match (setq last-match
(re-search-forward ":END:" end-of-heading t)))
(point)))
(defun org-projectile:prompt-for-subheadings (&optional recursive)
(let ((subheadings-to-point (org-projectile:get-subheadings))
(point-at-start (save-excursion (org-back-to-heading) (point))))
(when (> (length subheadings-to-point) 1)
(org-projectile:prompt-for-and-move-to-subheading subheadings-to-point)
(when recursive
(unless (eq point-at-start (save-excursion (org-back-to-heading) (point)))
(org-projectile:prompt-for-subheadings))))))
;; Only define the following functions if helm is installed
(when (require 'helm-source nil 'noerror)
(defun org-projectile:prompt-for-and-move-to-subheading (subheadings-to-point)
(cond ((eq projectile-completion-system 'helm)
(let ((selection
(helm :sources (org-projectile:helm-subheadings-source
subheadings-to-point))))
(goto-char selection)))))
(defun org-projectile:helm-subheadings-source (subheadings-to-point)
(helm-build-sync-source "Choose a subheading:"
:candidates subheadings-to-point))
(defun org-projectile:helm-source (&optional capture-template)
(helm-build-sync-source "Org Capture Options:"
:candidates (cl-loop for project in (org-projectile:known-projects)
collect `(,project . ,project))
:action `(("Do capture" .
,(lambda (project)
(org-projectile:capture-for-project
project capture-template)))))))
(defun org-projectile:get-subheadings (&optional scope)
(unless scope (setq scope 'tree))
(org-show-subtree)
(save-excursion
(org-map-entries (lambda () `(,(org-get-heading) . ,(point))) nil scope
(lambda () (when (and (nth 2 (org-heading-components))
(not (org-entry-get nil "ORG-PROJECTILE-SUBHEADINGS")))
(org-end-of-subtree))))))
;;;###autoload
(defun org-projectile:toggle-subheading ()
"Toggle subheading setting for heading at point.
When a heading is considered a subheading it will appear in
org-projectile search commands."
(interactive)
(let ((was-enabled (org-entry-get nil "ORG-PROJECTILE-SUBHEADINGS")))
(if was-enabled
(org-delete-property "ORG-PROJECTILE-SUBHEADINGS")
(org-set-property "ORG-PROJECTILE-SUBHEADINGS" "t"))))
;;;###autoload
(defun org-projectile:template-or-project (&optional arg)
"Select a project or org capture template and record a TODO.
If ARG is provided use `org-projectile:linked-capture-template'
as the capture template."
(interactive "P")
(if (require 'helm-org nil 'noerror)
(helm :sources
(list (helm-source-org-capture-templates)
(org-projectile:helm-source
(if arg org-projectile:linked-capture-template nil)))
:candidate-number-limit 99999
:buffer "*helm org capture templates*")
(user-error "%s" "This command is only available to helm users. Install helm and try again.")))
;;;###autoload
(defun org-projectile:project-todo-completing-read
(&optional capture-template &rest additional-options)
"Select a project using a `projectile-completing-read' and record a TODO.
If CAPTURE-TEMPLATE is provided use it as the capture template for the TODO."
(interactive)
(apply
#'org-projectile:capture-for-project
(projectile-completing-read "Record TODO for project: "
(org-projectile:known-projects))
capture-template additional-options))
;;;###autoload
(defun org-projectile:capture-for-current-project
(&optional capture-template &rest additional-options)
"Capture a TODO for the current active projectile project.
If CAPTURE-TEMPLATE is provided use it as the capture template for the TODO."
(interactive)
(let ((project-name (projectile-project-name)))
(if (projectile-project-p)
(apply #'org-projectile:capture-for-project
project-name capture-template additional-options)
(error (format "%s is not a recognized projectile project." project-name)))))
(provide 'org-projectile)
;;; org-projectile.el ends here

View File

@ -0,0 +1,16 @@
;;; projectile-direnv-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
;;;### (autoloads nil nil ("projectile-direnv.el") (22490 46091 998412
;;;;;; 740000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; projectile-direnv-autoloads.el ends here

View File

@ -0,0 +1 @@
(define-package "projectile-direnv" "20160305.1738" "Set environment variables from .envrc" '((emacs "24") (s "1.11.0") (dash "2.12.0") (projectile "0.13.0")) :url "https://github.com/christianromney/projectile-direnv" :keywords '("convenience"))

View File

@ -0,0 +1,81 @@
;;; projectile-direnv.el --- Set environment variables from .envrc -*- lexical-binding: t; -*-
;; Copyright (C) 2016 Free Software Foundation, Inc.
;; Author: Christian Romney <crommney@pointslope.com>
;; URL: https://github.com/christianromney/projectile-direnv
;; Package-Version: 20160305.1738
;; Keywords: convenience
;; Version: 0.1.0
;; Package-Requires: ((emacs "24") (s "1.11.0") (dash "2.12.0") (projectile "0.13.0"))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; I want to launch Emacs as a GUI and have it automatically
;; set the same environment variables that direnv sets for me
;; at the shell when I am in a Projectile project.
;;
;; See README.org for more info.
;;
;;; Code:
(require 's)
(require 'dash)
(require 'projectile)
(defvar projectile-direnv-envrc nil
"Contains the path to the last loaded .envrc")
(defun projectile-direnv-parse-export (line)
"Parses a single line of the form export VAR=VAL into a cons
cell where the car is the var name and the cdr is its value."
(let* ((parts (s-split "=" line))
(varname (car (last (s-split " " (car parts)))))
(varval (car (last parts))))
(cons varname varval)))
(defun projectile-direnv-read-file-as-string (filename)
"Returns a the file's contents as a string"
(with-temp-buffer
(insert-file-contents filename)
(buffer-string)))
(defun projectile-direnv-set-env-var (pair)
"Sets an environment variable. Expects a pair of (VARNAME . VALUE)"
(setenv (car pair) (cdr pair)))
(defun projectile-direnv-list-exports (exports)
"Returns a string of the form '+VAR1 +VAR2' listing the exported envvars"
(s-join " " (-map (lambda (e) (s-append (car e) "+")) exports)))
(defun projectile-direnv-export-variables ()
"Reads a .envrc file in the Projectile project root, and sets
environment variables for any defined exports"
(interactive)
(when (projectile-project-p)
(let ((envrc (expand-file-name ".envrc" (projectile-project-root))))
(when (and (file-exists-p envrc)
(not (string= envrc projectile-direnv-envrc)))
(let* ((contents (projectile-direnv-read-file-as-string envrc))
(lines (s-split "\n" contents))
(exports (-filter (lambda (l) (s-starts-with? "export" l)) lines))
(envvars (-map #'projectile-direnv-parse-export exports)))
(setq projectile-direnv-envrc envrc)
(-each envvars #'projectile-direnv-set-env-var)
(message "projectile-direnv: export %s" (projectile-direnv-list-exports envvars)))))))
(provide 'projectile-direnv)
;;; projectile-direnv.el ends here