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

Reply via email to