[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/why-this c2a21ca13d 01/59: Core implementation without any
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/why-this c2a21ca13d 01/59: Core implementation without any backends |
Date: |
Sun, 27 Nov 2022 16:02:45 -0500 (EST) |
branch: elpa/why-this
commit c2a21ca13dd16c39c807ed67d438d516afa5478e
Author: Akib Azmain Turja <akib@disroot.org>
Commit: Akib Azmain Turja <akib@disroot.org>
Core implementation without any backends
---
why-this.el | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
diff --git a/why-this.el b/why-this.el
new file mode 100644
index 0000000000..c96c53689d
--- /dev/null
+++ b/why-this.el
@@ -0,0 +1,169 @@
+;;; why-this.el --- Minor mode for showing why the current line was changed
-*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Akib Azmain Turja.
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; For a full copy of the GNU General Public License
+;; see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package shows the last commit which changed the current line.
+
+;;; Code:
+
+(defgroup why-this nil
+ "Show why the current line was changed."
+ :group 'tools
+ :prefix "why-this-")
+
+(defcustom why-this-backends nil
+ "List of enabled backends."
+ :type '(repeat function)
+ :group 'why-this)
+
+(defcustom why-this-message-format " %a, %T * %i"
+ "Format string for formatting message.
+
+It can also be a function to do the formatting itself."
+ :type '(choice string function)
+ :group 'why-this)
+
+(defcustom why-this-idle-delay 0.5
+ "Idle delay for rendering."
+ :type 'number
+ :group 'why-this)
+
+(defface why-this-face
+ '((t :foreground "#a8a8a8"
+ :background nil
+ :italic t))
+ "Face for Why-This data."
+ :group 'why-this)
+
+(defvar why-this--overlays nil
+ "Overlays created by Why-This.")
+
+(defvar why-this--idle-timer nil
+ "Timer for rendering.")
+
+(defvar-local why-this--backend nil
+ "Backend for current buffer.")
+
+(defun why-this-format-data (data)
+ "Format DATA."
+ (if (functionp why-this-message-format)
+ (funcall why-this-message-format data)
+ (let ((alist `((?a . ,(plist-get data :author))
+ (?T . ,(format-time-string "%d %B %Y"
+ (plist-get data :time)))
+ (?i . ,(plist-get data :message)))))
+ (replace-regexp-in-string
+ "%."
+ (lambda (str)
+ (let ((char (aref str 1)))
+ (if (eq char ?%)
+ "%"
+ (or (cdr (assoc char alist)) str))))
+ why-this-message-format t t))))
+
+(defvar why-this-mode)
+
+(defun why-this--render ()
+ "Render overlays."
+ (while why-this--overlays
+ (delete-overlay (car (pop why-this--overlays))))
+ (when why-this-mode
+ (let* ((begin (line-number-at-pos (if (use-region-p)
+ (region-beginning)
+ (point))))
+ (end (1+ (line-number-at-pos (if (use-region-p)
+ (region-end)
+ (point)))))
+ (backend why-this--backend)
+ (data (funcall backend 'get-data (buffer-file-name) begin end)))
+ (dolist (i (number-sequence 0 (- end begin 1)))
+ (let ((pos (save-excursion
+ (goto-char (point-min))
+ (line-end-position (+ begin i)))))
+ (let ((ov (make-overlay pos pos)))
+ (overlay-put ov 'after-string
+ (propertize (why-this-format-data
+ (append `(:backend ,backend)
+ (nth i data)))
+ 'cursor t 'face 'why-this-face))
+ (push (cons ov (current-buffer)) why-this--overlays)))))))
+
+(defun why-this--render-non-blocking ()
+ "Render overlays, but don't block Emacs."
+ (while-no-input
+ (why-this--render)))
+
+(defun why-this--delete-overlays ()
+ "Delete all overlays unneeded overlays."
+ (let ((begin (line-number-at-pos (if (use-region-p)
+ (region-beginning)
+ (point))))
+ (end (1+ (line-number-at-pos (if (use-region-p)
+ (region-end)
+ (point))))))
+ (setq
+ why-this--overlays
+ (delq
+ nil
+ (mapcar
+ (lambda (ov)
+ (if (and (eq (cdr ov) (current-buffer))
+ (let ((line (line-number-at-pos
+ (overlay-start (car ov)))))
+ (and (>= line begin)
+ (< line end))))
+ ov
+ (delete-overlay (car ov))
+ nil))
+ why-this--overlays)))))
+
+;;;###autoload
+(defun why-this-supported-p ()
+ "Return non-nil if the Why-This mode is support in current buffer.
+
+Actually the supported backend is returned."
+ (catch 'yes
+ (dolist (backend why-this-backends)
+ (let ((result (funcall backend 'supported-p)))
+ (when result
+ (throw 'yes backend))))
+ nil))
+
+;;;###autoload
+(define-minor-mode why-this-mode
+ "Toggle showing why the current line was changed."
+ nil " Why-This" nil
+ (setq why-this--backend (why-this-supported-p))
+ (if (not why-this--backend)
+ (setq why-this-mode nil)
+ (if why-this-mode
+ (progn
+ (add-hook 'post-command-hook #'why-this--delete-overlays nil t)
+ (when why-this--idle-timer
+ (cancel-timer why-this--idle-timer)
+ (setq why-this--idle-timer nil))
+ (setq why-this--idle-timer
+ (run-with-idle-timer why-this-idle-delay t
+ #'why-this--render-non-blocking)))
+ (remove-hook 'post-command-hook #'why-this--delete-overlays t)
+ (cancel-timer why-this--idle-timer)
+ (setq why-this--idle-timer nil))))
+
+;;; why-this.el ends here
- [nongnu] elpa/why-this d47f547250 39/59: Allow customization of executable paths, (continued)
- [nongnu] elpa/why-this d47f547250 39/59: Allow customization of executable paths, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 7f1ae28159 36/59: Fix Git backend, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 9f656b59dd 33/59: Change package summary, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 3497115c2b 35/59: Don't store unnecessary data, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 7a2e4af450 19/59: Rewrite Git backend, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 41fe21da73 15/59: Fontify before annotate, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 006ea3864a 13/59: Fix Git backend 'supported-p command, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 0c1686d8d3 12/59: Fix misspelled word "annonate", ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 73398fb7cb 04/59: Don't interfere with writing, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 2093cadb03 06/59: Add relative time support and fix Git backend, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this c2a21ca13d 01/59: Core implementation without any backends,
ELPA Syncer <=
- [nongnu] elpa/why-this b26fca274d 21/59: Add COPYING, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 88ee5f9746 27/59: Add Mercurial backend, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 624e98bc78 23/59: Fix relative time calculation, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 45dc65ccb1 26/59: Fix timezone problem in Git backend, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 236f8fd225 09/59: Fix problem when enabled on multiple buffers, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this dc5fc19b75 30/59: Allow changing time format, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this b8e612d4cb 20/59: Show tooltip on hover, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this aa15ec4fcd 29/59: Add support for minimum column of message, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 3e3f852835 38/59: Fix README, ELPA Syncer, 2022/11/27
- [nongnu] elpa/why-this 357cfa7e1e 34/59: Ensure that temporary file created by Git backend is deleted, ELPA Syncer, 2022/11/27