branch: elpa/javelin
commit 253a2b1edbc494d87a88c27ab431b68a4be14902
Author: Otávio Schwanck dos Santos <[email protected]>
Commit: Otávio Schwanck dos Santos <[email protected]>
Initial Commit
---
README.org | 73 +++++++++++++++++++++++
demo.gif | Bin 0 -> 9219396 bytes
harpoon.el | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 272 insertions(+)
diff --git a/README.org b/README.org
new file mode 100644
index 00000000000..3638424c396
--- /dev/null
+++ b/README.org
@@ -0,0 +1,73 @@
+* About
+Harpoon plugin for emacs, based on
[[https://github.com/ThePrimeagen/harpoon][ThePrimeagen]] for vim.
+
+This plugin offers quick bookmarks separated by project and branch. You can
quick navigate between your working files and forget about that files opened
that you will not use anymore.
+
+Harpoon persists between emacs sessions.
+
+[[file:demo.gif]]
+
+* Installation
+** Manual
+Load =harpoon.el= in your personal configuration.
+
+** MELPA
+Coming soon.
+
+* Features
+- Add, order and delete harpoons in your code.
+- Harpoon is separated by project and branch
+- Quick switch between harpoons
+
+* Configuring
+Example of how to set the shortcuts:
+
+#+begin_src emacs-lisp
+;; On vanilla (You can use another prefix instead C-c h)
+(global-set-key (kbd "C-c h f") 'harpoon-toggle-file)
+(global-set-key (kbd "C-c h <return>") 'harpoon-add-file)
+(global-set-key (kbd "C-c h h") 'harpoon-toggle-quick-menu)
+(global-set-key (kbd "C-c h c") 'harpoon-clear)
+(global-set-key (kbd "C-c h 1") 'harpoon-go-to-1)
+(global-set-key (kbd "C-c h 2") 'harpoon-go-to-2)
+(global-set-key (kbd "C-c h 3") 'harpoon-go-to-3)
+(global-set-key (kbd "C-c h 4") 'harpoon-go-to-4)
+(global-set-key (kbd "C-c h 5") 'harpoon-go-to-5)
+(global-set-key (kbd "C-c h 6") 'harpoon-go-to-6)
+(global-set-key (kbd "C-c h 7") 'harpoon-go-to-7)
+(global-set-key (kbd "C-c h 8") 'harpoon-go-to-8)
+(global-set-key (kbd "C-c h 9") 'harpoon-go-to-9)
+
+;; On doom emacs
+(load "path/to/harpoon.el")
+(require 'harpoon)
+
+(map! :n "<tab> f" 'harpoon-toggle-file)
+(map! :n "<tab> <return>" 'harpoon-add-file)
+(map! :n "<tab> <tab>" 'harpoon-toggle-quick-menu)
+(map! :n "<tab> c" 'harpoon-clear)
+(map! :n "<tab> 1" 'harpoon-go-to-1)
+(map! :n "<tab> 2" 'harpoon-go-to-2)
+(map! :n "<tab> 3" 'harpoon-go-to-3)
+(map! :n "<tab> 4" 'harpoon-go-to-4)
+(map! :n "<tab> 5" 'harpoon-go-to-5)
+(map! :n "<tab> 6" 'harpoon-go-to-6)
+(map! :n "<tab> 7" 'harpoon-go-to-7)
+(map! :n "<tab> 8" 'harpoon-go-to-8)
+(map! :n "<tab> 9" 'harpoon-go-to-9)
+#+end_src
+
+* My other works:
+** Rails i18n:
+https://github.com/otavioschwanck/rails-i18n.el
+
+** Rails routes:
+https://github.com/otavioschwanck/rails-routes.el
+
+** My Personal Config (for rails)
+(Very complete, has videos + handbooks of how to use)
+https://github.com/otavioschwanck/doom-emacs-on-rails/
+
+
+* Do you like my work? Please, buy me a coffee
+https://www.buymeacoffee.com/otavioschwanck
diff --git a/demo.gif b/demo.gif
new file mode 100644
index 00000000000..736887f1d9c
Binary files /dev/null and b/demo.gif differ
diff --git a/harpoon.el b/harpoon.el
new file mode 100644
index 00000000000..000e774a122
--- /dev/null
+++ b/harpoon.el
@@ -0,0 +1,199 @@
+;;; harpoon.el --- Bookmarks with steroids -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Otávio Schwanck
+
+;; Author: Otávio Schwanck <[email protected]>
+;; Keywords: tools languages
+;; Homepage: https://github.com/otavioschwanck/rails-routes
+;; Version: 0.3
+;; Package-Requires: ((emacs "27.2") (projectile "2.5.0") (magit "3.3.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:
+
+;; This is a plugin base on harpoon from vim (by ThePrimeagen). Is like a
bookmark manager with steroids.
+;; You can easily add, reorder and delete bookmarks. Hhe bookmarks are
separated by project and branch.
+
+;;; Code:
+(require 'projectile)
+(require 'magit)
+(require 'f)
+(require 'magit)
+
+(defgroup harpoon nil
+ "Harpoon for emacs."
+ :group 'tools)
+
+(defcustom harpoon-cache-file (concat user-emacs-directory ".local/harpoon/")
+ "Where the cache will be saved."
+ :type 'string)
+
+(defvar harpoon-cache '()
+ "Cache for harpoon.")
+
+(defcustom harpoon--current-project-path nil
+ "Current project name on harpoon. Its only transactional."
+ :type 'string)
+
+(defcustom harpoon--project-path nil
+ "Current project name on harpoon. Its only transactional."
+ :type 'string)
+
+(defcustom harpoon-cache-loaded nil
+ "Cache for harpoon."
+ :type 'boolean)
+
+(defun harpoon--cache-key ()
+ "Key to save current file on cache."
+ (concat (harpoon--sanitize (projectile-project-name))
+ "#"
+ (harpoon--sanitize (magit-get-current-branch))))
+
+(defun harpoon--create-directory ()
+ "Create harpoon cache dir if dont exists."
+ (unless (f-directory? harpoon-cache-file)
+ (shell-command (concat "mkdir " harpoon-cache-file))))
+
+
+
+(defun harpoon--file-name ()
+ "File name for harpoon on current project."
+ (concat harpoon-cache-file (harpoon--cache-key)))
+
+(defun harpoon--buffer-file-name ()
+ "Parse harpoon file name."
+ (s-replace-regexp (projectile-project-p) "" (buffer-file-name)))
+
+(defun harpoon--sanitize (string)
+ "Sanitize word to save file. STRING: String to sanitize."
+ (s-replace-regexp "/" "---" string))
+
+(defun harpoon--go-to (line-number)
+ "Go to specific file on harpoon (by line order). LINE-NUMBER: Line to go."
+ (let* ((file-name (s-replace-regexp "\n" ""
+ (shell-command-to-string
+ (format "head -n %s < %s | tail -n 1"
+ line-number
+ (harpoon--file-name)))))
+ (full-file-name (concat (projectile-project-p) file-name)))
+ (message full-file-name)
+ (if (file-exists-p full-file-name)
+ (find-file full-file-name)
+ (message "File not found. =("))))
+
+(defun harpoon-go-to-1 ()
+ "Go to file 1 on harpoon."
+ (interactive)
+ (harpoon--go-to 1))
+
+(defun harpoon-go-to-2 ()
+ "Go to file 2 on harpoon."
+ (interactive)
+ (harpoon--go-to 2))
+
+(defun harpoon-go-to-3 ()
+ "Go to file 3 on harpoon."
+ (interactive)
+ (harpoon--go-to 3))
+
+(defun harpoon-go-to-4 ()
+ "Go to file 4 on harpoon."
+ (interactive)
+ (harpoon--go-to 4))
+
+(defun harpoon-go-to-5 ()
+ "Go to file 5 on harpoon."
+ (interactive)
+ (harpoon--go-to 5))
+
+(defun harpoon-go-to-6 ()
+ "Go to file 6 on harpoon."
+ (interactive)
+ (harpoon--go-to 6))
+
+(defun harpoon-go-to-7 ()
+ "Go to file 7 on harpoon."
+ (interactive)
+ (harpoon--go-to 7))
+
+(defun harpoon-go-to-8 ()
+ "Go to file 8 on harpoon."
+ (interactive)
+ (harpoon--go-to 8))
+
+(defun harpoon-go-to-9 ()
+ "Go to file 9 on harpoon."
+ (interactive)
+ (harpoon--go-to 9))
+
+(defun harpoon-add-file ()
+ "Add current file to harpoon."
+ (interactive)
+ (harpoon--create-directory)
+ (let ((harpoon-current-file-text
+ (harpoon--get-file-text)))
+ (if (string-match-p (harpoon--buffer-file-name) harpoon-current-file-text)
+ (message "This file is already on harpoon!")
+ (f-write-text (concat harpoon-current-file-text
(harpoon--buffer-file-name) "\n") 'utf-8 (harpoon--file-name)))))
+
+(defun harpoon--get-file-text ()
+ "Get text inside harpoon file."
+ (if (file-exists-p (harpoon--file-name))
+ (f-read (harpoon--file-name) 'utf-8) ""))
+
+(defun harpoon-toggle-file ()
+ "Open harpoon file."
+ (interactive)
+ (harpoon--create-directory)
+ (setq harpoon--current-project-path (projectile-project-p))
+ (find-file (harpoon--file-name) '(:dedicated t))
+ (harpoon-mode))
+
+(defun harpoon-toggle-quick-menu ()
+ "Open quickmenu."
+ (interactive)
+ (let ((result (completing-read "Harpoon to file: "
+ (delete (s-replace-regexp
(projectile-project-p) "" (buffer-file-name))
+ (delete "" (split-string
(harpoon--get-file-text) "\n"))))))
+ (when result
+ (find-file (concat (projectile-project-p) result)))))
+
+(define-derived-mode harpoon-mode nil "Harpoon"
+ "Mode for harpoon."
+ (setq-local require-final-newline mode-require-final-newline)
+ (setq-local harpoon--project-path harpoon--current-project-path)
+ (setq harpoon--current-project-path nil)
+ (display-line-numbers-mode t))
+
+(defun harpoon-clear ()
+ "Clear harpoon files."
+ (interactive)
+ (f-write "" 'utf-8 (harpoon--file-name)))
+
+(defun harpoon-find-file ()
+ "Visit file on harpoon-mode."
+ (interactive)
+ "Find file on harpoon mode"
+ (let* ((line (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
+ (path (concat harpoon--project-path line)))
+ (when (file-exists-p path)
+ (save-buffer)
+ (kill-buffer)
+ (find-file path))))
+
+(define-key harpoon-mode-map (kbd "<return>") #'harpoon-find-file)
+
+(provide 'harpoon)
+;;; harpoon.el ends here