diff options
-rw-r--r-- | init.el | 5 | ||||
-rw-r--r-- | lisp/general.el | 11 | ||||
-rw-r--r-- | lisp/lisp.el | 12 | ||||
-rw-r--r-- | lisp/neotree.el | 2226 |
4 files changed, 23 insertions, 2231 deletions
@@ -14,7 +14,7 @@ (setq package-list - '(good-scroll counsel smartparens xref-js2 eglot json-mode markdown-mode emojify tern rtags cmake-ide cmake-mode tide auctex evil js2-highlight-vars ac-js2 js2-refactor js2-mode flycheck-irony company-irony all-the-icons req-package projectile irony org)) + '(good-scroll counsel smartparens xref-js2 eglot json-mode markdown-mode emojify tern rtags cmake-ide cmake-mode tide auctex evil js2-highlight-vars ac-js2 js2-refactor js2-mode flycheck-irony company-irony all-the-icons req-package projectile irony org neotree)) ;; Fetch the list of packages available (unless package-archive-contents @@ -50,6 +50,7 @@ (require 'web) (require 'json) (require 'markdown) +(require 'lisp) (custom-set-variables ;; custom-set-variables was added by Custom. @@ -61,7 +62,7 @@ '(org-agenda-files (list org-directory)) '(org-directory "~/Documents/org") '(package-selected-packages - '(good-scroll counsel ## smartparens xref-js2 eglot json-mode markdown-mode emojify tern rtags cmake-ide cmake-mode tide auctex evil js2-highlight-vars ac-js2 js2-refactor js2-mode flycheck-irony company-irony all-the-icons req-package projectile irony org))) + '(neotree good-scroll counsel ## smartparens xref-js2 eglot json-mode markdown-mode emojify tern rtags cmake-ide cmake-mode tide auctex evil js2-highlight-vars ac-js2 js2-refactor js2-mode flycheck-irony company-irony all-the-icons req-package projectile irony org))) ;;; init.el ends here (custom-set-faces diff --git a/lisp/general.el b/lisp/general.el index 5945db0..1a94675 100644 --- a/lisp/general.el +++ b/lisp/general.el @@ -55,6 +55,7 @@ ;; Tree (require 'neotree) +(require 'evil) (setq neo-smart-open t) ;;(setq projectile-switch-project-action 'neotree-projectile-action) (setq neo-theme (if (display-graphic-p) 'icons 'arrow)) @@ -95,12 +96,14 @@ (bind-key* (kbd "C-c e") #'emojify-insert-emoji)) ; override binding in any mode ;; Global key binds +(require 'eglot) (bind-key* (kbd "<f2>") #'eglot-rename) (bind-key* (kbd "C-x C-f") 'counsel-find-file) (bind-key* (kbd "M-x") 'counsel-M-x) (bind-key* (kbd "C-;") 'neotree-toggle) (defun create-file () + "Create a file and refresh neotree." (interactive) (call-interactively #'make-empty-file) (neotree-refresh)) @@ -108,6 +111,7 @@ (bind-key* (kbd "s-n") 'create-file) (defun create-directory () + "Create a directory and refresh neotree." (interactive) (call-interactively #'make-directory) (neotree-refresh)) @@ -119,16 +123,17 @@ :defer t :init (add-hook 'after-init-hook 'global-company-mode) :config - (use-package company-irony :ensure t :defer t) + ;; (use-package company-irony :ensure t :defer t) TODO: Do I need irony? (setq company-idle-delay 0 company-minimum-prefix-length 2 - company-show-numbers t + company-show-quick-access t company-tooltip-limit 20 company-dabbrev-downcase nil - company-backends '((company-irony company-gtags)) + company-backends '((company-gtags company-elisp)) ; TODO: do i need company-irony here company-vscode-light-icons-margin 1 ) ) + (provide 'general) ;;; general.el ends here diff --git a/lisp/lisp.el b/lisp/lisp.el new file mode 100644 index 0000000..c313d53 --- /dev/null +++ b/lisp/lisp.el @@ -0,0 +1,12 @@ + +;;; Code: +(require 'eglot) +;;(add-hook 'emacs-lisp-mode-hook 'eglot-ensure) +(defun setup-lisp() + "Set up the Lisp auto complete." + (company-mode t) + ) + +(add-hook 'emacs-lisp-mode-hook 'setup-lisp) +(provide 'lisp) +;;; lisp.el ends here diff --git a/lisp/neotree.el b/lisp/neotree.el deleted file mode 100644 index 0156cb9..0000000 --- a/lisp/neotree.el +++ /dev/null @@ -1,2226 +0,0 @@ -;;; neotree.el --- A tree plugin like NerdTree for Vim - -;; Copyright (C) 2014 jaypei - -;; Author: jaypei <jaypei97159@gmail.com> -;; URL: https://github.com/jaypei/emacs-neotree -;; Version: 0.5.1 -;; Package-Requires: ((cl-lib "0.5")) - -;; 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: - -;; To use this file, put something like the following in your -;; ~/.emacs: -;; -;; (add-to-list 'load-path "/directory/containing/neotree/") -;; (require 'neotree) -;; -;; Type M-x neotree to start. -;; -;; To set options for NeoTree, type M-x customize, then select -;; Applications, NeoTree. -;; - -;;; Code: - -(require 'cl-lib) - -;; -;; Constants -;; - -(defconst neo-buffer-name " *NeoTree*" - "Name of the buffer where neotree shows directory contents.") - -(defconst neo-dir - (expand-file-name (if load-file-name - (file-name-directory load-file-name) - default-directory))) - -(defconst neo-header-height 5) - -(eval-and-compile - - ;; Added in Emacs 24.3 - (unless (fboundp 'user-error) - (defalias 'user-error 'error)) - - ;; Added in Emacs 24.3 (mirrors/emacs@b335efc3). - (unless (fboundp 'setq-local) - (defmacro setq-local (var val) - "Set variable VAR to value VAL in current buffer." - (list 'set (list 'make-local-variable (list 'quote var)) val))) - - ;; Added in Emacs 24.3 (mirrors/emacs@b335efc3). - (unless (fboundp 'defvar-local) - (defmacro defvar-local (var val &optional docstring) - "Define VAR as a buffer-local variable with default value VAL. -Like `defvar' but additionally marks the variable as being automatically -buffer-local wherever it is set." - (declare (debug defvar) (doc-string 3)) - (list 'progn (list 'defvar var val docstring) - (list 'make-variable-buffer-local (list 'quote var)))))) - -;; Add autoload function for vc (#153). -(autoload 'vc-responsible-backend "vc.elc") - -;; -;; Macros -;; - -(defmacro neo-util--to-bool (obj) - "If OBJ is non-nil, return t, else return nil." - `(and ,obj t)) - -(defmacro neo-global--with-buffer (&rest body) - "Execute the forms in BODY with global NeoTree buffer." - (declare (indent 0) (debug t)) - `(let ((neotree-buffer (neo-global--get-buffer))) - (unless (null neotree-buffer) - (with-current-buffer neotree-buffer - ,@body)))) - -(defmacro neo-global--with-window (&rest body) - "Execute the forms in BODY with global NeoTree window." - (declare (indent 0) (debug t)) - `(save-selected-window - (neo-global--select-window) - ,@body)) - -(defmacro neo-global--when-window (&rest body) - "Execute the forms in BODY when selected window is NeoTree window." - (declare (indent 0) (debug t)) - `(when (eq (selected-window) neo-global--window) - ,@body)) - -(defmacro neo-global--switch-to-buffer () - "Switch to NeoTree buffer." - `(let ((neotree-buffer (neo-global--get-buffer))) - (unless (null neotree-buffer) - (switch-to-buffer neotree-buffer)))) - -(defmacro neo-buffer--with-editing-buffer (&rest body) - "Execute BODY in neotree buffer without read-only restriction." - `(let (rlt) - (neo-global--with-buffer - (setq buffer-read-only nil) - (setq rlt (progn ,@body)) - (setq buffer-read-only t)) - rlt)) - -(defmacro neo-buffer--with-resizable-window (&rest body) - "Execute BODY in neotree window without `window-size-fixed' restriction." - `(let (rlt) - (neo-global--with-buffer - (neo-buffer--unlock-width)) - (setq rlt (progn ,@body)) - (neo-global--with-buffer - (neo-buffer--lock-width)) - rlt)) - -(defmacro neotree-make-executor (&rest fn-form) - "Make an open event handler, FN-FORM is event handler form." - (let* ((get-args-fn - (lambda (sym) (or (plist-get fn-form sym) (lambda (&rest _))))) - (file-fn (funcall get-args-fn :file-fn)) - (dir-fn (funcall get-args-fn :dir-fn))) - `(lambda (&optional arg) - (interactive "P") - (neo-global--select-window) - (neo-buffer--execute arg ,file-fn ,dir-fn)))) - - -;; -;; Customization -;; - -(defgroup neotree nil - "Options for neotree." - :prefix "neo-" - :group 'files) - -(defgroup neotree-vc-options nil - "Neotree-VC customizations." - :prefix "neo-vc-" - :group 'neotree - :link '(info-link "(neotree)Configuration")) - -(defgroup neotree-confirmations nil - "Neotree confirmation customizations." - :prefix "neo-confirm-" - :group 'neotree) - -(defcustom neo-window-position 'left - "*The position of NeoTree window." - :group 'neotree - :type '(choice (const left) - (const right))) - -(defcustom neo-display-action '(neo-default-display-fn) - "*Action to use for displaying NeoTree window. -If you change the action so it doesn't use -`neo-default-display-fn', then other variables such as -`neo-window-position' won't be respected when opening NeoTree -window." - :type 'sexp - :group 'neotree) - -(defcustom neo-create-file-auto-open nil - "*If non-nil, the file will auto open when created." - :type 'boolean - :group 'neotree) - -(defcustom neo-banner-message nil - "*The banner message of neotree window." - :type 'string - :group 'neotree) - -(defcustom neo-show-updir-line t - "*If non-nil, show the updir line (..)." - :type 'boolean - :group 'neotree) - -(defcustom neo-show-slash-for-folder t - "*If non-nil, show the slash at the end of folder (folder/)" - :type 'boolean - :group 'neotree) - -(defcustom neo-reset-size-on-open nil - "*If non-nil, the width of the noetree window will be reseted every time a file is open." - :type 'boolean - :group 'neotree) - -(defcustom neo-theme 'classic - "*The tree style to display. -`classic' use icon to display, it only it suitable for GUI mode. -`ascii' is the simplest style, it will use +/- to display the fold state, -it suitable for terminal. -`arrow' use unicode arrow. -`nerd' use the nerdtree indentation mode and arrow." - :group 'neotree - :type '(choice (const classic) - (const ascii) - (const arrow) - (const icons) - (const nerd))) - -(defcustom neo-mode-line-type 'neotree - "*The mode-line type to display, `default' is a non-modified mode-line, \ -`neotree' is a compact mode-line that shows useful information about the - current node like the parent directory and the number of nodes, -`custom' uses the format stored in `neo-mode-line-custom-format', -`none' hide the mode-line." - :group 'neotree - :type '(choice (const default) - (const neotree) - (const custom) - (const none))) - -(defcustom neo-mode-line-custom-format nil - "*If `neo-mode-line-type' is set to `custom', this variable specifiy \ -the mode-line format." - :type 'sexp - :group 'neotree) - -(defcustom neo-smart-open nil - "*If non-nil, every time when the neotree window is opened, it will try to find current file and jump to node." - :type 'boolean - :group 'neotree) - -(defcustom neo-show-hidden-files nil - "*If non-nil, the hidden files are shown by default." - :type 'boolean - :group 'neotree) - -(defcustom neo-autorefresh nil - "*If non-nil, the neotree buffer will auto refresh." - :type 'boolean - :group 'neotree) - -(defcustom neo-window-width 25 - "*Specifies the width of the NeoTree window." - :type 'integer - :group 'neotree) - -(defcustom neo-window-fixed-size t - "*If the neotree windows is fixed, it won't be resize when rebalance windows." - :type 'boolean - :group 'neotree) - -(defcustom neo-keymap-style 'default - "*The default keybindings for neotree-mode-map." - :group 'neotree - :type '(choice (const default) - (const concise))) - -(defcustom neo-cwd-line-style 'text - "*The default header style." - :group 'neotree - :type '(choice (const text) - (const button))) - -(defcustom neo-help-echo-style 'default - "The message NeoTree displays when the mouse moves onto nodes. -`default' means the node name is displayed if it has a -width (including the indent) larger than `neo-window-width', and -`none' means NeoTree doesn't display any messages." - :group 'neotree - :type '(choice (const default) - (const none))) - -(defcustom neo-click-changes-root nil - "*If non-nil, clicking on a directory will change the current root to the directory." - :type 'boolean - :group 'neotree) - -(defcustom neo-auto-indent-point nil - "*If non-nil the point is autmotically put on the first letter of a node." - :type 'boolean - :group 'neotree) - -(defcustom neo-hidden-regexp-list - '("^\\." "\\.pyc$" "~$" "^#.*#$" "\\.elc$" "\\.o$") - "*The regexp list matching hidden files." - :type '(repeat (choice regexp)) - :group 'neotree) - -(defcustom neo-enter-hook nil - "Functions to run if enter node occured." - :type 'hook - :group 'neotree) - -(defcustom neo-after-create-hook nil - "Hooks called after creating the neotree buffer." - :type 'hook - :group 'neotree) - -(defcustom neo-vc-integration nil - "If non-nil, show VC status." - :group 'neotree-vc - :type '(set (const :tag "Use different faces" face) - (const :tag "Use different characters" char))) - -(defcustom neo-vc-state-char-alist - '((up-to-date . ?\s) - (edited . ?E) - (added . ?+) - (removed . ?-) - (missing . ?!) - (needs-merge . ?M) - (conflict . ?!) - (unlocked-changes . ?!) - (needs-update . ?U) - (ignored . ?\s) - (user . ?U) - (unregistered . ?\s) - (nil . ?\s)) - "Alist of vc-states to indicator characters. -This variable is used in `neo-vc-for-node' when -`neo-vc-integration' contains `char'." - :group 'neotree-vc - :type '(alist :key-type symbol - :value-type character)) - -(defcustom neo-confirm-change-root 'yes-or-no-p - "Confirmation asking for permission to change root if file was not found in root path." - :type '(choice (function-item :tag "Verbose" yes-or-no-p) - (function-item :tag "Succinct" y-or-n-p) - (function-item :tag "Off" off-p)) - :group 'neotree-confirmations) - -(defcustom neo-confirm-create-file 'yes-or-no-p - "Confirmation asking whether *NeoTree* should create a file." - :type '(choice (function-item :tag "Verbose" yes-or-no-p) - (function-item :tag "Succinct" y-or-n-p) - (function-item :tag "Off" off-p)) - :group 'neotree-confirmations) - -(defcustom neo-confirm-create-directory 'yes-or-no-p - "Confirmation asking whether *NeoTree* should create a directory." - :type '(choice (function-item :tag "Verbose" yes-or-no-p) - (function-item :tag "Succinct" y-or-n-p) - (function-item :tag "Off" off-p)) - :group 'neotree-confirmations) - -(defcustom neo-confirm-delete-file 'yes-or-no-p - "Confirmation asking whether *NeoTree* should delete the file." - :type '(choice (function-item :tag "Verbose" yes-or-no-p) - (function-item :tag "Succinct" y-or-n-p) - (function-item :tag "Off" off-p)) - :group 'neotree-confirmations) - -(defcustom neo-confirm-delete-directory-recursively 'yes-or-no-p - "Confirmation asking whether the directory should be deleted recursively." - :type '(choice (function-item :tag "Verbose" yes-or-no-p) - (function-item :tag "Succinct" y-or-n-p) - (function-item :tag "Off" off-p)) - :group 'neotree-confirmations) - -(defcustom neo-confirm-kill-buffers-for-files-in-directory 'yes-or-no-p - "Confirmation asking whether *NeoTree* should kill buffers for the directory in question." - :type '(choice (function-item :tag "Verbose" yes-or-no-p) - (function-item :tag "Succinct" y-or-n-p) - (function-item :tag "Off" off-p)) - :group 'neotree-confirmations) - -(defcustom neo-toggle-window-keep-p nil - "If not nil, not switch to *NeoTree* buffer when executing `neotree-toggle'." - :type 'boolean - :group 'neotree) - -(defcustom neo-force-change-root t - "If not nil, do not prompt when switching root." - :type 'boolean - :group 'neotree) - -(defcustom neo-filepath-sort-function 'string< - "Function to be called when sorting neotree nodes." - :type '(symbol (const :tag "Normal" string<) - (const :tag "Sort Hidden at Bottom" neo-sort-hidden-last) - (function :tag "Other")) - :group 'neotree) - -(defcustom neo-default-system-application "xdg-open" - "*Name of the application that is used to open a file under point. -By default it is xdg-open." - :type 'string - :group 'neotree) - -(defcustom neo-hide-cursor nil - "If not nil, hide cursor in NeoTree buffer and turn on line higlight." - :type 'boolean - :group 'neotree) - -;; -;; Faces -;; - -(defface neo-banner-face - '((((background dark)) (:foreground "lightblue" :weight bold)) - (t (:foreground "DarkMagenta"))) - "*Face used for the banner in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-banner-face 'neo-banner-face) - -(defface neo-header-face - '((((background dark)) (:foreground "White")) - (t (:foreground "DarkMagenta"))) - "*Face used for the header in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-header-face 'neo-header-face) - -(defface neo-root-dir-face - '((((background dark)) (:foreground "lightblue" :weight bold)) - (t (:foreground "DarkMagenta"))) - "*Face used for the root dir in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-root-dir-face 'neo-root-dir-face) - -(defface neo-dir-link-face - '((((background dark)) (:foreground "DeepSkyBlue")) - (t (:foreground "MediumBlue"))) - "*Face used for expand sign [+] in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-dir-link-face 'neo-dir-link-face) - -(defface neo-file-link-face - '((((background dark)) (:foreground "White")) - (t (:foreground "Black"))) - "*Face used for open file/dir in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-file-link-face 'neo-file-link-face) - -(defface neo-button-face - '((t (:underline nil))) - "*Face used for open file/dir in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-button-face 'neo-button-face) - -(defface neo-expand-btn-face - '((((background dark)) (:foreground "SkyBlue")) - (t (:foreground "DarkCyan"))) - "*Face used for open file/dir in neotree buffer." - :group 'neotree :group 'font-lock-highlighting-faces) -(defvar neo-expand-btn-face 'neo-expand-btn-face) - -(defface neo-vc-default-face - '((((background dark)) (:foreground "White")) - (t (:foreground "Black"))) - "*Face used for unknown files in the neotree buffer. -Used only when \(vc-state node\) returns nil." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-default-face 'neo-vc-default-face) - -(defface neo-vc-user-face - '((t (:foreground "Red" :slant italic))) - "*Face used for user-locked files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-user-face 'neo-vc-user-face) - -(defface neo-vc-up-to-date-face - '((((background dark)) (:foreground "LightGray")) - (t (:foreground "DarkGray"))) - "*Face used for vc-up-to-date files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-up-to-date-face 'neo-vc-up-to-date-face) - -(defface neo-vc-edited-face - '((((background dark)) (:foreground "Magenta")) - (t (:foreground "DarkMagenta"))) - "*Face used for vc-edited files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-edited-face 'neo-vc-edited-face) - -(defface neo-vc-needs-update-face - '((t (:underline t))) - "*Face used for vc-needs-update files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-needs-update-face 'neo-vc-needs-update-face) - -(defface neo-vc-needs-merge-face - '((((background dark)) (:foreground "Red1")) - (t (:foreground "Red3"))) - "*Face used for vc-needs-merge files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-needs-merge-face 'neo-vc-needs-merge-face) - -(defface neo-vc-unlocked-changes-face - '((t (:foreground "Red" :background "Blue"))) - "*Face used for vc-unlocked-changes files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-unlocked-changes-face 'neo-vc-unlocked-changes-face) - -(defface neo-vc-added-face - '((((background dark)) (:foreground "LightGreen")) - (t (:foreground "DarkGreen"))) - "*Face used for vc-added files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-added-face 'neo-vc-added-face) - -(defface neo-vc-removed-face - '((t (:strike-through t))) - "*Face used for vc-removed files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-removed-face 'neo-vc-removed-face) - -(defface neo-vc-conflict-face - '((((background dark)) (:foreground "Red1")) - (t (:foreground "Red3"))) - "*Face used for vc-conflict files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-conflict-face 'neo-vc-conflict-face) - -(defface neo-vc-missing-face - '((((background dark)) (:foreground "Red1")) - (t (:foreground "Red3"))) - "*Face used for vc-missing files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-missing-face 'neo-vc-missing-face) - -(defface neo-vc-ignored-face - '((((background dark)) (:foreground "DarkGrey")) - (t (:foreground "LightGray"))) - "*Face used for vc-ignored files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-ignored-face 'neo-vc-ignored-face) - -(defface neo-vc-unregistered-face - nil - "*Face used for vc-unregistered files in the neotree buffer." - :group 'neotree-vc :group 'font-lock-highlighting-faces) -(defvar neo-vc-unregistered-face 'neo-vc-unregistered-face) - -;; -;; Variables -;; - -(defvar neo-global--buffer nil) - -(defvar neo-global--window nil) - -(defvar neo-global--autorefresh-timer nil) - -(defvar neo-mode-line-format - (list - '(:eval - (let* ((fname (neo-buffer--get-filename-current-line)) - (current (if fname fname neo-buffer--start-node)) - (parent (if fname (file-name-directory current) current)) - (nodes (neo-buffer--get-nodes parent)) - (dirs (car nodes)) - (files (cdr nodes)) - (ndirs (length dirs)) - (nfiles (length files)) - (index - (when fname - (1+ (if (file-directory-p current) - (neo-buffer--get-node-index current dirs) - (+ ndirs (neo-buffer--get-node-index current files))))))) - (neo-mode-line--compute-format parent index ndirs nfiles)))) - "Neotree mode-line displaying information on the current node. -This mode-line format is used if `neo-mode-line-type' is set to `neotree'") - -(defvar-local neo-buffer--start-node nil - "Start node(i.e. directory) for the window.") - -(defvar-local neo-buffer--start-line nil - "Index of the start line of the root.") - -(defvar-local neo-buffer--cursor-pos (cons nil 1) - "To save the cursor position. -The car of the pair will store fullpath, and cdr will store line number.") - -(defvar-local neo-buffer--last-window-pos (cons nil 1) - "To save the scroll position for NeoTree window.") - -(defvar-local neo-buffer--show-hidden-file-p nil - "Show hidden nodes in tree.") - -(defvar-local neo-buffer--expanded-node-list nil - "A list of expanded dir nodes.") - -(defvar-local neo-buffer--node-list nil - "The model of current NeoTree buffer.") - -(defvar-local neo-buffer--node-list-1 nil - "The model of current NeoTree buffer (temp).") - -;; -;; Major mode definitions -;; - -(defvar neotree-file-button-keymap - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] - (neotree-make-executor - :file-fn 'neo-open-file)) - map) - "Keymap for file-node button.") - -(defvar neotree-dir-button-keymap - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] - (neotree-make-executor :dir-fn 'neo-open-dir)) - map) - "Keymap for dir-node button.") - -(defvar neotree-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "TAB") (neotree-make-executor - :dir-fn 'neo-open-dir)) - (define-key map (kbd "RET") (neotree-make-executor - :file-fn 'neo-open-file - :dir-fn 'neo-open-dir)) - (define-key map (kbd "|") (neotree-make-executor - :file-fn 'neo-open-file-vertical-split)) - (define-key map (kbd "-") (neotree-make-executor - :file-fn 'neo-open-file-horizontal-split)) - (define-key map (kbd "a") (neotree-make-executor - :file-fn 'neo-open-file-ace-window)) - (define-key map (kbd "d") (neotree-make-executor - :dir-fn 'neo-open-dired)) - (define-key map (kbd "O") (neotree-make-executor - :dir-fn 'neo-open-dir-recursive)) - (define-key map (kbd "SPC") 'neotree-quick-look) - (define-key map (kbd "g") 'neotree-refresh) - (define-key map (kbd "q") 'neotree-hide) - (define-key map (kbd "p") 'neotree-previous-line) - (define-key map (kbd "C-p") 'neotree-previous-line) - (define-key map (kbd "n") 'neotree-next-line) - (define-key map (kbd "C-n") 'neotree-next-line) - (define-key map (kbd "A") 'neotree-stretch-toggle) - (define-key map (kbd "U") 'neotree-select-up-node) - (define-key map (kbd "D") 'neotree-select-down-node) - (define-key map (kbd "H") 'neotree-hidden-file-toggle) - (define-key map (kbd "S") 'neotree-select-previous-sibling-node) - (define-key map (kbd "s") 'neotree-select-next-sibling-node) - (define-key map (kbd "o") 'neotree-open-file-in-system-application) - (define-key map (kbd "C-x C-f") 'find-file-other-window) - (define-key map (kbd "C-x 1") 'neotree-empty-fn) - (define-key map (kbd "C-x 2") 'neotree-empty-fn) - (define-key map (kbd "C-x 3") 'neotree-empty-fn) - (define-key map (kbd "C-c C-f") 'find-file-other-window) - (define-key map (kbd "C-c C-c") 'neotree-change-root) - (define-key map (kbd "C-c c") 'neotree-dir) - (define-key map (kbd "C-c C-a") 'neotree-collapse-all) - (cond - ((eq neo-keymap-style 'default) - (define-key map (kbd "C-c C-n") 'neotree-create-node) - (define-key map (kbd "C-c C-d") 'neotree-delete-node) - (define-key map (kbd "C-c C-r") 'neotree-rename-node) - (define-key map (kbd "C-c C-p") 'neotree-copy-node)) - ((eq neo-keymap-style 'concise) - (define-key map (kbd "C") 'neotree-change-root) - (define-key map (kbd "c") 'neotree-create-node) - (define-key map (kbd "+") 'neotree-create-node) - (define-key map (kbd "d") 'neotree-delete-node) - (define-key map (kbd "r") 'neotree-rename-node) - (define-key map (kbd "e") 'neotree-enter))) - map) - "Keymap for `neotree-mode'.") - -(define-derived-mode neotree-mode special-mode "NeoTree" - "A major mode for displaying the directory tree in text mode." - (setq indent-tabs-mode nil ; only spaces - buffer-read-only t ; read only - truncate-lines -1 - neo-buffer--show-hidden-file-p neo-show-hidden-files) - (when neo-hide-cursor - (progn - (setq cursor-type nil) - (hl-line-mode +1))) - (pcase neo-mode-line-type - (`neotree - (setq-local mode-line-format neo-mode-line-format) - (add-hook 'post-command-hook 'force-mode-line-update nil t)) - (`none (setq-local mode-line-format nil)) - (`custom - (setq-local mode-line-format neo-mode-line-custom-format) - (add-hook 'post-command-hook 'force-mode-line-update nil t)) - (_ nil)) - ;; fix for electric-indent-mode - ;; for emacs 24.4 - (if (fboundp 'electric-indent-local-mode) - (electric-indent-local-mode -1) - ;; for emacs 24.3 or less - (add-hook 'electric-indent-functions - (lambda (arg) 'no-indent) nil 'local)) - (when neo-auto-indent-point - (add-hook 'post-command-hook 'neo-hook--node-first-letter nil t))) - -;; -;; Global methods -;; - -(defun neo-global--window-exists-p () - "Return non-nil if neotree window exists." - (and (not (null (window-buffer neo-global--window))) - (eql (window-buffer neo-global--window) (neo-global--get-buffer)))) - -(defun neo-global--select-window () - "Select the NeoTree window." - (interactive) - (let ((window (neo-global--get-window t))) - (select-window window))) - -(defun neo-global--get-window (&optional auto-create-p) - "Return the neotree window if it exists, else return nil. -But when the neotree window does not exist and AUTO-CREATE-P is non-nil, -it will create the neotree window and return it." - (unless (neo-global--window-exists-p) - (setf neo-global--window nil)) - (when (and (null neo-global--window) - auto-create-p) - (setq neo-global--window - (neo-global--create-window))) - neo-global--window) - -(defun neo-default-display-fn (buffer _alist) - "Display BUFFER to the left or right of the root window. -The side is decided according to `neo-window-position'. -The root window is the root window of the selected frame. -_ALIST is ignored." - (let ((window-pos (if (eq neo-window-position 'left) 'left 'right))) - (display-buffer-in-side-window buffer `((side . ,window-pos))))) - -(defun neo-global--create-window () - "Create global neotree window." - (let ((window nil) - (buffer (neo-global--get-buffer t))) - (setq window - (select-window - (display-buffer buffer neo-display-action))) - (neo-window--init window buffer) - (neo-global--attach) - (neo-global--reset-width) - window)) - -(defun neo-global--get-buffer (&optional init-p) - "Return the global neotree buffer if it exists. -If INIT-P is non-nil and global NeoTree buffer not exists, then create it." - (unless (equal (buffer-name neo-global--buffer) - neo-buffer-name) - (setf neo-global--buffer nil)) - (when (and init-p - (null neo-global--buffer)) - (save-window-excursion - (setq neo-global--buffer - (neo-buffer--create)))) - neo-global--buffer) - -(defun neo-global--file-in-root-p (path) - "Return non-nil if PATH in root dir." - (neo-global--with-buffer - (and (not (null neo-buffer--start-node)) - (neo-path--file-in-directory-p path neo-buffer--start-node)))) - -(defun neo-global--alone-p () - "Check whether the global neotree window is alone with some other window." - (let ((windows (window-list))) - (and (= (length windows) - 2) - (member neo-global--window windows)))) - -(defun neo-global--do-autorefresh () - "Do auto refresh." - (interactive) - (when (and neo-autorefresh (neo-global--window-exists-p) - (buffer-file-name)) - (neotree-refresh t))) - -(defun neo-global--open () - "Show the NeoTree window." - (let ((valid-start-node-p nil)) - (neo-global--with-buffer - (setf valid-start-node-p (neo-buffer--valid-start-node-p))) - (if (not valid-start-node-p) - (neo-global--open-dir (neo-path--get-working-dir)) - (neo-global--get-window t)))) - -(defun neo-global--open-dir (path) - "Show the NeoTree window, and change root to PATH." - (neo-global--get-window t) - (neo-global--with-buffer - (neo-buffer--change-root path))) - -(defun neo-global--open-and-find (path) - "Quick select node which specified PATH in NeoTree." - (let ((npath path) - root-dir) - (when (null npath) - (throw 'invalid-path "Invalid path to select.")) - (setq root-dir (if (file-directory-p npath) - npath (neo-path--updir npath))) - (when (or (not (neo-global--window-exists-p)) - (not (neo-global--file-in-root-p npath))) - (neo-global--open-dir root-dir)) - (neo-global--with-window - (neo-buffer--select-file-node npath t)))) - -(defun neo-global--select-mru-window (arg) - "Create or find a window to select when open a file node. -The description of ARG is in `neotree-enter'." - (when (eq (safe-length (window-list)) 1) - (neo-buffer--with-resizable-window - (split-window-horizontally))) - (when neo-reset-size-on-open - (neo-global--when-window - (neo-window--zoom 'minimize))) - ;; select target window - (cond - ;; select window with winum - ((and (integerp arg) - (bound-and-true-p winum-mode) - (fboundp 'winum-select-window-by-number)) - (winum-select-window-by-number arg)) - ;; select window with window numbering - ((and (integerp arg) - (boundp 'window-numbering-mode) - (symbol-value window-numbering-mode) - (fboundp 'select-window-by-number)) - (select-window-by-number arg)) - ;; open node in a new vertically split window - ((and (stringp arg) (string= arg "a") - (fboundp 'ace-select-window)) - (ace-select-window)) - ((and (stringp arg) (string= arg "|")) - (select-window (get-mru-window)) - (split-window-right) - (windmove-right)) - ;; open node in a new horizontally split window - ((and (stringp arg) (string= arg "-")) - (select-window (get-mru-window)) - (split-window-below) - (windmove-down))) - ;; open node in last active window - (select-window (get-mru-window))) - -(defun neo-global--detach () - "Detach the global neotree buffer." - (when neo-global--autorefresh-timer - (cancel-timer neo-global--autorefresh-timer)) - (neo-global--with-buffer - (neo-buffer--unlock-width)) - (setq neo-global--buffer nil) - (setq neo-global--window nil)) - -(defun neo-global--attach () - "Attach the global neotree buffer" - (when neo-global--autorefresh-timer - (cancel-timer neo-global--autorefresh-timer)) - (when neo-autorefresh - (setq neo-global--autorefresh-timer - (run-with-idle-timer 2 10 'neo-global--do-autorefresh))) - (setq neo-global--buffer (get-buffer neo-buffer-name)) - (setq neo-global--window (get-buffer-window - neo-global--buffer)) - (neo-global--with-buffer - (neo-buffer--lock-width)) - (run-hook-with-args 'neo-after-create-hook '(window))) - -(defun neo-global--set-window-width (width) - "Set neotree window width to WIDTH." - (neo-global--with-window - (neo-buffer--with-resizable-window - (neo-util--set-window-width (selected-window) width)))) - -(defun neo-global--reset-width () - "Set neotree window width to `neo-window-width'." - (neo-global--set-window-width neo-window-width)) - -;; -;; Advices -;; - -(defadvice mouse-drag-vertical-line - (around neotree-drag-vertical-line (start-event) activate) - "Drag and drop is not affected by the lock." - (neo-buffer--with-resizable-window - ad-do-it)) - -(defadvice balance-windows - (around neotree-balance-windows activate) - "Fix neotree inhibits balance-windows." - (if (neo-global--window-exists-p) - (let (old-width) - (neo-global--with-window - (setq old-width (window-width))) - (neo-buffer--with-resizable-window - ad-do-it) - (neo-global--with-window - (neo-global--set-window-width old-width))) - ad-do-it)) - -(eval-after-load 'popwin - '(progn - (defadvice popwin:create-popup-window - (around neotree/popwin-popup-buffer activate) - (let ((neo-exists-p (neo-global--window-exists-p))) - (when neo-exists-p - (neo-global--detach)) - ad-do-it - (when neo-exists-p - (neo-global--attach) - (neo-global--reset-width)))) - - (defadvice popwin:close-popup-window - (around neotree/popwin-close-popup-window activate) - (let ((neo-exists-p (neo-global--window-exists-p))) - (when neo-exists-p - (neo-global--detach)) - ad-do-it - (when neo-exists-p - (neo-global--attach) - (neo-global--reset-width)))))) - -;; -;; Hooks -;; - -(defun neo-hook--node-first-letter () - "Move point to the first letter of the current node." - (when (or (eq this-command 'next-line) - (eq this-command 'previous-line)) - (neo-point-auto-indent))) - -;; -;; Util methods -;; - -(defun neo-util--filter (condp lst) - "Apply CONDP to elements of LST keeping those that return non-nil. - -Example: - (neo-util--filter 'symbolp '(a \"b\" 3 d4)) - => (a d4) - -This procedure does not work when CONDP is the `null' function." - (delq nil - (mapcar (lambda (x) (and (funcall condp x) x)) lst))) - -(defun neo-util--find (where which) - "Find element of the list WHERE matching predicate WHICH." - (catch 'found - (dolist (elt where) - (when (funcall which elt) - (throw 'found elt))) - nil)) - -(defun neo-util--make-printable-string (string) - "Strip newline character from STRING, like 'Icon\n'." - (replace-regexp-in-string "\n" "" string)) - -(defun neo-util--walk-dir (path) - "Return the subdirectories and subfiles of the PATH." - (let* ((full-path (neo-path--file-truename path))) - (condition-case nil - (directory-files - path 'full directory-files-no-dot-files-regexp) - ('file-error - (message "Walk directory %S failed." path) - nil)))) - -(defun neo-util--hidden-path-filter (node) - "A filter function, if the NODE can not match each item in \ -`neo-hidden-regexp-list', return t." - (if (not neo-buffer--show-hidden-file-p) - (let ((shortname (neo-path--file-short-name node))) - (null (neo-util--filter - (lambda (x) (not (null (string-match-p x shortname)))) - neo-hidden-regexp-list))) - node)) - -(defun neo-str--trim-left (s) - "Remove whitespace at the beginning of S." - (if (string-match "\\`[ \t\n\r]+" s) - (replace-match "" t t s) - s)) - -(defun neo-str--trim-right (s) - "Remove whitespace at the end of S." - (if (string-match "[ \t\n\r]+\\'" s) - (replace-match "" t t s) - s)) - -(defun neo-str--trim (s) - "Remove whitespace at the beginning and end of S." - (neo-str--trim-left (neo-str--trim-right s))) - -(defun neo-path--expand-name (path &optional current-dir) - (expand-file-name (or (if (file-name-absolute-p path) path) - (let ((r-path path)) - (setq r-path (substitute-in-file-name r-path)) - (setq r-path (expand-file-name r-path current-dir)) - r-path)))) - -(defun neo-path--shorten (path len) - "Shorten a given PATH to a specified LEN. -This is needed for paths, which are to long for the window to display -completely. The function cuts of the first part of the path to remain -the last folder (the current one)." - (let ((result - (if (> (length path) len) - (concat "<" (substring path (- (- len 2)))) - path))) - (when result - (decode-coding-string result 'utf-8)))) - -(defun neo-path--insert-chroot-button (label path face) - (insert-button - label - 'action '(lambda (x) (neotree-change-root)) - 'follow-link t - 'face face - 'neo-full-path path)) - -(defun neo-path--insert-header-buttonized (path) - "Shortens the PATH to (window-body-width) and displays any \ -visible remains as buttons that, when clicked, navigate to that -parent directory." - (let* ((dirs (reverse (cl-maplist 'identity (reverse (split-string path "/" :omitnulls))))) - (last (car-safe (car-safe (last dirs))))) - (neo-path--insert-chroot-button "/" "/" 'neo-root-dir-face) - (dolist (dir dirs) - (if (string= (car dir) last) - (neo-buffer--insert-with-face last 'neo-root-dir-face) - (neo-path--insert-chroot-button - (concat (car dir) "/") - (apply 'neo-path--join (cons "/" (reverse dir))) - 'neo-root-dir-face)))) - ;;shorten the line if need be - (when (> (current-column) (window-body-width)) - (forward-char (- (window-body-width))) - (delete-region (point-at-bol) (point)) - (let* ((button (button-at (point))) - (path (if button (overlay-get button 'neo-full-path) "/"))) - (neo-path--insert-chroot-button "<" path 'neo-root-dir-face)) - (end-of-line))) - -(defun neo-path--updir (path) - (let ((r-path (neo-path--expand-name path))) - (if (and (> (length r-path) 0) - (equal (substring r-path -1) "/")) - (setq r-path (substring r-path 0 -1))) - (if (eq (length r-path) 0) - (setq r-path "/")) - (directory-file-name - (file-name-directory r-path)))) - -(defun neo-path--join (root &rest dirs) - "Joins a series of directories together with ROOT and DIRS. -Like Python's os.path.join, - (neo-path--join \"/tmp\" \"a\" \"b\" \"c\") => /tmp/a/b/c ." - (or (if (not dirs) root) - (let ((tdir (car dirs)) - (epath nil)) - (setq epath - (or (if (equal tdir ".") root) - (if (equal tdir "..") (neo-path--updir root)) - (neo-path--expand-name tdir root))) - (apply 'neo-path--join - epath - (cdr dirs))))) - -(defun neo-path--file-short-name (file) - "Base file/directory name by FILE. -Taken from http://lists.gnu.org/archive/html/emacs-devel/2011-01/msg01238.html" - (or (if (string= file "/") "/") - (neo-util--make-printable-string (file-name-nondirectory (directory-file-name file))))) - -(defun neo-path--file-truename (path) - (let ((rlt (file-truename path))) - (if (not (null rlt)) - (progn - (if (and (file-directory-p rlt) - (> (length rlt) 0) - (not (equal (substring rlt -1) "/"))) - (setq rlt (concat rlt "/"))) - rlt) - nil))) - -(defun neo-path--has-subfile-p (dir) - "To determine whether a directory(DIR) contain files." - (and (file-exists-p dir) - (file-directory-p dir) - (neo-util--walk-dir dir) - t)) - -(defun neo-path--match-path-directory (path) - (let ((true-path (neo-path--file-truename path)) - (rlt-path nil)) - (setq rlt-path - (catch 'rlt - (if (file-directory-p true-path) - (throw 'rlt true-path)) - (setq true-path - (file-name-directory true-path)) - (if (file-directory-p true-path) - (throw 'rlt true-path)))) - (if (not (null rlt-path)) - (setq rlt-path (neo-path--join "." rlt-path "./"))) - rlt-path)) - -(defun neo-path--get-working-dir () - "Return a directory name of the current buffer." - (file-name-as-directory (file-truename default-directory))) - -(defun neo-path--strip (path) - "Remove whitespace at the end of PATH." - (let* ((rlt (neo-str--trim path)) - (pos (string-match "[\\\\/]+\\'" rlt))) - (when pos - (setq rlt (replace-match "" t t rlt)) - (when (eq (length rlt) 0) - (setq rlt "/"))) - rlt)) - -(defun neo-path--path-equal-p (path1 path2) - "Return non-nil if pathes PATH1 and PATH2 are the same path." - (string-equal (neo-path--strip path1) - (neo-path--strip path2))) - -(defun neo-path--file-equal-p (file1 file2) - "Return non-nil if files FILE1 and FILE2 name the same file. -If FILE1 or FILE2 does not exist, the return value is unspecified." - (unless (or (null file1) - (null file2)) - (let ((nfile1 (neo-path--strip file1)) - (nfile2 (neo-path--strip file2))) - (file-equal-p nfile1 nfile2)))) - -(defun neo-path--file-in-directory-p (file dir) - "Return non-nil if FILE is in DIR or a subdirectory of DIR. -A directory is considered to be \"in\" itself. -Return nil if DIR is not an existing directory." - (let ((nfile (neo-path--strip file)) - (ndir (neo-path--strip dir))) - (setq ndir (concat ndir "/")) - (file-in-directory-p nfile ndir))) - -(defun neo-util--kill-buffers-for-path (path) - "Kill all buffers for files in PATH." - (let ((buffer (find-buffer-visiting path))) - (when buffer - (kill-buffer buffer))) - (dolist (filename (directory-files path t directory-files-no-dot-files-regexp)) - (let ((buffer (find-buffer-visiting filename))) - (when buffer - (kill-buffer buffer)) - (when (and - (file-directory-p filename) - (neo-path--has-subfile-p filename)) - (neo-util--kill-buffers-for-path filename))))) - -(defun neo-util--set-window-width (window n) - "Make WINDOW N columns width." - (let ((w (max n window-min-width))) - (unless (null window) - (if (> (window-width) w) - (shrink-window-horizontally (- (window-width) w)) - (if (< (window-width) w) - (enlarge-window-horizontally (- w (window-width)))))))) - -(defun neo-point-auto-indent () - "Put the point on the first letter of the current node." - (when (neo-buffer--get-filename-current-line) - (beginning-of-line 1) - (re-search-forward "[^-\s+]" (line-end-position 1) t) - (backward-char 1))) - -(defun off-p (msg) - "Returns true regardless of message value in the argument." - t) - -(defun neo-sort-hidden-last (x y) - "Sort normally but with hidden files last." - (let ((x-hidden (neo-filepath-hidden-p x)) - (y-hidden (neo-filepath-hidden-p y))) - (cond - ((and x-hidden (not y-hidden)) - nil) - ((and (not x-hidden) y-hidden) - t) - (t - (string< x y))))) - -(defun neo-filepath-hidden-p (node) - "Return whether or not node is a hidden path." - (let ((shortname (neo-path--file-short-name node))) - (neo-util--filter - (lambda (x) (not (null (string-match-p x shortname)))) - neo-hidden-regexp-list))) - -(defun neo-get-unsaved-buffers-from-projectile () - "Return list of unsaved buffers from projectile buffers." - (interactive) - (let ((rlist '()) - (rtag t)) - (condition-case nil - (projectile-project-buffers) - (error (setq rtag nil))) - (when (and rtag (fboundp 'projectile-project-buffers)) - (dolist (buf (projectile-project-buffers)) - (with-current-buffer buf - (if (and (buffer-modified-p) buffer-file-name) - (setq rlist (cons (buffer-file-name) rlist)) - )))) - rlist)) - -;; -;; Buffer methods -;; - -(defun neo-buffer--newline-and-begin () - "Insert new line." - (newline) - (beginning-of-line)) - -(defun neo-buffer--get-icon (name) - "Get image by NAME." - (let ((icon-path (neo-path--join neo-dir "icons")) - image) - (setq image (create-image - (neo-path--join icon-path (concat name ".xpm")) - 'xpm nil :ascent 'center :mask '(heuristic t))) - image)) - -(defun neo-buffer--insert-fold-symbol (name &optional node-name) - "Write icon by NAME, the icon style affected by neo-theme. -`open' write opened folder icon. -`close' write closed folder icon. -`leaf' write leaf icon. -Optional NODE-NAME is used for the `icons' theme" - (let ((n-insert-image (lambda (n) - (insert-image (neo-buffer--get-icon n)))) - (n-insert-symbol (lambda (n) - (neo-buffer--insert-with-face - n 'neo-expand-btn-face)))) - (cond - ((and (display-graphic-p) (equal neo-theme 'classic)) - (or (and (equal name 'open) (funcall n-insert-image "open")) - (and (equal name 'close) (funcall n-insert-image "close")) - (and (equal name 'leaf) (funcall n-insert-image "leaf")))) - ((equal neo-theme 'arrow) - (or (and (equal name 'open) (funcall n-insert-symbol "▾")) - (and (equal name 'close) (funcall n-insert-symbol "▸")))) - ((equal neo-theme 'nerd) - (or (and (equal name 'open) (funcall n-insert-symbol "▾ ")) - (and (equal name 'close) (funcall n-insert-symbol "▸ ")) - (and (equal name 'leaf) (funcall n-insert-symbol " ")))) - ((and (display-graphic-p) (equal neo-theme 'icons)) - (unless (require 'all-the-icons nil 'noerror) - (error "Package `all-the-icons' isn't installed")) - (setq-local tab-width 1) - (or (and (equal name 'open) (insert (all-the-icons-icon-for-dir-with-chevron (directory-file-name node-name) "down"))) - (and (equal name 'close) (insert (all-the-icons-icon-for-dir-with-chevron (directory-file-name node-name) "right"))) - (and (equal name 'leaf) (insert (format "\t\t\t%s\t" (all-the-icons-icon-for-file node-name)))))) - (t - (or (and (equal name 'open) (funcall n-insert-symbol "- ")) - (and (equal name 'close) (funcall n-insert-symbol "+ "))))))) - -(defun neo-buffer--save-cursor-pos (&optional node-path line-pos) - "Save cursor position. -If NODE-PATH and LINE-POS is nil, it will be save the current line node position." - (let ((cur-node-path nil) - (cur-line-pos nil) - (ws-wind (selected-window)) - (ws-pos (window-start))) - (setq cur-node-path (if node-path - node-path - (neo-buffer--get-filename-current-line))) - (setq cur-line-pos (if line-pos - line-pos - (line-number-at-pos))) - (setq neo-buffer--cursor-pos (cons cur-node-path cur-line-pos)) - (setq neo-buffer--last-window-pos (cons ws-wind ws-pos)))) - -(defun neo-buffer--goto-cursor-pos () - "Jump to saved cursor position." - (let ((line-pos nil) - (node (car neo-buffer--cursor-pos)) - (line-pos (cdr neo-buffer--cursor-pos)) - (ws-wind (car neo-buffer--last-window-pos)) - (ws-pos (cdr neo-buffer--last-window-pos))) - (catch 'line-pos-founded - (unless (null node) - (setq line-pos 0) - (mapc - (lambda (x) - (setq line-pos (1+ line-pos)) - (unless (null x) - (when (neo-path--path-equal-p x node) - (throw 'line-pos-founded line-pos)))) - neo-buffer--node-list)) - (setq line-pos (cdr neo-buffer--cursor-pos)) - (throw 'line-pos-founded line-pos)) - ;; goto line - (goto-char (point-min)) - (neo-buffer--forward-line (1- line-pos)) - ;; scroll window - (when (equal (selected-window) ws-wind) - (set-window-start ws-wind ws-pos t)))) - -(defun neo-buffer--node-list-clear () - "Clear node list." - (setq neo-buffer--node-list nil)) - -(defun neo-buffer--node-list-set (line-num path) - "Set value in node list. -LINE-NUM is the index of node list. -PATH is value." - (let ((node-list-length (length neo-buffer--node-list)) - (node-index line-num)) - (when (null node-index) - (setq node-index (line-number-at-pos))) - (when (< node-list-length node-index) - (setq neo-buffer--node-list - (vconcat neo-buffer--node-list - (make-vector (- node-index node-list-length) nil)))) - (aset neo-buffer--node-list (1- node-index) path)) - neo-buffer--node-list) - -(defun neo-buffer--insert-with-face (content face) - (let ((pos-start (point))) - (insert content) - (set-text-properties pos-start - (point) - (list 'face face)))) - -(defun neo-buffer--valid-start-node-p () - (and (not (null neo-buffer--start-node)) - (file-accessible-directory-p neo-buffer--start-node))) - -(defun neo-buffer--create () - "Create and switch to NeoTree buffer." - (switch-to-buffer - (generate-new-buffer-name neo-buffer-name)) - (neotree-mode) - ;; disable linum-mode - (when (and (boundp 'linum-mode) - (not (null linum-mode))) - (linum-mode -1)) - ;; Use inside helm window in NeoTree - ;; Refs https://github.com/jaypei/emacs-neotree/issues/226 - (setq-local helm-split-window-inside-p t) - (current-buffer)) - -(defun neo-buffer--insert-banner () - (unless (null neo-banner-message) - (let ((start (point))) - (insert neo-banner-message) - (set-text-properties start (point) '(face neo-banner-face))) - (neo-buffer--newline-and-begin))) - -(defun neo-buffer--insert-root-entry (node) - (neo-buffer--node-list-set nil node) - (cond ((eq neo-cwd-line-style 'button) - (neo-path--insert-header-buttonized node)) - (t - (neo-buffer--insert-with-face (neo-path--shorten node (window-body-width)) - 'neo-root-dir-face))) - (neo-buffer--newline-and-begin) - (when neo-show-updir-line - (neo-buffer--insert-fold-symbol 'close node) - (insert-button ".." - 'action '(lambda (x) (neotree-change-root)) - 'follow-link t - 'face neo-dir-link-face - 'neo-full-path (neo-path--updir node)) - (neo-buffer--newline-and-begin))) - -(defun neo-buffer--help-echo-message (node-name) - (cond - ((eq neo-help-echo-style 'default) - (if (<= (+ (current-column) (string-width node-name)) - neo-window-width) - nil - node-name)) - (t nil))) - -(defun neo-buffer--insert-dir-entry (node depth expanded) - (let ((node-short-name (neo-path--file-short-name node))) - (insert-char ?\s (* (- depth 1) 2)) ; indent - (when (memq 'char neo-vc-integration) - (insert-char ?\s 2)) - (neo-buffer--insert-fold-symbol - (if expanded 'open 'close) node) - (insert-button (if neo-show-slash-for-folder (concat node-short-name "/") node-short-name) - 'follow-link t - 'face neo-dir-link-face - 'neo-full-path node - 'keymap neotree-dir-button-keymap - 'help-echo (neo-buffer--help-echo-message node-short-name)) - (neo-buffer--node-list-set nil node) - (neo-buffer--newline-and-begin))) - -(defun neo-buffer--insert-file-entry (node depth) - (let ((node-short-name (neo-path--file-short-name node)) - (vc (when neo-vc-integration (neo-vc-for-node node)))) - (insert-char ?\s (* (- depth 1) 2)) ; indent - (when (memq 'char neo-vc-integration) - (insert-char (car vc)) - (insert-char ?\s)) - (neo-buffer--insert-fold-symbol 'leaf node-short-name) - (insert-button node-short-name - 'follow-link t - 'face (if (memq 'face neo-vc-integration) - (cdr vc) - neo-file-link-face) - 'neo-full-path node - 'keymap neotree-file-button-keymap - 'help-echo (neo-buffer--help-echo-message node-short-name)) - (neo-buffer--node-list-set nil node) - (neo-buffer--newline-and-begin))) - -(defun neo-vc-for-node (node) - (let* ((backend (ignore-errors - (vc-responsible-backend node))) - (vc-state (when backend (vc-state node backend)))) - (cons (cdr (assoc vc-state neo-vc-state-char-alist)) - (cl-case vc-state - (up-to-date neo-vc-up-to-date-face) - (edited neo-vc-edited-face) - (needs-update neo-vc-needs-update-face) - (needs-merge neo-vc-needs-merge-face) - (unlocked-changes neo-vc-unlocked-changes-face) - (added neo-vc-added-face) - (removed neo-vc-removed-face) - (conflict neo-vc-conflict-face) - (missing neo-vc-missing-face) - (ignored neo-vc-ignored-face) - (unregistered neo-vc-unregistered-face) - (user neo-vc-user-face) - (otherwise neo-vc-default-face))))) - -(defun neo-buffer--get-nodes (path) - (let* ((nodes (neo-util--walk-dir path)) - (comp neo-filepath-sort-function) - (nodes (neo-util--filter 'neo-util--hidden-path-filter nodes))) - (cons (sort (neo-util--filter 'file-directory-p nodes) comp) - (sort (neo-util--filter #'(lambda (f) (not (file-directory-p f))) nodes) comp)))) - -(defun neo-buffer--get-node-index (node nodes) - "Return the index of NODE in NODES. - -NODES can be a list of directory or files. -Return nil if NODE has not been found in NODES." - (let ((i 0) - (l (length nodes)) - (cur (car nodes)) - (rest (cdr nodes))) - (while (and cur (not (equal cur node))) - (setq i (1+ i)) - (setq cur (car rest)) - (setq rest (cdr rest))) - (if (< i l) i))) - -(defun neo-buffer--expanded-node-p (node) - "Return non-nil if NODE is expanded." - (neo-util--to-bool - (neo-util--find - neo-buffer--expanded-node-list - #'(lambda (x) (equal x node))))) - -(defun neo-buffer--set-expand (node do-expand) - "Set the expanded state of the NODE to DO-EXPAND. -Return the new expand state for NODE (t for expanded, nil for collapsed)." - (if (not do-expand) - (setq neo-buffer--expanded-node-list - (neo-util--filter - #'(lambda (x) (not (equal node x))) - neo-buffer--expanded-node-list)) - (push node neo-buffer--expanded-node-list)) - do-expand) - -(defun neo-buffer--toggle-expand (node) - (neo-buffer--set-expand node (not (neo-buffer--expanded-node-p node)))) - -(defun neo-buffer--insert-tree (path depth) - (if (eq depth 1) - (neo-buffer--insert-root-entry path)) - (let* ((contents (neo-buffer--get-nodes path)) - (nodes (car contents)) - (leafs (cdr contents)) - (default-directory path)) - (dolist (node nodes) - (let ((expanded (neo-buffer--expanded-node-p node))) - (neo-buffer--insert-dir-entry - node depth expanded) - (if expanded (neo-buffer--insert-tree (concat node "/") (+ depth 1))))) - (dolist (leaf leafs) - (neo-buffer--insert-file-entry leaf depth)))) - -(defun neo-buffer--refresh (save-pos-p &optional non-neotree-buffer) - "Refresh the NeoTree buffer. -If SAVE-POS-P is non-nil, it will be auto save current line number." - (let ((start-node neo-buffer--start-node)) - (unless start-node - (setq start-node default-directory)) - (neo-buffer--with-editing-buffer - ;; save context - (when save-pos-p - (neo-buffer--save-cursor-pos)) - (when non-neotree-buffer - (setq neo-buffer--start-node start-node)) - ;; starting refresh - (erase-buffer) - (neo-buffer--node-list-clear) - (neo-buffer--insert-banner) - (setq neo-buffer--start-line neo-header-height) - (neo-buffer--insert-tree start-node 1)) - ;; restore context - (neo-buffer--goto-cursor-pos))) - -(defun neo-buffer--post-move () - "Reset current directory when position moved." - (funcall - (neotree-make-executor - :file-fn - '(lambda (path _) - (setq default-directory (neo-path--updir btn-full-path))) - :dir-fn - '(lambda (path _) - (setq default-directory (file-name-as-directory path)))))) - -(defun neo-buffer--get-button-current-line () - "Return the first button in current line." - (let* ((btn-position nil) - (pos-line-start (line-beginning-position)) - (pos-line-end (line-end-position)) - ;; NOTE: cannot find button when the button - ;; at beginning of the line - (current-button (or (button-at (point)) - (button-at pos-line-start)))) - (if (null current-button) - (progn - (setf btn-position - (catch 'ret-button - (let* ((next-button (next-button pos-line-start)) - (pos-btn nil)) - (if (null next-button) (throw 'ret-button nil)) - (setf pos-btn (overlay-start next-button)) - (if (> pos-btn pos-line-end) (throw 'ret-button nil)) - (throw 'ret-button pos-btn)))) - (if (null btn-position) - nil - (setf current-button (button-at btn-position))))) - current-button)) - -(defun neo-buffer--get-filename-current-line (&optional default) - "Return filename for first button in current line. -If there is no button in current line, then return DEFAULT." - (let ((btn (neo-buffer--get-button-current-line))) - (if (not (null btn)) - (button-get btn 'neo-full-path) - default))) - -(defun neo-buffer--lock-width () - "Lock the width size for NeoTree window." - (if neo-window-fixed-size - (setq window-size-fixed 'width))) - -(defun neo-buffer--unlock-width () - "Unlock the width size for NeoTree window." - (setq window-size-fixed nil)) - -(defun neo-buffer--rename-node () - "Rename current node as another path." - (interactive) - (let* ((current-path (neo-buffer--get-filename-current-line)) - (buffer (find-buffer-visiting current-path)) - to-path - msg) - (unless (null current-path) - (setq msg (format "Rename [%s] to: " (neo-path--file-short-name current-path))) - (setq to-path (read-file-name msg (file-name-directory current-path))) - (if buffer - (with-current-buffer buffer - (set-visited-file-name to-path nil t))) - (rename-file current-path to-path 1) - (neo-buffer--refresh t) - (message "Rename successful.")))) - -(defun neo-buffer--copy-node () - "Copies current node as another path." - (interactive) - (let* ((current-path (neo-buffer--get-filename-current-line)) - (buffer (find-buffer-visiting current-path)) - to-path - msg) - (unless (null current-path) - (setq msg (format "Copy [%s] to: " (neo-path--file-short-name current-path))) - (setq to-path (read-file-name msg (file-name-directory current-path))) - (if (file-directory-p current-path) - (copy-directory current-path to-path) - (copy-file current-path to-path)) - (neo-buffer--refresh t) - (message "Copy successful.")))) - -(defun neo-buffer--select-file-node (file &optional recursive-p) - "Select the node that corresponds to the FILE. -If RECURSIVE-P is non nil, find files will recursively." - (let ((efile file) - (iter-curr-dir nil) - (file-node-find-p nil) - (file-node-list nil)) - (unless (file-name-absolute-p efile) - (setq efile (expand-file-name efile))) - (setq iter-curr-dir efile) - (catch 'return - (while t - (setq iter-curr-dir (neo-path--updir iter-curr-dir)) - (push iter-curr-dir file-node-list) - (when (neo-path--file-equal-p iter-curr-dir neo-buffer--start-node) - (setq file-node-find-p t) - (throw 'return nil)) - (let ((niter-curr-dir (file-remote-p iter-curr-dir 'localname))) - (unless niter-curr-dir - (setq niter-curr-dir iter-curr-dir)) - (when (neo-path--file-equal-p niter-curr-dir "/") - (setq file-node-find-p nil) - (throw 'return nil))))) - (when file-node-find-p - (dolist (p file-node-list) - (neo-buffer--set-expand p t)) - (neo-buffer--save-cursor-pos file) - (neo-buffer--refresh nil)))) - -(defun neo-buffer--change-root (root-dir) - "Change the tree root to ROOT-DIR." - (let ((path root-dir) - start-path) - (unless (and (file-exists-p path) - (file-directory-p path)) - (throw 'error "The path is not a valid directory.")) - (setq start-path (expand-file-name (substitute-in-file-name path))) - (setq neo-buffer--start-node start-path) - (cd start-path) - (neo-buffer--save-cursor-pos path nil) - (neo-buffer--refresh nil))) - -(defun neo-buffer--get-nodes-for-select-down-node (path) - "Return the node list for the down dir selection." - (if path - (when (file-name-directory path) - (if (neo-buffer--expanded-node-p path) - (neo-buffer--get-nodes path) - (neo-buffer--get-nodes (file-name-directory path)))) - (neo-buffer--get-nodes (file-name-as-directory neo-buffer--start-node)))) - -(defun neo-buffer--get-nodes-for-sibling (path) - "Return the node list for the sibling selection. Return nil of no nodes can -be found. -The returned list is a directory list if path is a directory, otherwise it is -a file list." - (when path - (let ((nodes (neo-buffer--get-nodes (file-name-directory path)))) - (if (file-directory-p path) - (car nodes) - (cdr nodes))))) - -(defun neo-buffer--sibling (path &optional previous) - "Return the next sibling of node PATH. -If PREVIOUS is non-nil the previous sibling is returned." - (let* ((nodes (neo-buffer--get-nodes-for-sibling path))) - (when nodes - (let ((i (neo-buffer--get-node-index path nodes)) - (l (length nodes))) - (if i (nth (mod (+ i (if previous -1 1)) l) nodes)))))) - -(defun neo-buffer--execute (arg &optional file-fn dir-fn) - "Define the behaviors for keyboard event. -ARG is the parameter for command. -If FILE-FN is non-nil, it will executed when a file node. -If DIR-FN is non-nil, it will executed when a dir node." - (interactive "P") - (let* ((btn-full-path (neo-buffer--get-filename-current-line)) - is-file-p - enter-fn) - (unless (null btn-full-path) - (setq is-file-p (not (file-directory-p btn-full-path)) - enter-fn (if is-file-p file-fn dir-fn)) - (unless (null enter-fn) - (funcall enter-fn btn-full-path arg) - (run-hook-with-args - 'neo-enter-hook - (if is-file-p 'file 'directory) - btn-full-path - arg))) - btn-full-path)) - -(defun neo-buffer--set-show-hidden-file-p (show-p) - "If SHOW-P is non-nil, show hidden nodes in tree." - (setq neo-buffer--show-hidden-file-p show-p) - (neo-buffer--refresh t)) - -(defun neo-buffer--forward-line (n) - "Move N lines forward in NeoTree buffer." - (forward-line (or n 1)) - (neo-buffer--post-move)) - -;; -;; Mode-line methods -;; - -(defun neo-mode-line--compute-format (parent index ndirs nfiles) - "Return a formated string to be used in the `neotree' mode-line." - (let* ((nall (+ ndirs nfiles)) - (has-dirs (> ndirs 0)) - (has-files (> nfiles 0)) - (msg-index (when index (format "[%s/%s] " index nall))) - (msg-ndirs (when has-dirs (format (if has-files " (D:%s" " (D:%s)") ndirs))) - (msg-nfiles (when has-files (format (if has-dirs " F:%s)" " (F:%s)") nfiles))) - (msg-directory (file-name-nondirectory (directory-file-name parent))) - (msg-directory-max-length (- (window-width) - (length msg-index) - (length msg-ndirs) - (length msg-nfiles)))) - (setq msg-directory (if (<= (length msg-directory) msg-directory-max-length) - msg-directory - (concat (substring msg-directory - 0 (- msg-directory-max-length 3)) - "..."))) - (propertize - (decode-coding-string (concat msg-index msg-directory msg-ndirs msg-nfiles) 'utf-8) - 'help-echo (decode-coding-string parent 'utf-8)))) - -;; -;; Window methods -;; - -(defun neo-window--init (window buffer) - "Make WINDOW a NeoTree window. -NeoTree buffer is BUFFER." - (neo-buffer--with-resizable-window - (switch-to-buffer buffer) - (set-window-parameter window 'no-delete-other-windows t) - (set-window-dedicated-p window t)) - window) - -(defun neo-window--zoom (method) - "Zoom the NeoTree window, the METHOD should one of these options: -'maximize 'minimize 'zoom-in 'zoom-out." - (neo-buffer--unlock-width) - (cond - ((eq method 'maximize) - (maximize-window)) - ((eq method 'minimize) - (neo-util--set-window-width (selected-window) neo-window-width)) - ((eq method 'zoom-in) - (shrink-window-horizontally 2)) - ((eq method 'zoom-out) - (enlarge-window-horizontally 2))) - (neo-buffer--lock-width)) - -(defun neo-window--minimize-p () - "Return non-nil when the NeoTree window is minimize." - (<= (window-width) neo-window-width)) - -;; -;; Interactive functions -;; - -(defun neotree-next-line (&optional count) - "Move next line in NeoTree buffer. -Optional COUNT argument, moves COUNT lines down." - (interactive "p") - (neo-buffer--forward-line (or count 1))) - -(defun neotree-previous-line (&optional count) - "Move previous line in NeoTree buffer. -Optional COUNT argument, moves COUNT lines up." - (interactive "p") - (neo-buffer--forward-line (- (or count 1)))) - -;;;###autoload -(defun neotree-find (&optional path default-path) - "Quick select node which specified PATH in NeoTree. -If path is nil and no buffer file name, then use DEFAULT-PATH," - (interactive) - (let* ((ndefault-path (if default-path default-path - (neo-path--get-working-dir))) - (npath (if path path - (or (buffer-file-name) ndefault-path))) - (do-open-p nil)) - (if (and (not neo-force-change-root) - (not (neo-global--file-in-root-p npath)) - (neo-global--window-exists-p)) - (setq do-open-p (funcall neo-confirm-change-root "File not found in root path, do you want to change root?")) - (setq do-open-p t)) - (when do-open-p - (neo-global--open-and-find npath)) - (when neo-auto-indent-point - (neo-point-auto-indent))) - (neo-global--select-window)) - -(defun neotree-click-changes-root-toggle () - "Toggle the variable neo-click-changes-root. -If true, clicking on a directory will change the current root to -the directory instead of showing the directory contents." - (interactive) - (setq neo-click-changes-root (not neo-click-changes-root))) - -(defun neo-open-dir (full-path &optional arg) - "Toggle fold a directory node. - -FULL-PATH is the path of the directory. -ARG is ignored." - (if neo-click-changes-root - (neotree-change-root) - (progn - (let ((new-state (neo-buffer--toggle-expand full-path))) - (neo-buffer--refresh t) - (when neo-auto-indent-point - (when new-state (forward-line 1)) - (neo-point-auto-indent)))))) - - -(defun neo--expand-recursive (path state) - "Set the state of children recursively. - -The children of PATH will have state STATE." - (let ((children (car (neo-buffer--get-nodes path) ))) - (dolist (node children) - (neo-buffer--set-expand node state) - (neo--expand-recursive node state )))) - -(defun neo-open-dir-recursive (full-path &optional arg) - "Toggle fold a directory node recursively. - -The children of the node will also be opened recursively. -FULL-PATH is the path of the directory. -ARG is ignored." - (if neo-click-changes-root - (neotree-change-root) - (let ((new-state (neo-buffer--toggle-expand full-path)) - (children (car (neo-buffer--get-nodes full-path)))) - (dolist (node children) - (neo-buffer--set-expand node new-state) - (neo--expand-recursive node new-state)) - (neo-buffer--refresh t)))) - -(defun neo-open-dired (full-path &optional arg) - "Open file or directory node in `dired-mode'. - -FULL-PATH is the path of node. -ARG is same as `neo-open-file'." - (neo-global--select-mru-window arg) - (dired full-path)) - -(defun neo-open-file (full-path &optional arg) - "Open a file node. - -FULL-PATH is the file path you want to open. -If ARG is an integer then the node is opened in a window selected via -`winum' or`window-numbering' (if available) according to the passed number. -If ARG is `|' then the node is opened in new vertically split window. -If ARG is `-' then the node is opened in new horizontally split window." - (neo-global--select-mru-window arg) - (find-file full-path)) - -(defun neo-open-file-vertical-split (full-path arg) - "Open the current node is a vertically split window. -FULL-PATH and ARG are the same as `neo-open-file'." - (neo-open-file full-path "|")) - -(defun neo-open-file-horizontal-split (full-path arg) - "Open the current node is horizontally split window. -FULL-PATH and ARG are the same as `neo-open-file'." - (neo-open-file full-path "-")) - -(defun neo-open-file-ace-window (full-path arg) - "Open the current node in a window chosen by ace-window. -FULL-PATH and ARG are the same as `neo-open-file'." - (neo-open-file full-path "a")) - -(defun neotree-open-file-in-system-application () - "Open a file under point in the system application." - (interactive) - (call-process neo-default-system-application nil 0 nil - (neo-buffer--get-filename-current-line))) - -(defun neotree-change-root () - "Change root to current node dir. -If current node is a file, then it will do nothing. -If cannot find any node in current line, it equivalent to using `neotree-dir'." - (interactive) - (neo-global--select-window) - (let ((btn-full-path (neo-buffer--get-filename-current-line))) - (if (null btn-full-path) - (call-interactively 'neotree-dir) - (neo-global--open-dir btn-full-path)))) - -(defun neotree-select-up-node () - "Select the parent directory of the current node. Change the root if -necessary. " - (interactive) - (neo-global--select-window) - (let* ((btn-full-path (neo-buffer--get-filename-current-line)) - (btn-parent-dir (if btn-full-path (file-name-directory btn-full-path))) - (root-slash (file-name-as-directory neo-buffer--start-node))) - (cond - ((equal btn-parent-dir root-slash) (neo-global--open-dir root-slash)) - (btn-parent-dir (neotree-find btn-parent-dir)) - (t (neo-global--open-dir (file-name-directory - (directory-file-name root-slash))))))) - -(defun neotree-select-down-node () - "Select an expanded directory or content directory according to the -current node, in this order: -- select the first expanded child node if the current node has one -- select the content of current node if it is expanded -- select the next expanded sibling if the current node is not expanded." - (interactive) - (let* ((btn-full-path (neo-buffer--get-filename-current-line)) - (path (if btn-full-path btn-full-path neo-buffer--start-node)) - (nodes (neo-buffer--get-nodes-for-select-down-node path))) - (when nodes - (if (or (equal path neo-buffer--start-node) - (neo-buffer--expanded-node-p path)) - ;; select the first expanded child node - (let ((expanded-dir (catch 'break - (dolist (node (car nodes)) - (if (neo-buffer--expanded-node-p node) - (throw 'break node))) - nil))) - (if expanded-dir - (neotree-find expanded-dir) - ;; select the directory content if needed - (let ((dirs (car nodes)) - (files (cdr nodes))) - (if (> (length dirs) 0) - (neotree-find (car dirs)) - (when (> (length files) 0) - (neotree-find (car files))))))) - ;; select the next expanded sibling - (let ((sibling (neo-buffer--sibling path))) - (while (and (not (neo-buffer--expanded-node-p sibling)) - (not (equal sibling path))) - (setq sibling (neo-buffer--sibling sibling))) - (when (not (string< sibling path)) - ;; select next expanded sibling - (neotree-find sibling))))))) - -(defun neotree-select-next-sibling-node () - "Select the next sibling of current node. -If the current node is the last node then the first node is selected." - (interactive) - (let ((sibling (neo-buffer--sibling (neo-buffer--get-filename-current-line)))) - (when sibling (neotree-find sibling)))) - -(defun neotree-select-previous-sibling-node () - "Select the previous sibling of current node. -If the current node is the first node then the last node is selected." - (interactive) - (let ((sibling (neo-buffer--sibling (neo-buffer--get-filename-current-line) t))) - (when sibling (neotree-find sibling)))) - -(defun neotree-create-node (filename) - "Create a file or directory use specified FILENAME in current node." - (interactive - (let* ((current-dir (neo-buffer--get-filename-current-line neo-buffer--start-node)) - (current-dir (neo-path--match-path-directory current-dir)) - (filename (read-file-name "Filename:" current-dir))) - (if (file-directory-p filename) - (setq filename (concat filename "/"))) - (list filename))) - (catch 'rlt - (let ((is-file nil)) - (when (= (length filename) 0) - (throw 'rlt nil)) - (setq is-file (not (equal (substring filename -1) "/"))) - (when (file-exists-p filename) - (message "File %S already exists." filename) - (throw 'rlt nil)) - (when (and is-file - (funcall neo-confirm-create-file (format "Do you want to create file %S ?" - filename))) - ;; ensure parent directory exist before saving - (mkdir (substring filename 0 (+ 1 (cl-position ?/ filename :from-end t))) t) - ;; NOTE: create a empty file - (write-region "" nil filename) - (neo-buffer--save-cursor-pos filename) - (neo-buffer--refresh nil) - (if neo-create-file-auto-open - (find-file-other-window filename))) - (when (and (not is-file) - (funcall neo-confirm-create-directory (format "Do you want to create directory %S?" - filename))) - (mkdir filename t) - (neo-buffer--save-cursor-pos filename) - (neo-buffer--refresh nil))))) - -(defun neotree-delete-node () - "Delete current node." - (interactive) - (let* ((filename (neo-buffer--get-filename-current-line)) - (buffer (find-buffer-visiting filename)) - (deleted-p nil) - (trash delete-by-moving-to-trash)) - (catch 'end - (if (null filename) (throw 'end nil)) - (if (not (file-exists-p filename)) (throw 'end nil)) - (if (not (funcall neo-confirm-delete-file (format "Do you really want to delete %S?" - filename))) - (throw 'end nil)) - (if (file-directory-p filename) - ;; delete directory - (progn - (unless (neo-path--has-subfile-p filename) - (delete-directory filename nil trash) - (setq deleted-p t) - (throw 'end nil)) - (when (funcall neo-confirm-delete-directory-recursively - (format "%S is a directory, delete it recursively?" - filename)) - (when (funcall neo-confirm-kill-buffers-for-files-in-directory - (format "kill buffers for files in directory %S?" - filename)) - (neo-util--kill-buffers-for-path filename)) - (delete-directory filename t trash) - (setq deleted-p t))) - ;; delete file - (progn - (delete-file filename trash) - (when buffer - (kill-buffer-ask buffer)) - (setq deleted-p t)))) - (when deleted-p - (message "%S deleted." filename) - (neo-buffer--refresh t)) - filename)) - -(defun neotree-rename-node () - "Rename current node." - (interactive) - (neo-buffer--rename-node)) - -(defun neotree-copy-node () - "Copy current node." - (interactive) - (neo-buffer--copy-node)) - -(defun neotree-hidden-file-toggle () - "Toggle show hidden files." - (interactive) - (neo-buffer--set-show-hidden-file-p (not neo-buffer--show-hidden-file-p))) - -(defun neotree-empty-fn () - "Used to bind the empty function to the shortcut." - (interactive)) - -(defun neotree-refresh (&optional is-auto-refresh) - "Refresh the NeoTree buffer." - (interactive) - (if (eq (current-buffer) (neo-global--get-buffer)) - (neo-buffer--refresh t) - (save-excursion - (let ((cw (selected-window))) ;; save current window - (if is-auto-refresh - (let ((origin-buffer-file-name (buffer-file-name))) - (when (and (fboundp 'projectile-project-p) - (projectile-project-p) - (fboundp 'projectile-project-root)) - (neo-global--open-dir (projectile-project-root)) - (neotree-find (projectile-project-root))) - (neotree-find origin-buffer-file-name)) - (neo-buffer--refresh t t)) - (recenter) - (when (or is-auto-refresh neo-toggle-window-keep-p) - (select-window cw)))))) - -(defun neotree-stretch-toggle () - "Make the NeoTree window toggle maximize/minimize." - (interactive) - (neo-global--with-window - (if (neo-window--minimize-p) - (neo-window--zoom 'maximize) - (neo-window--zoom 'minimize)))) - -(defun neotree-collapse-all () - (interactive) - "Collapse all expanded folders in the neotree buffer" - (setq list-of-expanded-folders neo-buffer--expanded-node-list) - (dolist (folder list-of-expanded-folders) - (neo-buffer--toggle-expand folder) - (neo-buffer--refresh t) - ) - ) -;;;###autoload -(defun neotree-projectile-action () - "Integration with `Projectile'. - -Usage: - (setq projectile-switch-project-action 'neotree-projectile-action). - -When running `projectile-switch-project' (C-c p p), `neotree' will change root -automatically." - (interactive) - (cond - ((fboundp 'projectile-project-root) - (neotree-dir (projectile-project-root))) - (t - (error "Projectile is not available")))) - -;;;###autoload -(defun neotree-toggle () - "Toggle show the NeoTree window." - (interactive) - (if (neo-global--window-exists-p) - (neotree-hide) - (neotree-show))) - -;;;###autoload -(defun neotree-show () - "Show the NeoTree window." - (interactive) - (let ((cw (selected-window)) - (path (buffer-file-name))) ;; save current window and buffer - (if neo-smart-open - (progn - (when (and (fboundp 'projectile-project-p) - (projectile-project-p) - (fboundp 'projectile-project-root)) - (neotree-dir (projectile-project-root))) - (neotree-find path)) - (neo-global--open)) - (neo-global--select-window) - (when neo-toggle-window-keep-p - (select-window cw)))) - -;;;###autoload -(defun neotree-hide () - "Close the NeoTree window." - (interactive) - (if (neo-global--window-exists-p) - (delete-window neo-global--window))) - -;;;###autoload -(defun neotree-dir (path) - "Show the NeoTree window, and change root to PATH." - (interactive "DDirectory: ") - (neo-global--open-dir path) - (neo-global--select-window)) - -;;;###autoload -(defalias 'neotree 'neotree-show "Show the NeoTree window.") - -;; -;; backward compatible -;; - -(defun neo-bc--make-obsolete-message (from to) - (message "Warning: `%S' is obsolete. Use `%S' instead." from to)) - -(defun neo-buffer--enter-file (path) - (neo-bc--make-obsolete-message 'neo-buffer--enter-file 'neo-open-file)) - -(defun neo-buffer--enter-dir (path) - (neo-bc--make-obsolete-message 'neo-buffer--enter-dir 'neo-open-dir)) - -(defun neotree-enter (&optional arg) - "NeoTree typical open event. -ARG are the same as `neo-open-file'." - (interactive "P") - (neo-buffer--execute arg 'neo-open-file 'neo-open-dir)) - -(defun neotree-quick-look (&optional arg) - "Quick Look like NeoTree open event. -ARG are the same as `neo-open-file'." - (interactive "P") - (neotree-enter arg) - (neo-global--select-window)) - -(defun neotree-enter-vertical-split () - "NeoTree open event, file node will opened in new vertically split window." - (interactive) - (neo-buffer--execute nil 'neo-open-file-vertical-split 'neo-open-dir)) - -(defun neotree-enter-horizontal-split () - "NeoTree open event, file node will opened in new horizontally split window." - (interactive) - (neo-buffer--execute nil 'neo-open-file-horizontal-split 'neo-open-dir)) - -(defun neotree-enter-ace-window () - "NeoTree open event, file node will be opened in window chosen by ace-window." - (interactive) - (neo-buffer--execute nil 'neo-open-file-ace-window 'neo-open-dir)) - -(defun neotree-copy-filepath-to-yank-ring () - "Neotree convenience interactive function: file node path will be added to the kill ring." - (interactive) - (kill-new (neo-buffer--get-filename-current-line))) - -(defun neotree-split-window-sensibly (&optional window) - "An neotree-version of split-window-sensibly, -which is used to fix issue #209. -(setq split-window-preferred-function 'neotree-split-window-sensibly)" - (let ((window (or window (selected-window)))) - (or (split-window-sensibly window) - (and (get-buffer-window neo-buffer-name) - (not (window-minibuffer-p window)) - ;; If WINDOW is the only window on its frame - ;; (or only include Neo window) and is not the - ;; minibuffer window, try to split it vertically disregarding - ;; the value of `split-height-threshold'. - (let ((split-height-threshold 0)) - (when (window-splittable-p window) - (with-selected-window window - (split-window-below)))))))) - -(provide 'neotree) -;;; neotree.el ends here - |