Update packages

This commit is contained in:
Marcus Kammer 2020-02-12 10:55:21 +01:00
parent e3b0ca8999
commit 40e8b28ab4
254 changed files with 3437 additions and 567 deletions

View file

@ -85,7 +85,7 @@
'(package-enable-at-startup t)
'(package-selected-packages
(quote
(olivetti elm-mode dashboard pickle poet-theme flymake-eslint json-mode elpy darkroom dockerfile-mode ein spacemacs-theme flucui-themes leuven-theme htmlize scss-mode berrys-theme web-mode python-docstring sphinx-doc sphinx-frontend sphinx-mode ox-nikola racket-mode slime gherkin-mode powershell typescript-mode ob-http ob-ipython ob-restclient nord-theme restclient request restclient-test yaml-mode magit)))
(org-pomodoro olivetti elm-mode dashboard pickle poet-theme flymake-eslint json-mode elpy darkroom dockerfile-mode ein spacemacs-theme flucui-themes leuven-theme htmlize scss-mode berrys-theme web-mode python-docstring sphinx-doc sphinx-frontend sphinx-mode ox-nikola racket-mode slime gherkin-mode powershell typescript-mode ob-http ob-ipython ob-restclient nord-theme restclient request restclient-test yaml-mode magit)))
'(python-shell-interpreter "python3")
'(register-preview-delay 2)
'(register-separator 43)

View file

@ -0,0 +1,100 @@
;;; alert-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name
(or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "alert" "alert.el" (0 0 0 0))
;;; Generated autoloads from alert.el
(autoload 'alert-add-rule "alert" "\
Programmatically add an alert configuration rule.
Normally, users should custoimze `alert-user-configuration'.
This facility is for module writers and users that need to do
things the Lisp way.
Here is a rule the author currently uses with ERC, so that the
fringe gets colored whenever people chat on BitlBee:
\(alert-add-rule :status \\='(buried visible idle)
:severity \\='(moderate high urgent)
:mode \\='erc-mode
:predicate
#\\='(lambda (info)
(string-match (concat \"\\\\`[^&].*@BitlBee\\\\\\='\")
(erc-format-target-and/or-network)))
:persistent
#\\='(lambda (info)
;; If the buffer is buried, or the user has been
;; idle for `alert-reveal-idle-time' seconds,
;; make this alert persistent. Normally, alerts
;; become persistent after
;; `alert-persist-idle-time' seconds.
(memq (plist-get info :status) \\='(buried idle)))
:style \\='fringe
:continue t)
\(fn &key SEVERITY STATUS MODE CATEGORY TITLE MESSAGE PREDICATE ICON (STYLE alert-default-style) PERSISTENT CONTINUE NEVER-PERSIST APPEND)" nil nil)
(autoload 'alert "alert" "\
Alert the user that something has happened.
MESSAGE is what the user will see. You may also use keyword
arguments to specify additional details. Here is a full example:
\(alert \"This is a message\"
:severity \\='high ;; The default severity is `normal'
:title \"Title\" ;; An optional title
:category \\='example ;; A symbol to identify the message
:mode \\='text-mode ;; Normally determined automatically
:buffer (current-buffer) ;; This is the default
:data nil ;; Unused by alert.el itself
:persistent nil ;; Force the alert to be persistent;
;; it is best not to use this
:never-persist nil ;; Force this alert to never persist
:id \\='my-id) ;; Used to replace previous message of
;; the same id in styles that support it
:style \\='fringe) ;; Force a given style to be used;
;; this is only for debugging!
If no :title is given, the buffer-name of :buffer is used. If
:buffer is nil, it is the current buffer at the point of call.
:data is an opaque value which modules can pass through to their
own styles if they wish.
Here are some more typical examples of usage:
;; This is the most basic form usage
(alert \"This is an alert\")
;; You can adjust the severity for more important messages
(alert \"This is an alert\" :severity \\='high)
;; Or decrease it for purely informative ones
(alert \"This is an alert\" :severity \\='trivial)
;; Alerts can have optional titles. Otherwise, the title is the
;; buffer-name of the (current-buffer) where the alert originated.
(alert \"This is an alert\" :title \"My Alert\")
;; Further, alerts can have categories. This allows users to
;; selectively filter on them.
(alert \"This is an alert\" :title \"My Alert\"
:category \\='some-category-or-other)
\(fn MESSAGE &key (SEVERITY \\='normal) TITLE ICON CATEGORY BUFFER MODE DATA STYLE PERSISTENT NEVER-PERSIST ID)" nil nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "alert" '("alert-" "x-urgen")))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; coding: utf-8
;; End:
;;; alert-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "alert" "20191126.2032" "Growl-style notification system for Emacs" '((gntp "0.1") (log4e "0.3.0") (cl-lib "0.5")) :commit "a73ede85c9cdd7d1a7593d4674cde8eec66c098b" :keywords '("notification" "emacs" "message") :authors '(("John Wiegley" . "jwiegley@gmail.com")) :maintainer '("John Wiegley" . "jwiegley@gmail.com") :url "https://github.com/jwiegley/alert")

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -1845,9 +1845,9 @@
("Michael Heerdegen" . "michael_heerdegen@web.de"))
(:maintainer "Michael Heerdegen" . "michael_heerdegen@web.de"))])
(sml-mode .
[(6 9)
[(6 10)
((emacs
(24))
(24 3))
(cl-lib
(0 5)))
"Major mode for editing (Standard) ML" single
@ -1923,7 +1923,7 @@
("Christian Johansson" . "christian@cvj.se"))
(:keywords "tools" "convenience"))])
(stream .
[(2 2 4)
[(2 2 5)
((emacs
(25)))
"Implementation of streams" tar

View file

@ -1,79 +0,0 @@
;;; ein-iexec.el --- Instant execution mode for notebook
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-iexec.el 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.
;; ein-iexec.el 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 ein-iexec.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ein-worksheet)
(defcustom ein:iexec-delay 0.3
"Delay before executing cell after change in second."
:type 'number
:group 'ein)
(defvar ein:iexec-timer nil)
(defun ein:iexec-execute-cell (cell)
"Call `ein:notebook-execute-cell' after `ein:iexec-delay' second.
If the previous execution timer is not fired yet, cancel the timer."
(when ein:iexec-timer
(cancel-timer ein:iexec-timer))
(setq ein:iexec-timer
(run-with-idle-timer ein:iexec-delay nil
#'ein:worksheet-execute-cell
ein:%worksheet% cell)))
(defun ein:iexec-should-execute-p (cell beg end)
"Return non-`nil' if CELL should be executed by the change within
BEG and END."
(and (ein:codecell-p cell)
this-command
(aif (ein:cell-input-pos-min cell) (<= it beg))
(aif (ein:cell-input-pos-max cell) (>= it end))))
(defun ein:iexec-after-change (beg end -ignore-len-)
"Called via `after-change-functions' hook."
(let ((cell (ein:worksheet-get-current-cell :pos beg)))
(when (ein:iexec-should-execute-p cell beg end)
(ein:iexec-execute-cell cell))))
;;;###autoload
(define-minor-mode ein:iexec-mode
"Instant cell execution minor mode.
Code cell at point will be automatically executed after any
change in its input area."
:lighter " ein:i"
:group 'ein
(if ein:iexec-mode
(add-hook 'after-change-functions 'ein:iexec-after-change nil t)
(remove-hook 'after-change-functions 'ein:iexec-after-change t)))
;; To avoid MuMaMo to discard `ein:iexec-after-change', make it
;; permanent local.
(put 'ein:iexec-after-change 'permanent-local-hook t)
(put 'ein:iexec-mode 'permanent-local t)
(provide 'ein-iexec)
;;; ein-iexec.el ends here

Binary file not shown.

View file

@ -1,146 +0,0 @@
;;; ein-pytools.el --- Python tools build on top of kernel
;; Copyright (C) 2012- Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-pytools.el 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.
;; ein-pytools.el 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 ein-pytools.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ein-kernel)
(require 'ein-notebook)
(defun ein:goto-file (filename lineno &optional other-window)
"Jump to file FILEAME at line LINENO.
If OTHER-WINDOW is non-`nil', open the file in the other window."
(funcall (if other-window #'find-file-other-window #'find-file) filename)
(goto-char (point-min))
(forward-line (1- lineno)))
(defun ein:goto-marker (marker &optional other-window)
(funcall (if other-window #'pop-to-buffer #'switch-to-buffer)
(marker-buffer marker))
(goto-char marker))
(defcustom ein:propagate-connect t
"Set to `t' to connect to the notebook after jumping to a buffer."
:type '(choice (const :tag "Yes" t)
(const :tag "No" nil))
:group 'ein)
(defun ein:pytools-request-help (kernel func)
(interactive (list (ein:get-kernel-or-error)
(ein:object-at-point-or-error)))
(ein:kernel-execute kernel
(format "%s?" func) ; = code
nil ; = callbacks
;; It looks like that magic command does
;; not work in silent mode.
:silent nil))
(defvar ein:pytools-jump-stack nil)
(defvar ein:pytools-jump-to-source-not-found-regexp
(ein:join-str "\\|"
(list "^WARNING: .*"
"^Traceback (most recent call last):\n"
"^.*<ipython-input-[^>\n]+>\n"
"^\n")))
(defun ein:pytools-jump-to-source-1 (packed msg-type content -metadata-not-used-)
(ein:log 'debug "msg-type[[%s]] content[[%s]]" msg-type content)
(destructuring-bind (kernel object other-window notebook) packed
(ein:log 'debug "object[[%s]] other-window[[%s]]" object other-window)
(ein:case-equal msg-type
(("stream" "display_data")
(aif (or (plist-get content :text) (plist-get (plist-get content :data) :text/plain))
(if (string-match ein:pytools-jump-to-source-not-found-regexp it)
(ein:log 'info
"Jumping to the source of %s...Not found" object)
(destructuring-bind (filename &optional lineno &rest ignore)
(split-string it "\n")
(setq lineno (string-to-number lineno)
filename (ein:kernel-filename-from-python kernel filename))
(ein:log 'debug "filename[[%s]] lineno[[%s]] ignore[[%s]]"
filename lineno ignore)
(unless (file-exists-p filename)
(ein:log 'info
"Jumping to the source of %s...Not found" object))))))
(("pyerr" "error")
(ein:log 'info "Jumping to the source of %s...Not found" object)))))
(defun ein:pytools-jump-to-source (kernel object &optional
other-window notebook)
(ein:log 'info "Jumping to the source of %s..." object)
(let ((last (car ein:pytools-jump-stack)))
(if (ein:aand last (eql (current-buffer) (marker-buffer it)))
(unless (equal (point) (marker-position last))
(push (point-marker) ein:pytools-jump-stack))
(setq ein:pytools-jump-stack (list (point-marker)))))
(ein:kernel-execute
kernel
(format "__ein_find_source('%s')" object)
(list
:output
(cons
#'ein:pytools-jump-to-source-1
(list kernel object other-window notebook)))))
(defun ein:pytools-jump-to-source-command (&optional other-window)
"Jump to the source code of the object at point.
When the prefix argument ``C-u`` is given, open the source code
in the other window. You can explicitly specify the object by
selecting it."
(interactive "P")
(if poly-ein-mode
(cl-letf (((symbol-function 'xref--prompt-p) #'ignore))
(if other-window
(call-interactively #'xref-find-definitions-other-window)
(call-interactively #'xref-find-definitions)))
(let ((kernel (ein:get-kernel))
(object (ein:object-at-point)))
(assert (ein:kernel-live-p kernel) nil "Kernel is not ready.")
(assert object nil "Object at point not found.")
(ein:pytools-jump-to-source kernel object other-window
(when ein:propagate-connect
(ein:get-notebook))))))
(defun ein:pytools-jump-back-command (&optional other-window)
"Go back to the point where `ein:pytools-jump-to-source-command'
is executed last time. When the prefix argument ``C-u`` is
given, open the last point in the other window."
(interactive "P")
(if poly-ein-mode
(call-interactively #'xref-pop-marker-stack)
(when (ein:aand (car ein:pytools-jump-stack)
(equal (point) (marker-position it)))
(setq ein:pytools-jump-stack (cdr ein:pytools-jump-stack)))
(aif (car ein:pytools-jump-stack)
(ein:goto-marker it other-window)
(ein:log 'info "Nothing on stack."))))
(define-obsolete-function-alias
'ein:pytools-eval-string-internal
'ein:shared-output-eval-string "0.1.2")
(provide 'ein-pytools)
;;; ein-pytools.el ends here

View file

@ -76,20 +76,6 @@ Open a buffer with bug report template.
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ein-file" '("ein:" "*ein:file-buffername-template*")))
;;;***
;;;### (autoloads nil "ein-iexec" "ein-iexec.el" (0 0 0 0))
;;; Generated autoloads from ein-iexec.el
(autoload 'ein:iexec-mode "ein-iexec" "\
Instant cell execution minor mode.
Code cell at point will be automatically executed after any
change in its input area.
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ein-iexec" '("ein:iexec-")))
;;;***
;;;### (autoloads nil "ein-ipdb" "ein-ipdb.el" (0 0 0 0))
@ -325,6 +311,13 @@ and the url-or-port argument of ein:notebooklist-open*.
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ein-output-area" '("ein:")))
;;;***
;;;### (autoloads nil "ein-pager" "ein-pager.el" (0 0 0 0))
;;; Generated autoloads from ein-pager.el
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ein-pager" '("ein:pager-")))
;;;***
;;;### (autoloads nil "ein-process" "ein-process.el" (0 0 0 0))
@ -337,7 +330,7 @@ and the url-or-port argument of ein:notebooklist-open*.
;;;### (autoloads nil "ein-pytools" "ein-pytools.el" (0 0 0 0))
;;; Generated autoloads from ein-pytools.el
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ein-pytools" '("ein:")))
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ein-pytools" '("ein:pytools-")))
;;;***

View file

@ -151,12 +151,6 @@ To view full output, use `ein:notebook-show-in-shared-output'."
(const :tag "Show all traceback" nil))
:group 'ein)
(defcustom ein:cell-autoexec-prompt ""
"String shown in the cell prompt when the auto-execution flag
is on."
:type 'string
:group 'ein)
(defcustom ein:truncate-long-cell-output nil
"When nil do not truncate cells with long outputs. When set to
a number will limit the number of lines in a cell output."
@ -471,9 +465,7 @@ Return language name as a string or `nil' when not defined.
Called from ewoc pretty printer via `ein:cell-pp'."
;; Newline is inserted in `ein:cell-insert-input'.
(ein:insert-read-only
(concat
(format "In [%s]:" (or (ein:oref-safe cell 'input-prompt-number) " "))
(when (slot-value cell 'autoexec) " %s" ein:cell-autoexec-prompt))
(format "In [%s]:" (or (ein:oref-safe cell 'input-prompt-number) " "))
'font-lock-face 'ein:cell-input-prompt))
(cl-defmethod ein:cell-insert-prompt ((cell ein:textcell))
@ -661,25 +653,6 @@ Return language name as a string or `nil' when not defined.
(setf (slot-value cell 'input-prompt-number) number)
(ein:cell-invalidate-prompt cell))
(cl-defmethod ein:cell-set-autoexec ((cell ein:codecell) bool)
"Set auto-execution flag of CELL to BOOL and invalidate the
prompt EWOC node."
(setf (slot-value cell 'autoexec) bool)
(ein:cell-invalidate-prompt cell))
(cl-defmethod ein:cell-autoexec-p ((cell ein:basecell))
"Auto-execution flag set to CELL.
Return `nil' always for non-code cells."
nil)
(cl-defmethod ein:cell-autoexec-p ((cell ein:codecell))
(slot-value cell 'autoexec))
(cl-defmethod ein:cell-toggle-autoexec ((cell ein:codecell))
"Toggle auto-execution flag of CELL to BOOL and invalidate the
prompt EWOC node."
(ein:cell-set-autoexec cell (not (ein:cell-autoexec-p cell))))
(cl-defmethod ein:cell-goto ((cell ein:basecell) &optional relpos prop)
"Go to the input area of the given CELL.
RELPOS is the position relative to the input area. Default is 0.

View file

@ -112,6 +112,9 @@
`ein:$notebook-kernelinfo' : `ein:kernelinfo'
`ein:kernelinfo' instance.
`ein:$notebook-pager'
Variable for `ein:pager-*' functions. See ein-pager.el.
`ein:$notebook-dirty' : boolean
Set to `t' if notebook has unsaved changes. Otherwise `nil'.
@ -145,6 +148,7 @@
kernel
kernelinfo
kernelspec
pager
dirty
metadata
notebook-name
@ -260,13 +264,7 @@ Implementation note:
Typed `:input-prompt-number' becomes a problem when reading a
notebook that saved "*". So don't add `:type'!")
(collapsed :initarg :collapsed :initform nil :type boolean)
(running :initarg :running :initform nil :type boolean)
(autoexec :initarg :autoexec :initform nil :type boolean
:documentation "Auto-execution flag.
This cell is executed when the connected buffer is saved,
provided that (1) this flag is `t' and (2) corresponding
auto-execution mode flag in the connected buffer is `t'.")))
(running :initarg :running :initform nil :type boolean)))
(defclass ein:textcell (ein:basecell)
((cell-type :initarg :cell-type :initform "text")

View file

@ -44,7 +44,7 @@
(ein:$content-path content)))
(setq ein:content-file-buffer--content content)
(let ((raw-content (ein:$content-raw-content content)))
(if (eql system-type 'windows-nt)
(if (eq system-type 'windows-nt)
(insert (decode-coding-string raw-content 'utf-8))
(insert raw-content)))
(set-visited-file-name (buffer-name))

View file

@ -293,9 +293,7 @@ server command."
(if result
(format "[%s not a directory]" result)
""))
nil
ein:jupyter-default-notebook-directory
t)))
default-dir default-dir t)))
result)
nil
(lambda (buffer url-or-port)
@ -347,12 +345,16 @@ server command."
do (sleep-for 0 500))
(lexical-let* ((proc (ein:jupyter-server-process))
(pid (process-id proc)))
(ein:log 'info "Signaled %s with pid %s" proc pid)
(signal-process pid 15)
(if (eq system-type 'windows-nt)
(ein:query-singleton-ajax
(ein:url url-or-port "api/shutdown")
:type "POST")
(ein:log 'info "Signaled %s with pid %s" proc pid)
(signal-process pid 15))
(run-at-time 2 nil
(lambda ()
(ein:log 'info "Resignaled %s with pid %s" proc pid)
(signal-process pid 15))))
(signal-process pid (if (eq system-type 'windows-nt) 9 15)))))
;; `ein:notebooklist-sentinel' frequently does not trigger
(ein:notebooklist-list-remove url-or-port)

View file

@ -2047,16 +2047,6 @@ Used for `flyspell-generic-check-word-predicate'."
ein:markdown-inline-code-face
ein:markdown-url-face))))))))
(defun ein:markdown-font-lock-ensure ()
"Provide `font-lock-ensure' in Emacs 24."
(if (fboundp 'font-lock-ensure)
(font-lock-ensure)
(with-no-warnings
;; Suppress warning about non-interactive use of
;; `font-lock-fontify-buffer' in Emacs 25.
(font-lock-fontify-buffer))))
;;; ein:markdown Parsing Functions ================================================
(define-obsolete-function-alias
@ -6961,24 +6951,6 @@ Translate filenames using `markdown-filename-translate-function'."
(add-text-properties start end props)
t)))
(defun ein:markdown-extend-changed-region (from to)
"Extend region given by FROM and TO so that we can fontify all links.
The region is extended to the first newline before and the first
newline after."
;; start looking for the first new line before 'from
(goto-char from)
(re-search-backward "\n" nil t)
(let ((new-from (point-min))
(new-to (point-max)))
(if (not (= (point) from))
(setq new-from (point)))
;; do the same thing for the first new line after 'to
(goto-char to)
(re-search-forward "\n" nil t)
(if (not (= (point) to))
(setq new-to (point)))
(cl-values new-from new-to)))
;;; Following & Doing =========================================================
(defun ein:markdown-follow-thing-at-point (_arg)
@ -7272,40 +7244,6 @@ Use matching function MATCHER."
"Add text properties to next tilde fenced code block from point to LAST."
(ein:markdown-fontify-code-blocks-generic 'ein:markdown-match-fenced-code-blocks last))
(require 'edit-indirect nil t)
(defvar edit-indirect-guess-mode-function)
(defvar edit-indirect-after-commit-functions)
(defun ein:markdown--edit-indirect-after-commit-function (_beg end)
"Ensure trailing newlines at the END of code blocks."
(goto-char end)
(unless (eq (char-before) ?\n)
(insert "\n")))
(defun ein:markdown-edit-code-block ()
"Edit ein:markdown code block in an indirect buffer."
(interactive)
(save-excursion
(if (fboundp 'edit-indirect-region)
(let* ((bounds (ein:markdown-get-enclosing-fenced-block-construct))
(begin (and bounds (goto-char (nth 0 bounds)) (point-at-bol 2)))
(end (and bounds (goto-char (nth 1 bounds)) (point-at-bol 1))))
(if (and begin end)
(let* ((lang (ein:markdown-code-block-lang))
(mode (or (and lang (ein:markdown-get-lang-mode lang))
ein:markdown-edit-code-block-default-mode))
(edit-indirect-guess-mode-function
(lambda (_parent-buffer _beg _end)
(funcall mode))))
(edit-indirect-region begin end 'display-buffer))
(user-error "Not inside a GFM or tilde fenced code block")))
(when (y-or-n-p "Package edit-indirect needed to edit code blocks. Install it now? ")
(progn (package-refresh-contents)
(package-install 'edit-indirect)
(ein:markdown-edit-code-block))))))
;;; Table Editing =============================================================
;; These functions were originally adapted from `org-table.el'.
@ -8134,12 +8072,7 @@ rows and columns and the column alignment."
;; Backwards compatibility with ein:markdown-css-path
(when (boundp 'ein:markdown-css-path)
(warn "ein:markdown-css-path is deprecated, see ein:markdown-css-paths.")
(add-to-list 'ein:markdown-css-paths ein:markdown-css-path))
;; edit-indirect
(add-hook 'edit-indirect-after-commit-functions
#'ein:markdown--edit-indirect-after-commit-function
nil 'local))
(add-to-list 'ein:markdown-css-paths ein:markdown-css-path)))
(ein:markdown-update-header-faces)
(provide 'ein-markdown-mode)

View file

@ -45,10 +45,10 @@
(require 'ein-kernelinfo)
(require 'ein-cell)
(require 'ein-worksheet)
(require 'ein-iexec)
(require 'ein-scratchsheet)
(require 'ein-notification)
(require 'ein-completer)
(require 'ein-pager)
(require 'ein-events)
(require 'ein-notification)
(require 'ein-kill-ring)
@ -131,6 +131,7 @@ Current buffer for these functions is set to the notebook buffer.")
;; is at:
;; https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping
(defvar ein:notebook-pager-buffer-name-template "*ein:pager %s/%s*")
(defvar ein:notebook-buffer-name-template "*ein: %s/%s*")
(ein:deflocal ein:%notebook% nil
@ -382,7 +383,14 @@ of minor mode."
(defun ein:notebook-bind-events (notebook events)
"Bind events related to PAGER to the event handler EVENTS."
(setf (ein:$notebook-events notebook) events)
(ein:worksheet-class-bind-events events))
(ein:worksheet-class-bind-events events)
;; Bind events for sub components:
(setf (ein:$notebook-pager notebook)
(ein:pager-new
(format ein:notebook-pager-buffer-name-template
(ein:$notebook-url-or-port notebook)
(ein:$notebook-notebook-name notebook))
(ein:$notebook-events notebook))))
(defalias 'ein:notebook-reconnect-kernel 'ein:notebook-reconnect-session-command "The distinction between kernel and session is a bit mysterious, all the action is now occurring in `ein:notebook-reconnect-session-command' these days, for which this function is now an alias.")
@ -462,14 +470,6 @@ This is equivalent to do ``C-c`` in the console program."
(interactive)
(ein:kernel-interrupt (ein:$notebook-kernel ein:%notebook%)))
;; autoexec
(defun ein:notebook-execute-autoexec-cells (notebook)
"Execute cells of which auto-execution flag is on."
(interactive (list (or ein:%notebook% (error "Not in notebook buffer!"))))
(mapc #'ein:worksheet-execute-autoexec-cells
(ein:$notebook-worksheets notebook)))
(define-obsolete-function-alias
'ein:notebook-eval-string
'ein:shared-output-eval-string "0.1.2")
@ -1170,7 +1170,6 @@ Tried add-function: the &rest from :around is an emacs-25 compilation issue."
(ein:notebook--define-key map (kbd "M-RET") ein:worksheet-execute-cell-and-goto-next)
(ein:notebook--define-key map (kbd "<M-S-return>")
ein:worksheet-execute-cell-and-insert-below)
(ein:notebook--define-key map (kbd "C-c C-'") ein:worksheet-turn-on-autoexec)
(ein:notebook--define-key map "\C-c\C-e" ein:worksheet-toggle-output)
(ein:notebook--define-key map "\C-c\C-v" ein:worksheet-set-output-visibility-all)
(ein:notebook--define-key map "\C-c\C-l" ein:worksheet-clear-output)
@ -1192,8 +1191,8 @@ Tried add-function: the &rest from :around is an emacs-25 compilation issue."
(ein:notebook--define-key map (kbd "C-<down>") ein:worksheet-goto-next-input)
(ein:notebook--define-key map (kbd "C-c <up>") ein:worksheet-move-cell-up)
(ein:notebook--define-key map (kbd "C-c <down>") ein:worksheet-move-cell-down)
(ein:notebook--define-key map (kbd "M-<up>") ein:worksheet-move-cell-up)
(ein:notebook--define-key map (kbd "M-<down>") ein:worksheet-move-cell-down)
(ein:notebook--define-key map (kbd "M-<up>") ein:worksheet-not-move-cell-up)
(ein:notebook--define-key map (kbd "M-<down>") ein:worksheet-not-move-cell-down)
(ein:notebook--define-key map "\C-c\C-h" ein:pytools-request-help)
(ein:notebook--define-key map (kbd "C-c C-$") ein:tb-show)
(ein:notebook--define-key map "\C-c\C-x" nil)

View file

@ -0,0 +1,98 @@
;;; ein-pager.el --- Pager module
;; Copyright (C) 2012- Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-pager.el 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.
;; ein-pager.el 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 ein-pager.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ansi-color)
(require 'ein-core)
(require 'ein-events)
(require 'view)
;; FIXME: Make a class with `:get-notebook-name' slot like `ein:worksheet'
(declare-function ess-help-underline "ess-help")
(defun ein:pager-new (name events)
;; currently pager = name.
(ein:pager-bind-events name events)
name)
(defun ein:pager-bind-events (pager events)
"Bind events related to PAGER to the event handler EVENTS."
(ein:events-on events
'open_with_text.Pager
#'ein:pager--open-with-text
pager))
(defun ein:pager--open-with-text (pager data)
(let ((text (plist-get data :text)))
(unless (equal (ein:trim text) "")
(ein:pager-clear pager)
(ein:pager-expand pager)
(ein:pager-append-text pager text))))
(defun ein:pager-clear (pager)
(ein:with-read-only-buffer (get-buffer-create pager)
(erase-buffer)))
(defun ein:pager-expand (pager)
(pop-to-buffer (get-buffer-create pager))
(goto-char (point-min)))
(defun ein:pager-append-text (pager text)
(ein:with-read-only-buffer (get-buffer-create pager)
(insert (ansi-color-apply text))
(if (featurep 'ess-help)
(ess-help-underline))
(unless (eql 'ein:pager-mode major-mode)
(ein:pager-mode))))
;; FIXME: this should be automatically called when opening pager.
(defun ein:pager-goto-docstring-bset-loc ()
"Goto the best location of the documentation."
(interactive)
(goto-char (point-min))
(search-forward-regexp "^Docstring:")
(beginning-of-line 0)
(recenter 0))
(defvar ein:pager-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-c\C-b" 'ein:pager-goto-docstring-bset-loc)
map)
"Keymap for ein:pager-mode.")
(define-derived-mode ein:pager-mode view-mode "ein:pager"
"IPython notebook pager mode.
Commands:
\\{ein:pager-mode-map}"
(setq-local view-no-disable-on-exit t)
(font-lock-mode))
(provide 'ein-pager)
;;; ein-pager.el ends here

Binary file not shown.

View file

@ -1,4 +1,4 @@
(define-package "ein" "20200205.1547" "Emacs IPython Notebook"
(define-package "ein" "20200212.238" "Emacs IPython Notebook"
'((emacs "25")
(websocket "20190620.338")
(anaphora "20180618")

View file

@ -0,0 +1,65 @@
;;; ein-pytools.el --- Python tools build on top of kernel
;; Copyright (C) 2012- Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-pytools.el 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.
;; ein-pytools.el 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 ein-pytools.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ein-kernel)
(require 'ein-notebook)
(defun ein:pytools-request-help (kernel func)
(interactive (list (ein:get-kernel-or-error)
(ein:object-at-point-or-error)))
(ein:kernel-execute kernel
(format "%s?" func) ; = code
nil ; = callbacks
;; It looks like that magic command does
;; not work in silent mode.
:silent nil))
(defun ein:pytools-jump-to-source-command (&optional other-window)
"Jump to the source code of the object at point.
When the prefix argument ``C-u`` is given, open the source code
in the other window. You can explicitly specify the object by
selecting it."
(interactive "P")
(cl-letf (((symbol-function 'xref--prompt-p) #'ignore))
(if other-window
(call-interactively #'xref-find-definitions-other-window)
(call-interactively #'xref-find-definitions))))
(defun ein:pytools-jump-back-command (&optional other-window)
"Go back to the point where `ein:pytools-jump-to-source-command'
is executed last time. When the prefix argument ``C-u`` is
given, open the last point in the other window."
(interactive "P")
(call-interactively #'xref-pop-marker-stack))
(define-obsolete-function-alias
'ein:pytools-eval-string-internal
'ein:shared-output-eval-string "0.1.2")
(provide 'ein-pytools)
;;; ein-pytools.el ends here

Binary file not shown.

View file

@ -56,9 +56,7 @@
Called from ewoc pretty printer via `ein:cell-pp'."
;; Newline is inserted in `ein:cell-insert-input'.
(ein:insert-read-only
(concat
(format "In [%s]" (or (ein:oref-safe cell 'input-prompt-number) " "))
(when (slot-value cell 'autoexec) " %s" ein:cell-autoexec-prompt))
(format "In [%s]" (or (ein:oref-safe cell 'input-prompt-number) " "))
'font-lock-face 'ein:cell-input-prompt))
(cl-defmethod ein:cell-execute ((cell ein:shared-output-cell) kernel code

View file

@ -33,6 +33,7 @@
(require 'ein-utils)
(require 'ein-cell)
(require 'ein-kill-ring)
(require 'warnings)
(require 'poly-ein)
;;; Configuration
@ -40,6 +41,11 @@
;; (define-obsolete-variable-alias
;; 'ein:notebook-enable-undo 'ein:worksheet-enable-undo "0.2.0")
(defcustom ein:worksheet-warn-obsolesced-keybinding t
"Warn of keybindings we arbitrarily obsolesce."
:type 'boolean
:group 'ein)
(defcustom ein:worksheet-enable-undo t
"When non-`nil', allow undo of cell inputs only (as opposed to
whole-cell operations such as killing, moving, executing cells).
@ -948,6 +954,26 @@ It is set in `ein:notebook-multilang-mode'."
(poly-ein-fontify-buffer (ein:worksheet--get-buffer ein:%worksheet%))))
(message "No %s cell" (if up "previous" "next"))))
(defun ein:worksheet-not-move-cell (which)
(when ein:worksheet-warn-obsolesced-keybinding
(ein:display-warning-once
(mapconcat #'identity
'("M-<up> and M-<down> no longer move cells."
"Use C-c <up> and C-c <down>."
"Custom set variable `ein:worksheet-warn-obsolesced-keybinding' to disable this warning.") "\n")
warning-minimum-level))
(call-interactively (cl-some #'identity
(mapcar (lambda (pair) (lookup-key (cdr pair) which))
(cdr minor-mode-map-alist)))))
(defun ein:worksheet-not-move-cell-up (&rest _args)
(interactive)
(ein:worksheet-not-move-cell (kbd "M-<up>")))
(defun ein:worksheet-not-move-cell-down (&rest _args)
(interactive)
(ein:worksheet-not-move-cell (kbd "M-<down>")))
(defun ein:worksheet-move-cell-up (ws cell)
(interactive (list (ein:worksheet--get-ws-or-error)
(ein:worksheet-get-current-cell)))
@ -1021,18 +1047,24 @@ Do not clear input prompts when the prefix argument is given."
(mapc (lambda (cell) (setf (slot-value cell 'kernel) (slot-value ws 'kernel)))
(seq-filter #'ein:codecell-p (ein:worksheet-get-cells ws))))
(defun ein:worksheet-execute-cell (ws cell)
(defun ein:worksheet-execute-cell (ws cell &optional batch)
"Execute code type CELL."
(interactive (list (ein:worksheet--get-ws-or-error)
(ein:worksheet-get-current-cell
:cell-p #'ein:codecell-p)))
(interactive `(,(ein:worksheet--get-ws-or-error)
,(ein:worksheet-get-current-cell)
,(when current-prefix-arg
(prog1 (read-char-choice "[RET]all [a]bove [b]elow: " (list ?\r ?a ?b))
(message "")))))
(ein:kernel-when-ready (slot-value ws 'kernel)
(apply-partially
(lambda (ws* cell* kernel)
(ein:cell-execute cell*)
(oset ws* :dirty t)
(ein:worksheet--unshift-undo-list cell*))
ws cell))
(lambda (ws* cell* batch* _kernel)
(cl-case batch*
(?\r (ein:worksheet-execute-all-cells ws*))
(?a (ein:worksheet-execute-all-cells ws* :above cell*))
(?b (ein:worksheet-execute-all-cells ws* :below cell*))
(t (ein:cell-execute cell*)
(oset ws* :dirty t)
(ein:worksheet--unshift-undo-list cell*))))
ws cell batch))
cell)
(defun ein:worksheet-execute-cell-and-goto-next (ws cell &optional insert)
@ -1060,34 +1092,37 @@ cell bellow."
"Execute all cells in the current worksheet buffer.
If :above or :below specified, execute above/below the current cell."
(interactive (list (ein:worksheet--get-ws-or-error)))
(let* ((all (seq-filter #'ein:codecell-p (ein:worksheet-get-cells ws)))
(current-id (aif (ein:worksheet-get-current-cell) (slot-value it 'cell-id)))
(not-matching (apply-partially (lambda (my other)
(not (string= (slot-value other 'cell-id) my)))
current-id)))
(mapc #'ein:cell-execute
(if (or above below)
(append (when (and current-id above)
(aif (seq-take-while not-matching all)
it
(prog1 nil
(ein:log 'info
"ein:worksheet-execute-all-cells: no cells above current"))))
(when (and current-id below)
(seq-drop-while not-matching all)))
all))))
(let ((all (ein:worksheet-get-cells ws)))
(mapc (apply-partially #'ein:worksheet-execute-cell ws)
(seq-filter
#'ein:codecell-p
(aif (or above below)
(-when-let* ((current-id (slot-value it 'cell-id))
(not-matching (apply-partially
(lambda (my other)
(not (string= (slot-value other 'cell-id) my)))
current-id)))
(append (when above
(aif (seq-take-while not-matching all)
it
(prog1 nil
(ein:log 'info
"ein:worksheet-execute-all-cells: no cells above current"))))
(when below
(seq-drop-while not-matching all))))
all)))))
(defun ein:worksheet-execute-all-cells-above (ws)
"Execute all cells above the current cell (exclusively) in the
current worksheet buffer."
(interactive (list (ein:worksheet--get-ws-or-error)))
(ein:worksheet-execute-all-cells ws :above t))
(ein:worksheet-execute-all-cells ws :above (ein:worksheet-get-current-cell)))
(defun ein:worksheet-execute-all-cells-below (ws)
"Execute all cells below the current cell (inclusively) in the
current worksheet buffer."
(interactive (list (ein:worksheet--get-ws-or-error)))
(ein:worksheet-execute-all-cells ws :below t))
(ein:worksheet-execute-all-cells ws :below (ein:worksheet-get-current-cell)))
;;; Metadata
@ -1144,43 +1179,6 @@ current worksheet buffer."
(indent-rigidly
beg end (- (ein:find-leftmost-column beg end)))))
;;; Auto-execution
(defun ein:worksheet-toggle-autoexec (cell)
"Toggle auto-execution flag of the cell at point."
(interactive (list (ein:worksheet-get-current-cell #'ein:codecell-p)))
(ein:cell-toggle-autoexec cell))
(defun ein:worksheet-turn-on-autoexec (cells &optional off)
"Turn on auto-execution flag of the cells in region or cell at point.
When the prefix argument is given, turn off the flag instead. Questionable."
(interactive
(list (ein:worksheet-get-cells-in-region-or-at-point
:cell-p #'ein:codecell-p)
current-prefix-arg))
(mapc (lambda (c) (ein:cell-set-autoexec c (not off))) cells)
(ein:log 'info "Turn %s auto-execution flag of %s cells."
(if off "off" "on")
(length cells)))
(defun ein:worksheet-execute-autoexec-cells (ws)
"Execute cells of which auto-execution flag is on.
This function internally sets current buffer to the worksheet
buffer, so you don't need to set current buffer to call this
function."
(interactive (list (ein:worksheet--get-ws-or-error)))
(ein:with-live-buffer (ein:worksheet-buffer ws)
(ein:kernel-when-ready
(slot-value ws 'kernel)
(apply-partially
(lambda (ws buffer kernel)
(with-current-buffer buffer
(let ((buffer-undo-list t))
(mapc #'ein:cell-execute
(seq-filter #'ein:cell-autoexec-p
(ein:worksheet-get-cells ws))))))
ws (current-buffer)))))
;;; Workarounds
(defadvice fill-paragraph (around ein:worksheet-fill-paragraph activate)

View file

@ -6,7 +6,7 @@
(defmacro poly-ein--remove-hook (label functions)
"Remove any hooks saying LABEL from FUNCTIONS"
`(mapc (lambda (x) (when (cl-search ,label (symbol-name x))
`(mapc (lambda (x) (when (and (symbolp x) (cl-search ,label (symbol-name x)))
(remove-hook (quote ,functions) x t)))
,functions))
@ -64,26 +64,27 @@
(fmakunbound 'poly-lock-mode)
(defalias 'poly-lock-mode (symbol-function (default-value 'font-lock-function)))
(defun poly-ein--syntax-propertize (pos)
(prog1 poly-ein-mode
(when (and poly-ein-mode (< syntax-propertize--done pos))
(save-excursion
;; pared down from default `syntax-propertize'
(with-silent-modifications
(let ((parse-sexp-lookup-properties t)
(start (point-min)) ;; i've narrowed in the :around
(end (point-max))
(span (pm-innermost-span pos)))
(setq syntax-propertize--done end)
(when (eq 'body (nth 0 span))
(remove-text-properties start end
'(syntax-table nil syntax-multiline nil))
;; avoid recursion if syntax-propertize-function calls me (syntax-propertize)
(when syntax-propertize-function
(let ((syntax-propertize--done most-positive-fixnum))
(funcall syntax-propertize-function start end))))))))))
(add-function
:before-until (symbol-function 'syntax-propertize)
(lambda (pos)
(prog1 poly-ein-mode
(when (and poly-ein-mode (< syntax-propertize--done pos))
(save-excursion
;; pared down from default `syntax-propertize'
(with-silent-modifications
(let ((parse-sexp-lookup-properties t)
(start (point-min)) ;; i've narrowed in the :around
(end (point-max))
(span (pm-innermost-span pos)))
(setq syntax-propertize--done end)
(when (eq 'body (nth 0 span))
(remove-text-properties start end
'(syntax-table nil syntax-multiline nil))
;; avoid recursion if syntax-propertize-function calls me (syntax-propertize)
(when syntax-propertize-function
(let ((syntax-propertize--done most-positive-fixnum))
(funcall syntax-propertize-function start end)))))))))))
#'poly-ein--syntax-propertize)
(add-function
:around (symbol-function 'syntax-propertize)
@ -263,6 +264,7 @@ TYPE can be 'body, nil."
(buffer-local-value 'after-change-functions (pm-base-buffer)))
(poly-ein-copy-state (pm-base-buffer) (current-buffer))
(setq-local font-lock-dont-widen t)
(setq-local syntax-propertize-chunks 0) ;; internal--syntax-propertize too far
(ein:notebook-mode))
(defcustom pm-host/ein

View file

@ -0,0 +1,28 @@
;;; gntp-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name
(or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "gntp" "gntp.el" (0 0 0 0))
;;; Generated autoloads from gntp.el
(autoload 'gntp-notify "gntp" "\
Send notification NAME with TITLE, TEXT, PRIORITY and ICON to SERVER:PORT.
PORT defaults to `gntp-server-port'
\(fn NAME TITLE TEXT SERVER &optional PORT PRIORITY ICON)" nil nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "gntp" '("gntp-")))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; coding: utf-8
;; End:
;;; gntp-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "gntp" "20141025.250" "Growl Notification Protocol for Emacs" 'nil :commit "767571135e2c0985944017dc59b0be79af222ef5" :authors '(("Engelke Eschner" . "tekai@gmx.li")) :maintainer '("Engelke Eschner" . "tekai@gmx.li"))

View file

@ -0,0 +1,243 @@
;;; gntp.el --- Growl Notification Protocol for Emacs -*- lexical-binding: t -*-
;; Author: Engelke Eschner <tekai@gmx.li>
;; Version: 0.1
;; Package-Version: 20141025.250
;; Created: 2013-03-21
;; LICENSE
;; Copyright (c) 2013 Engelke Eschner
;; All rights reserved.
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;; * Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;; * Redistributions in binary form must reproduce the above
;; copyright notice, this list of conditions and the following
;; disclaimer in the documentation and/or other materials provided
;; with the distribution.
;; * Neither the name of the gntp.el nor the names of its
;; contributors may be used to endorse or promote products derived
;; from this software without specific prior written permission.
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
;; HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
;; OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;; Commentary:
;; This package implements the Growl Notification Protocol GNTP
;; described at http://www.growlforwindows.com/gfw/help/gntp.aspx
;; It is incomplete as it only lets you send but not receive
;; notifications.
;;; Code:
(defgroup gntp nil
"GNTP, send/register growl notifications via GNTP from within emacs."
:group 'external)
(defcustom gntp-application-name "Emacs/gntp.el"
"Name of the application gntp registers itself."
:type '(string))
(defcustom gntp-application-icon nil
"Icon to display as the application icon.
Either a URL or a path to a file."
:type '(string))
(defcustom gntp-server "localhost"
"Default port of the server.
Standard says can't be changed, but port-forwarding etc."
:type '(string))
(defcustom gntp-server-port 23053
"Default port of the server.
Standard says can't be changed, but port-forwarding etc."
:type '(integer))
(defcustom gntp-register-alist nil
"Registration item list."
:type '(choice string (const nil)))
(defun gntp-register (&optional notifications server port)
(interactive)
"Register NOTIFICATIONS at SERVER:PORT.
PORT defaults to `gntp-server-port'."
(let ((message (gntp-build-message-register (if notifications notifications gntp-register-alist))))
(gntp-send message (if server server gntp-server) port)))
;;;###autoload
(defun gntp-notify (name title text server &optional port priority icon)
"Send notification NAME with TITLE, TEXT, PRIORITY and ICON to SERVER:PORT.
PORT defaults to `gntp-server-port'"
(let ((message (gntp-build-message-notify name title text priority icon)))
(gntp-send message server port)))
(defun gntp-build-message-register (notifications)
"Build the message to register NOTIFICATIONS types."
(let ((lines (list "GNTP/1.0 REGISTER NONE"
(format "Application-Name: %s"
gntp-application-name)
(format "Notifications-Count: %d"
(length notifications))))
(icon-uri (gntp-app-icon-uri))
(icon-data (gntp-app-icon-data))
(icons (list)))
;; append icon uri
(when icon-uri
(nconc lines (list (format "Application-Icon: %s" icon-uri)))
;; and data when it exists
(when icon-data
(setq icons (cons icon-data icons))))
(dolist (notice notifications)
;; "For each notification being registered:
;; Each notification being registered should be seperated by a
;; blank line, including the first notification
(nconc lines (cons "" (gntp-notification-lines notice)))
;; c
(let ((icon (gntp-notice-icon-data notice)))
(when icon
(nconc icons (list "" icon)))))
;; icon data must come last
(when icons
(nconc lines (cons "" icons)))
(mapconcat 'identity (remove nil lines) "\r\n")))
(defun gntp-notification-lines (notice)
"Transform NOTICE into a list of strings."
(let ((display-name (gntp-notice-get notice :display))
(enabled (gntp-notice-get notice :enabled))
(icon-uri (gntp-notice-icon-uri notice)))
(list
;; Required - The name (type) of the notification being registered
(concat "Notification-Name: " (gntp-notice-name notice))
;; Optional - The name of the notification that is displayed to
;; the user (defaults to the same value as Notification-Name)
(when display-name
(concat "Notification-Display-Name: " display-name))
;; Optional - Indicates if the notification should be enabled by
;; default (defaults to False)
(when enabled
"Notification-Enabled: True")
;; Optional - The default icon to use for notifications of this type
(when icon-uri
(concat "Notification-Icon: " icon-uri)))))
(defun gntp-build-message-notify (name title text &optional priority icon)
"Build a message of type NAME with TITLE and TEXT."
(format
"GNTP/1.0 NOTIFY NONE\r\n\
Application-Name: %s\r\n\
Notification-Name: %s\r\n\
Notification-Title: %s\r\n\
Notification-Text: %s\r\n\
Notification-Priority: %s\r\n\
Notification-Icon: %s\r\n\
\r\n"
gntp-application-name
(if (symbolp name) (symbol-name name) name)
title
;; no CRLF in the text to avoid accidentel msg end
(replace-regexp-in-string "\r\n" "\n" text)
(if priority priority "0")
(if icon (gntp-icon-uri icon) "")))
;; notice
;;(list name ; everthing else is optional
;; :display "name to display"
;; :enabled nil
;; :icon "url or file")
(defun gntp-notice-icon-uri (notice)
"Get the icon URI from NOTICE."
(gntp-icon-uri (gntp-notice-get notice :icon)))
(defun gntp-notice-icon-data (notice)
"Get icon data from NOTICE."
(gntp-icon-data (gntp-notice-get notice :icon)))
(defun gntp-app-icon-uri ()
"Return the value to be used in the Application-Icon header."
(gntp-icon-uri gntp-application-icon))
(defun gntp-app-icon-data ()
"Return the value to be used in the Application-Icon header."
(gntp-icon-data gntp-application-icon))
(defun gntp-icon-uri (icon)
"Get the URI of ICON."
(when icon
(cond ((string-equal (substring icon 0 7) "http://") icon)
((and (file-exists-p icon) (file-readable-p icon))
(concat "x-growl-resource://" (md5 icon))))))
(defun gntp-icon-data (icon)
"Get the URI of ICON."
(when (and icon (not (string-equal (substring icon 0 7) "http://"))
(file-exists-p icon) (file-readable-p icon))
(let ((id (md5 icon))
(data (gntp-file-string icon)))
(format "Identifier: %s\r\nLength: %d\r\n\r\n%s"
id (length data) data))))
(defun gntp-notice-name (notice)
"Get the name of NOTICE. The name must be either a symbol or string."
(let ((name (car notice)))
(if (symbolp name)
(symbol-name name)
name)))
(defun gntp-notice-get (notice property)
"Get PROPERTY from NOTICE."
(plist-get (cdr notice) property))
(defun gntp-send (message server &optional port)
"Send MESSAGE to SERVER:PORT. PORT defaults to `gntp-server-port'."
(let ((proc (make-network-process
:name "gntp"
:host server
:server nil
:service (if port port gntp-server-port)
;;:sentinel 'gntp-sentinel
:filter 'gntp-filter)))
;; hmm one CRLF too much?
(process-send-string proc (concat message "\r\n\r\n\r\n"))))
(defun gntp-filter (proc string)
"Filter for PROC started by `gntp-send'.
Argument STRING reply from the server."
(when (string-equal "GNTP/1.0 -ERROR" (substring string 0 15))
(error "GNTP: Something went wrong take a look at the reply:\n %s"
string)))
;; (defun gntp-sentinel (proc msg)
;; (when (string= msg "connection broken by remote peer\n")
;; (message (format "client %s has quit" proc))))
(defun gntp-file-string (file)
"Read the contents of a FILE and return as a string."
(with-temp-buffer
(insert-file-contents-literally file)
(buffer-string)))
(provide 'gntp)
;;; gntp.el ends here

Binary file not shown.

View file

@ -0,0 +1,35 @@
;;; log4e-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name
(or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "log4e" "log4e.el" (0 0 0 0))
;;; Generated autoloads from log4e.el
(autoload 'log4e-mode "log4e" "\
Major mode for browsing a buffer made by log4e.
\\<log4e-mode-map>
\\{log4e-mode-map}
\(fn)" t nil)
(autoload 'log4e:insert-start-log-quickly "log4e" "\
Insert logging statment for trace level log at start of current function/macro.
\(fn)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "log4e" '("log4e")))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; coding: utf-8
;; End:
;;; log4e-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "log4e" "20170401.1304" "provide logging framework for elisp" 'nil :commit "c69424e407be0d9d0e54b427d8b18b1ac5a607e2" :keywords '("log") :authors '(("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) :maintainer '("Hiroaki Otsu" . "ootsuhiroaki@gmail.com") :url "https://github.com/aki2o/log4e")

View file

@ -0,0 +1,592 @@
;;; log4e.el --- provide logging framework for elisp
;; Copyright (C) 2013 Hiroaki Otsu
;; Author: Hiroaki Otsu <ootsuhiroaki@gmail.com>
;; Keywords: log
;; Package-Version: 20170401.1304
;; URL: https://github.com/aki2o/log4e
;; Version: 0.3.1
;; 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 file 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 extension provides logging framework for elisp.
;;; Dependency:
;;
;; Nothing.
;;; Installation:
;;
;; Put this to your load-path.
;; And put the following lines in your elisp file.
;;
;; (require 'log4e)
;;; Configuration:
;;
;; See <https://github.com/aki2o/log4e/blob/master/README.md>
;; Otherwise, eval following sexp.
;; (describe-function 'log4e:deflogger)
;;; API:
;;
;; [EVAL] (autodoc-document-lisp-buffer :type 'command :prefix "log4e:" :docstring t)
;; `log4e:next-log'
;; Move to start of next log on log4e-mode.
;; `log4e:previous-log'
;; Move to start of previous log on log4e-mode.
;; `log4e:insert-start-log-quickly'
;; Insert logging statment for trace level log at start of current function/macro.
;;
;; *** END auto-documentation
;;
;; For detail, see <https://github.com/aki2o/log4e/blob/master/README.md>
;;
;; [Note] Other than listed above, Those specifications may be changed without notice.
;;; Tested On:
;;
;; - Emacs ... GNU Emacs 23.3.1 (i386-mingw-nt5.1.2600) of 2011-08-15 on GNUPACK
;; Enjoy!!!
;;; Code:
(eval-when-compile (require 'cl))
(require 'rx)
(defconst log4e-log-level-alist '((fatal . 6)
(error . 5)
(warn . 4)
(info . 3)
(debug . 2)
(trace . 1))
"Alist of log level value.")
(defconst log4e-default-logging-function-name-alist '((fatal . "log-fatal")
(error . "log-error")
(warn . "log-warn")
(info . "log-info")
(debug . "log-debug")
(trace . "log-trace"))
"Alist of logging function name at default.")
(defmacro log4e--def-symmaker (symnm)
`(progn
(defsubst ,(intern (concat "log4e--make-symbol-" symnm)) (prefix)
(intern (concat ,(format "log4e--%s-" symnm) prefix)))))
(log4e--def-symmaker "log-buffer")
(log4e--def-symmaker "msg-buffer")
(log4e--def-symmaker "log-template")
(log4e--def-symmaker "time-template")
(log4e--def-symmaker "min-level")
(log4e--def-symmaker "max-level")
(log4e--def-symmaker "toggle-logging")
(log4e--def-symmaker "toggle-debugging")
(log4e--def-symmaker "buffer-coding-system")
(log4e--def-symmaker "author-mail-address")
(defmacro log4e--def-level-logger (prefix suffix level)
(let ((argform (if suffix
'(msg &rest msgargs)
'(level msg &rest msgargs)))
(buff (log4e--make-symbol-log-buffer prefix))
(codsys (log4e--make-symbol-buffer-coding-system prefix))
(logtmpl (log4e--make-symbol-log-template prefix))
(timetmpl (log4e--make-symbol-time-template prefix))
(minlvl (log4e--make-symbol-min-level prefix))
(maxlvl (log4e--make-symbol-max-level prefix))
(logging-p (log4e--make-symbol-toggle-logging prefix)))
`(progn
;; Define logging function
(defun ,(intern (concat prefix "--" (or suffix "log"))) ,argform
,(format "Do logging for %s level log.
%sMSG/MSGARGS are passed to `format'."
(or (eval level) "any")
(if suffix "" "LEVEL is symbol as a log level in '(trace debug info warn error fatal).\n"))
(let ((log4e--current-msg-buffer ,(log4e--make-symbol-msg-buffer prefix)))
(apply 'log4e--logging ,buff ,codsys ,logtmpl ,timetmpl ,minlvl ,maxlvl ,logging-p ,(if suffix level 'level) msg msgargs)))
;; Define logging macro
(defmacro ,(intern (concat prefix "--" (or suffix "log") "*")) ,argform
,(format "Do logging for %s level log.
%sMSG/MSGARGS are passed to `format'.
Evaluation of MSGARGS is invoked only if %s level log should be printed."
(or (eval level) "any")
(if suffix "" "LEVEL is symbol as a log level in '(trace debug info warn error fatal).\n")
(or (eval level) "the"))
(let ((prefix ,prefix)
(suffix ,suffix)
(level ',level)
(msg msg)
(msgargs msgargs)
(buff (log4e--make-symbol-log-buffer ,prefix))
(codsys (log4e--make-symbol-buffer-coding-system ,prefix))
(logtmpl (log4e--make-symbol-log-template ,prefix))
(timetmpl (log4e--make-symbol-time-template ,prefix))
(minlvl (log4e--make-symbol-min-level ,prefix))
(maxlvl (log4e--make-symbol-max-level ,prefix))
(logging-p (log4e--make-symbol-toggle-logging ,prefix)))
`(let ((log4e--current-msg-buffer ,(log4e--make-symbol-msg-buffer prefix)))
(when (and ,logging-p
(log4e--logging-level-p ,minlvl ,maxlvl ,level))
(log4e--logging ,buff ,codsys ,logtmpl ,timetmpl ,minlvl ,maxlvl ,logging-p ,(if suffix level 'level) ,msg ,@msgargs)))))
)))
(defsubst log4e--logging-level-p (minlevel maxlevel currlevel)
(let ((minlvlvalue (or (assoc-default minlevel log4e-log-level-alist)
1))
(maxlvlvalue (or (assoc-default maxlevel log4e-log-level-alist)
6))
(currlvlvalue (or (assoc-default currlevel log4e-log-level-alist)
0)))
(and (>= currlvlvalue minlvlvalue)
(<= currlvlvalue maxlvlvalue))))
(defsubst log4e--get-or-create-log-buffer (buffnm &optional codesys)
(or (get-buffer buffnm)
(let ((buff (get-buffer-create buffnm)))
(with-current-buffer buff
(log4e-mode)
(when codesys
(setq buffer-file-coding-system codesys)))
buff)))
(defvar log4e--regexp-msg-format
(rx-to-string `(and "%"
(* (any "+#-0")) ; flags
(* (any "0-9")) ; width
(? "." (+ (any "0-9"))) ; precision
(any "a-zA-Z"))))
(defsubst log4e--insert-log (logtmpl timetmpl level msg msgargs propertize-p)
(let ((timetext (format-time-string timetmpl))
(lvltext (format "%-05s" (upcase (symbol-name level))))
(buffer-read-only nil))
(when propertize-p
(put-text-property 0 (length timetext) 'face 'font-lock-doc-face timetext)
(put-text-property 0 (length lvltext) 'face 'font-lock-keyword-face lvltext))
(let* ((logtext logtmpl)
(logtext (replace-regexp-in-string "%t" timetext logtext))
(logtext (replace-regexp-in-string "%l" lvltext logtext))
(logtext (replace-regexp-in-string "%m" msg logtext))
(begin (point)))
(insert logtext "\n")
(when propertize-p
(put-text-property begin (+ begin 1) 'log4e--level level))
(loop initially (goto-char begin)
while (and msgargs
(re-search-forward log4e--regexp-msg-format nil t))
for currtype = (match-string-no-properties 0)
for currarg = (pop msgargs)
for failfmt = nil
for currtext = (condition-case e
(format currtype currarg)
(error (setq failfmt t)
(format "=%s=" (error-message-string e))))
if propertize-p
do (ignore-errors
(cond (failfmt (put-text-property 0 (length currtext) 'face 'font-lock-warning-face currtext))
(t (put-text-property 0 (length currtext) 'face 'font-lock-string-face currtext))))
do (replace-match currtext t t))
(goto-char begin))))
(defvar log4e--current-msg-buffer nil)
;; We needs this signature be stay for other compiled plugins using old version
(defun log4e--logging (buffnm codsys logtmpl timetmpl minlevel maxlevel logging-p level msg &rest msgargs)
(when (and logging-p
(log4e--logging-level-p minlevel maxlevel level))
(save-match-data
(with-current-buffer (log4e--get-or-create-log-buffer buffnm codsys)
(goto-char (point-max))
(let* ((buffer-read-only nil)
(begin (point))
(currlog (progn
(log4e--insert-log logtmpl timetmpl level msg msgargs t)
(goto-char (point-max))
(buffer-substring-no-properties begin (point))))
(msgbuf (or (when (and log4e--current-msg-buffer
(not (eq log4e--current-msg-buffer t)))
(ignore-errors (get-buffer log4e--current-msg-buffer)))
log4e--current-msg-buffer)))
(when msgbuf
(let ((standard-output (if (buffer-live-p msgbuf)
msgbuf
standard-output)))
(princ currlog))))
nil))))
(defun log4e--get-current-log-line-level ()
(save-excursion
(beginning-of-line)
(get-text-property (point) 'log4e--level)))
;; We needs this signature be stay for other plugins compiled with this old version
(defun log4e--clear-log (buffnm)
(with-current-buffer (log4e--get-or-create-log-buffer buffnm)
(setq buffer-read-only nil)
(erase-buffer)))
;; We needs this signature be stay for other plugins compiled with this old version
(defun log4e--open-log (buffnm)
(let* ((buff (get-buffer buffnm)))
(if (not (buffer-live-p buff))
(message "[Log4E] Not exist log buffer.")
(with-current-buffer buff
(setq buffer-read-only t))
(pop-to-buffer buff))))
;; We needs this signature be stay for other plugins compiled with this old version
(defun log4e--open-log-if-debug (buffnm dbg)
(when dbg
(log4e--open-log buffnm)))
;; (defun log4e--send-report-if-not-debug (buffnm dbg addr prefix)
;; (let* ((buff (get-buffer buffnm)))
;; (when (and (not dbg)
;; (stringp addr)
;; (buffer-live-p buff))
;; (reporter-submit-bug-report addr prefix nil nil nil nil))))
(defmacro log4e:deflogger (prefix msgtmpl timetmpl &optional log-function-name-custom-alist)
"Define the functions of logging for your elisp.
Specification:
After eval this, you can use the functions for supporting about logging. They are the following ...
- do logging for each log level. Log level are trace, debug, info, warn, error and fatal.
- set max and min log level.
- switch logging.
- switch debugging.
- open and clear log buffer.
- send bug report for you.
For details, see Functions section.
Argument:
- PREFIX is string as your elisp prefix.
- MSGTMPL is string as format of log. The following words has a special meaning.
- %t ... Replaced with time string. About it, see TIMETMPL argument.
- %l ... Replaced with log level. They are 'TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'.
- %m ... Replaced with log message that passed by you.
- TIMETMPL is string as format of time. This value is passed to `format-time-string'.
- LOG-FUNCTION-NAME-CUSTOM-ALIST is alist as the function name of logging.
- If this value is nil, define the following functions.
yourprefix--log-trace
yourprefix--log-debug
...
yourprefix--log-fatal
- If you want to custom the name of them, give like the following value.
'((fatal . \"fatal\")
(error . \"error\")
(warn . \"warn\")
(info . \"info\")
(debug . \"debug\")
(trace . \"trace\"))
Then, define the following functions.
yourprefix--trace
yourprefix--debug
...
yourprefix--fatal
Functions:
List all functions defined below. PREFIX is your prefix.
- PREFIX--log-fatal ... #1
- PREFIX--log-error ... #1
- PREFIX--log-warn ... #1
- PREFIX--log-info ... #1
- PREFIX--log-debug ... #1
- PREFIX--log-trace ... #1
- PREFIX--log-fatal* ... #2
- PREFIX--log-error* ... #2
- PREFIX--log-warn* ... #2
- PREFIX--log-info* ... #2
- PREFIX--log-debug* ... #2
- PREFIX--log-trace* ... #2
- PREFIX--log
- PREFIX--log-set-level
- PREFIX--log-enable-logging ... #3
- PREFIX--log-disable-logging ... #3
- PREFIX--log-enable-messaging ... #3
- PREFIX--log-disable-messaging ... #3
- PREFIX--log-enable-debugging ... #3
- PREFIX--log-disable-debugging ... #3
- PREFIX--log-debugging-p
- PREFIX--log-set-coding-system
- PREFIX--log-set-author-mail-address
- PREFIX--log-clear-log ... #3
- PREFIX--log-open-log ... #3
- PREFIX--log-open-log-if-debug
#1 : You can customize this name
#2 : Name is a #1 name + \"*\"
#3 : This is command
Example:
;; If you develop elisp that has prefix \"hoge\", write and eval the following sexp in your elisp file.
(require 'log4e)
(log4e:deflogger \"hoge\" \"%t [%l] %m\" \"%H:%M:%S\")
;; Eval the following
(hoge--log-enable-logging)
;; Then, write the following
(defun hoge-do-hoge (hoge)
(if (not (stringp hoge))
(hoge--log-fatal \"failed do hoge : hoge is '%s'\" hoge)
(hoge--log-debug \"start do hoge about '%s'\" hoge)
(message \"hoge!\")
(hoge--log-info \"done hoge about '%s'\" hoge)))
;; Eval the following
(hoge-do-hoge \"HOGEGE\")
;; Do M-x hoge--log-open-log
;; Open the buffer which name is \" *log4e-hoge*\". The buffer string is below
12:34:56 [INFO ] done hoge about 'HOGEGE'
;; Eval the following
(hoge--log-set-level 'trace)
(hoge-do-hoge \"FUGAGA\")
;; Do M-x hoge--log-open-log
;; Open the buffer. its string is below
12:34:56 [INFO ] done hoge about 'HOGEGE'
12:35:43 [DEBUG] start do hoge about 'FUGAGA'
12:35:43 [INFO ] done hoge about 'FUGAGA'
"
(declare (indent 0))
(if (or (not (stringp prefix)) (string= prefix "")
(not (stringp msgtmpl)) (string= msgtmpl "")
(not (stringp timetmpl)) (string= timetmpl ""))
(message "[LOG4E] invalid argument of deflogger")
(let* ((bufsym (log4e--make-symbol-log-buffer prefix))
(msgbufsym (log4e--make-symbol-msg-buffer prefix))
(logtmplsym (log4e--make-symbol-log-template prefix))
(timetmplsym (log4e--make-symbol-time-template prefix))
(minlvlsym (log4e--make-symbol-min-level prefix))
(maxlvlsym (log4e--make-symbol-max-level prefix))
(tglsym (log4e--make-symbol-toggle-logging prefix))
(dbgsym (log4e--make-symbol-toggle-debugging prefix))
(codsyssym (log4e--make-symbol-buffer-coding-system prefix))
(addrsym (log4e--make-symbol-author-mail-address prefix))
(funcnm-alist (loop with custom-alist = (car (cdr log-function-name-custom-alist))
for lvl in '(fatal error warn info debug trace)
for lvlpair = (assq lvl custom-alist)
for fname = (or (cdr-safe lvlpair) "")
collect (or (if (string-match "\*" fname)
(progn
(message "[LOG4E] ignore %s level name in log-function-name-custom-alist. can't use '*' for the name." lvl)
nil)
lvlpair)
(assq lvl log4e-default-logging-function-name-alist)))))
`(progn
;; Define variable for prefix
(defvar ,bufsym (format " *log4e-%s*" ,prefix))
(defvar ,logtmplsym ,msgtmpl)
(defvar ,timetmplsym ,timetmpl)
(defvar ,minlvlsym 'info)
(defvar ,maxlvlsym 'fatal)
(defvar ,tglsym nil)
(defvar ,msgbufsym nil)
(defvar ,dbgsym nil)
(defvar ,codsyssym nil)
(defvar ,addrsym nil)
;; Define level set function
(defun ,(intern (concat prefix "--log-set-level")) (minlevel &optional maxlevel)
"Set range for doing logging.
MINLEVEL is symbol of lowest level for doing logging. its default is 'info.
MAXLEVEL is symbol of highest level for doing logging. its default is 'fatal."
(setq ,minlvlsym minlevel)
(setq ,maxlvlsym maxlevel))
;; Define logging toggle function
(defun ,(intern (concat prefix "--log-enable-logging")) ()
"Enable logging by logging functions."
(interactive)
(setq ,tglsym t))
(defun ,(intern (concat prefix "--log-disable-logging")) ()
"Disable logging by logging functions."
(interactive)
(setq ,tglsym nil))
;; Define messaging toggle function
(defun ,(intern (concat prefix "--log-enable-messaging")) (&optional buffer)
"Enable dump the log into other buffer by logging functions.
BUFFER is a buffer dumped log into. nil means *Messages* buffer."
(interactive)
(setq ,msgbufsym (or buffer t)))
(defun ,(intern (concat prefix "--log-disable-messaging")) ()
"Disable dump the log into other buffer by logging functions."
(interactive)
(setq ,msgbufsym nil))
;; Define debugging toggle function
(defun ,(intern (concat prefix "--log-enable-debugging")) ()
"Enable debugging and logging.
`PREFIX--log-debugging-p' will return t."
(interactive)
(setq ,tglsym t)
(setq ,dbgsym t))
(defun ,(intern (concat prefix "--log-disable-debugging")) ()
"Disable debugging.
`PREFIX--log-debugging-p' will return nil."
(interactive)
(setq ,dbgsym nil))
(defun ,(intern (concat prefix "--log-debugging-p")) ()
,dbgsym)
;; Define coding system set funtion
(defun ,(intern (concat prefix "--log-set-coding-system")) (coding-system)
"Set charset and linefeed of LOG-BUFFER.
CODING-SYSTEM is symbol for setting to `buffer-file-coding-system'.
LOG-BUFFER is a buffer which name is \" *log4e-PREFIX*\"."
(setq ,codsyssym coding-system))
;; ;; Define author mail set function
;; (defun ,(intern (concat prefix "--log-set-author-mail-address")) (before-atmark after-atmark)
;; "Set mail address of author for elisp that has PREFIX. This value is used SEND-REPORT.
;; BEFORE-ATMARK is string as part of mail address. If your address is \"hoge@example.co.jp\", it is \"hoge\".
;; AFTER-ATMARK is string as part of mail address. If your address is \"hoge@example.co.jp\", it is \"example.co.jp\".
;; SEND-REPORT is `PREFIX--log-send-report-if-not-debug'."
;; (setq ,addrsym (concat before-atmark "@" after-atmark)))
;; Define log buffer handle function
(defun ,(intern (concat prefix "--log-clear-log")) ()
"Clear buffer string of buffer which name is \" *log4e-PREFIX*\"."
(interactive)
(log4e--clear-log ,bufsym))
(defun ,(intern (concat prefix "--log-open-log")) ()
"Open buffer which name is \" *log4e-PREFIX*\"."
(interactive)
(log4e--open-log ,bufsym))
(defun ,(intern (concat prefix "--log-open-log-if-debug")) ()
"Open buffer which name is \" *log4e-PREFIX*\" if debugging is enabled."
(log4e--open-log-if-debug ,bufsym ,dbgsym))
;; ;; Define report send function
;; (defun ,(intern (concat prefix "--log-send-report-if-not-debug")) ()
;; "Send bug report to author if debugging is disabled.
;; The author mailaddress is set by `PREFIX--log-set-author-mail-address'.
;; About the way of sending bug report, see `reporter-submit-bug-report'."
;; (log4e--send-report-if-not-debug ,bufsym ,dbgsym ,addrsym ,prefix))
;; Define each level logging function
(log4e--def-level-logger ,prefix nil nil)
(log4e--def-level-logger ,prefix ,(assoc-default 'fatal funcnm-alist) 'fatal)
(log4e--def-level-logger ,prefix ,(assoc-default 'error funcnm-alist) 'error)
(log4e--def-level-logger ,prefix ,(assoc-default 'warn funcnm-alist) 'warn)
(log4e--def-level-logger ,prefix ,(assoc-default 'info funcnm-alist) 'info)
(log4e--def-level-logger ,prefix ,(assoc-default 'debug funcnm-alist) 'debug)
(log4e--def-level-logger ,prefix ,(assoc-default 'trace funcnm-alist) 'trace)
))))
;;;###autoload
(define-derived-mode log4e-mode view-mode "Log4E"
"Major mode for browsing a buffer made by log4e.
\\<log4e-mode-map>
\\{log4e-mode-map}"
(define-key log4e-mode-map (kbd "J") 'log4e:next-log)
(define-key log4e-mode-map (kbd "K") 'log4e:previous-log))
(defun log4e:next-log ()
"Move to start of next log on log4e-mode."
(interactive)
(let* ((level))
(while (and (not level)
(< (point) (point-max)))
(forward-line 1)
(setq level (log4e--get-current-log-line-level)))
level))
(defun log4e:previous-log ()
"Move to start of previous log on log4e-mode."
(interactive)
(let* ((level))
(while (and (not level)
(> (point) (point-min)))
(forward-line -1)
(setq level (log4e--get-current-log-line-level)))
level))
;;;###autoload
(defun log4e:insert-start-log-quickly ()
"Insert logging statment for trace level log at start of current function/macro."
(interactive)
(let* ((fstartpt (when (re-search-backward "(\\(?:defun\\|defmacro\\|defsubst\\)\\*? +\\([^ ]+\\) +(\\([^)]*\\))" nil t)
(point)))
(fncnm (when fstartpt (match-string-no-properties 1)))
(argtext (when fstartpt (match-string-no-properties 2)))
(prefix (save-excursion
(goto-char (point-min))
(loop while (re-search-forward "(log4e:deflogger[ \n]+\"\\([^\"]+\\)\"" nil t)
for prefix = (match-string-no-properties 1)
for currface = (get-text-property (match-beginning 0) 'face)
if (not (eq currface 'font-lock-comment-face))
return prefix))))
(when (and fstartpt prefix)
(let* ((fncnm (replace-regexp-in-string (concat "\\`" prefix "[^a-zA-Z0-9]+") "" fncnm))
(fncnm (replace-regexp-in-string "-" " " fncnm))
(argtext (replace-regexp-in-string "\n" " " argtext))
(argtext (replace-regexp-in-string "^ +" "" argtext))
(argtext (replace-regexp-in-string " +$" "" argtext))
(args (split-string argtext " +"))
(args (loop for arg in args
if (and (not (string= arg ""))
(not (string-match "\\`&" arg)))
collect arg))
(logtext (loop with ret = (format "start %s." fncnm)
for arg in args
do (setq ret (concat ret " " arg "[%s]"))
finally return ret))
(sexpformat (loop with ret = "(%s--log 'trace \"%s\""
for arg in args
do (setq ret (concat ret " %s"))
finally return (concat ret ")")))
(inserttext (apply 'format sexpformat prefix logtext args)))
(forward-char)
(forward-sexp 3)
(when (re-search-forward "\\=[ \n]+\"" nil t)
(forward-char -1)
(forward-sexp))
(newline-and-indent)
(insert inserttext)))))
(provide 'log4e)
;;; log4e.el ends here

Binary file not shown.

View file

@ -0,0 +1,43 @@
;;; org-pomodoro-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name
(or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "org-pomodoro" "org-pomodoro.el" (0 0 0 0))
;;; Generated autoloads from org-pomodoro.el
(autoload 'org-pomodoro "org-pomodoro" "\
Start a new pomodoro or stop the current one.
When no timer is running for `org-pomodoro` a new pomodoro is started and
the current task is clocked in. Otherwise EMACS will ask whether we´d like to
kill the current timer, this may be a break or a running pomodoro.
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-pomodoro" '("org-pomodoro-")))
;;;***
;;;### (autoloads nil "org-pomodoro-pidgin" "org-pomodoro-pidgin.el"
;;;;;; (0 0 0 0))
;;; Generated autoloads from org-pomodoro-pidgin.el
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-pomodoro-pidgin" '("org-pom")))
;;;***
;;;### (autoloads nil nil ("org-pomodoro-pkg.el") (0 0 0 0))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; coding: utf-8
;; End:
;;; org-pomodoro-autoloads.el ends here

View file

@ -0,0 +1,149 @@
;; -*- lexical-binding: t; -*-
;;; org-pomodoro-pidgin.el --- Integrate org-pomodoro and Pidgin
;;
;; Copyright (C) 2013 Damien Cassou
;;
;; Author: Damien Cassou <damien.cassou@gmail.com>
;; Created: 2013-07-11
;; Keywords: emacs package elisp pidgin pomodoro org-mode
;;
;; This file is NOT part of GNU Emacs.
;;
;; 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 2, 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 ; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;
;;; commentary:
;;
;; Update Pidgin status as the Pomodoro progresses.
;;
;; (require 'org-pomodoro-pidgin)
;;
;;; code:
;;
;; The following code uses the "org-pompid" prefix for all "private"
;; functions (and an addition dash "-") and the "org-pomodoro-pidgin"
;; prefix for all "public" functions.
(require 'org-pomodoro)
(defgroup org-pomodoro-pidgin nil
"Customization group for the Pidgin integration with
org-pomodoro."
:group 'org-pomodoro)
(defcustom org-pomodoro-pidgin-busy-status
"Pomodoro ends at %s"
"Status message when a pomodoro is in progress.
The string will be passed to `format' with the time when pomodoro
ends."
:group 'org-pomodoro-pidgin)
(defcustom org-pomodoro-pidgin-break-status
"Available"
"Status message when a pomodoro is in progress."
:group 'org-pomodoro-pidgin)
(defun org-pompid--status-type-to-id (type)
"Convert the symbol TYPE to the correspond int32.
https://developer.pidgin.im/wiki/DbusHowto#CallingPidginmethods."
(cl-case type
(offline 1)
(available 2)
(unavailable 3)
(invisible 4)
(away 5)
(mobile 7)
(tune 8)))
(defun org-pompid--call-method (method handler &rest args)
"Call METHOD with D-Bus and execute HANDLER upon answer.
ARGS lists additional parameters for METHOD."
(when
(member "im.pidgin.purple.PurpleService" (dbus-list-known-names :session))
(apply #'dbus-call-method-asynchronously
:session
"im.pidgin.purple.PurpleService"
"/im/pidgin/purple/PurpleObject"
"im.pidgin.purple.PurpleInterface"
method
handler
args)))
(defun org-pompid--set-status-message (status message)
"Update STATUS with the MESSAGE."
(org-pompid--call-method
"PurpleSavedstatusSetMessage"
nil
:int32 status
message))
(defun org-pompid--new-transient-status (type handler)
"Create a new status of TYPE and execute HANDLER when created."
(org-pompid--call-method
"PurpleSavedstatusNew"
handler
""
:int32 (org-pompid--status-type-to-id type)))
(defun org-pompid--activate (status)
"Make STATUS the current one in Piding."
(org-pompid--call-method
"PurpleSavedstatusActivate"
nil
:int32 status))
(defun org-pompid--change-status-message (type message)
"Create a new status of TYPE with MESSAGE.
TYPE must be valid for `org-pompid--status-type-to-id'."
(org-pompid--new-transient-status
type
(lambda (status)
(org-pompid--set-status-message status message)
(org-pompid--activate status))))
(defun org-pompid--format-message (message)
"Replace the %s in MESSAGE with the time when pomodoro ends."
(format
message
(format-time-string
"%H:%M"
(time-add (current-time) (seconds-to-time org-pomodoro-countdown)))))
(add-hook
'org-pomodoro-started-hook
(lambda ()
(org-pompid--change-status-message
'unavailable
(org-pompid--format-message org-pomodoro-pidgin-busy-status))))
(add-hook
'org-pomodoro-finished-hook
(lambda ()
(org-pompid--change-status-message
'available
org-pomodoro-pidgin-break-status)))
(add-hook
'org-pomodoro-killed-hook
(lambda ()
(org-pompid--change-status-message
'available
org-pomodoro-pidgin-break-status)))
(provide 'org-pomodoro-pidgin)
;;; org-pomodoro-pidgin.el ends here

View file

@ -0,0 +1,11 @@
(define-package "org-pomodoro" "20190530.1445" "Pomodoro implementation for org-mode."
'((alert "0.5.10")
(cl-lib "0.5"))
:authors
'(("Arthur Leonard Andersen" . "leoc.git@gmail.com"))
:maintainer
'("Arthur Leonard Andersen" . "leoc.git@gmail.com")
:url "https://github.com/lolownia/org-pomodoro")
;; Local Variables:
;; no-byte-compile: t
;; End:

View file

@ -0,0 +1,655 @@
;;; org-pomodoro.el --- Pomodoro implementation for org-mode.
;; Author: Arthur Leonard Andersen <leoc.git@gmail.com>, Marcin Koziej <marcin at lolownia dot org>
;; URL: https://github.com/lolownia/org-pomodoro
;; Created: May 10, 2013
;; Version: 2.1.0
;; Package-Requires: ((alert "0.5.10") (cl-lib "0.5"))
;; 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 file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; Org-pomodoro introduces an easy way to clock time in org-mode with
;; the pomodoro technique. You can clock into tasks with starting a
;; pomodoro time automatically. Each finished pomodoro is followed by
;; a break timer. If you completed 4 pomodoros in a row the break is
;; longer that the shorter break between each pomodoro.
;;
;; For a full explanation of the pomodoro technique, have a look at:
;; http://www.pomodorotechnique.com
;;; Code:
(eval-when-compile
(require 'cl-lib))
(require 'timer)
(require 'org)
(require 'org-agenda)
(require 'org-clock)
(require 'org-timer)
(require 'alert)
;;; Custom Variables
(defgroup org-pomodoro nil
"Org pomodoro customization"
:tag "Org Pomodoro"
:group 'org-progress)
(defcustom org-pomodoro-long-break-frequency 4
"The maximum number of pomodoros until a long break is started."
:group 'org-pomodoro
:type 'integer)
(defcustom org-pomodoro-ask-upon-killing t
"Determines whether to ask upon killing a pomodoro or not."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-play-sounds t
"Determines whether sounds are played or not."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-manual-break nil
"Whether the user needs to exit manually from a running pomodoro to enter a break.
If non-nil, after the time is up for a pomodoro, an \"overtime\"
state is entered until org-pomodoro is invoked, which then
finishes the pomodoro and enters the break period."
:group 'org-pomodoro
:type 'boolean)
;; Pomodoro Values
(defcustom org-pomodoro-length 25
"The length of a pomodoro in minutes."
:group 'org-pomodoro
:type 'integer)
(defcustom org-pomodoro-time-format "%.2m:%.2s"
"Defines the format of the time representation in the modeline."
:group 'org-pomodoro
:type 'string)
(defcustom org-pomodoro-format "Pomodoro~%s"
"The format of the mode line string during a pomodoro session."
:group 'org-pomodoro
:type 'string)
(defcustom org-pomodoro-audio-player (or (executable-find "aplay")
(executable-find "afplay"))
"Music player used to play sounds."
:group 'org-pomodoro
:type 'string)
;;; POMODORO START SOUND
(defcustom org-pomodoro-start-sound-p nil
"Determines whether to play a sound when a pomodoro started.
Use `org-pomodoro-start-sound' to determine what sound that should be."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-start-sound (when load-file-name
(concat (file-name-directory load-file-name)
"resources/bell.wav"))
"The path to a sound file that´s to be played when a pomodoro is started."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-start-sound-args nil
"Arguments used when playing the `org-pomodoro-start-sound'."
:group 'org-pomodoro
:type 'string)
;;; POMODORO FINISHED SOUND
(defcustom org-pomodoro-finished-sound-p t
"Determines whether to play a sound when a pomodoro finished.
Use `org-pomodoro-finished-sound' to determine what sound that should be."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-finished-sound (when load-file-name
(concat (file-name-directory load-file-name)
"resources/bell.wav"))
"The path to a sound file that´s to be played when a pomodoro was finished."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-finished-sound-args nil
"Arguments used when playing the `org-pomodoro-finished-sound'."
:group 'org-pomodoro
:type 'string)
;;; POMODORO OVERTIME SOUND
(defcustom org-pomodoro-overtime-sound-p t
"Determines whether to play a sound when a pomodoro starts to run overtime.
Use `org-pomodoro-overtime-sound' to determine what sound that should be."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-overtime-sound (when load-file-name
(concat (file-name-directory load-file-name)
"resources/bell.wav"))
"The path to a sound file that´s to be played when a pomodoro runs overtime."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-overtime-sound-args nil
"Arguments used when playing the `org-pomodoro-overtime-sound'."
:group 'org-pomodoro
:type 'string)
;;; POMODORO KILLED SOUND
(defcustom org-pomodoro-killed-sound-p nil
"Determines whether to play a sound when a pomodoro killed.
Use `org-pomodoro-killed-sound' to determine what sound that should be."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-killed-sound nil
"The path to a sound file, that´s to be played when a pomodoro is killed."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-killed-sound-args nil
"Arguments used when playing the `org-pomodoro-killed-sound'."
:group 'org-pomodoro
:type 'string)
;;; POMODORO SHORT-BREAK SOUND
(defcustom org-pomodoro-short-break-sound-p t
"Determines whether to play a sound when a short-break finished.
Use `org-pomodoro-short-break-sound' to determine what sound that should be."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-clock-break nil
"When t, also clocks time during breaks."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-short-break-sound (when load-file-name
(concat (file-name-directory load-file-name)
"resources/bell.wav"))
"The path to a sound file that´s to be played when a break was finished."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-short-break-sound-args nil
"Arguments used when playing the `org-pomodoro-short-break-sound'."
:group 'org-pomodoro
:type 'string)
;;; POMODORO LONG-BREAK SOUND
(defcustom org-pomodoro-long-break-sound-p t
"Determines whether to play a sound when a long-break finished.
Use `org-pomodoro-long-break-sound' to determine what sound that should be."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-long-break-sound (when load-file-name
(concat (file-name-directory load-file-name)
"resources/bell_multiple.wav"))
"The path to a sound file that´s to be played when a long break is finished."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-long-break-sound-args nil
"Arguments used when playing the `org-pomodoro-long-break-sound'."
:group 'org-pomodoro
:type 'string)
;;; POMODORO TICKING SOUND
(defcustom org-pomodoro-ticking-sound-p nil
"Determines whether ticking sounds are played or not."
:group 'org-pomodoro
:type 'boolean)
(defcustom org-pomodoro-ticking-sound (when load-file-name
(concat (file-name-directory load-file-name)
"resources/tick.wav"))
"The path to a sound file that´s to be played while a pomodoro is running."
:group 'org-pomodoro
:type 'file)
(defcustom org-pomodoro-ticking-sound-args nil
"Arguments used when playing the `org-pomodoro-ticking-sound'."
:group 'org-pomodoro
:type 'string)
(defcustom org-pomodoro-ticking-sound-states '(:pomodoro :short-break :long-break)
"The states in which to play ticking sounds."
:group 'org-pomodoro
:type 'list)
(defcustom org-pomodoro-ticking-frequency 1
"The frequency at which to playback the ticking sound."
:group 'org-pomodoro
:type 'list)
;;; OVERTIME VALUES
(defcustom org-pomodoro-overtime-format "+%s"
"The format of the mode line during a pomodoro running overtime."
:group 'org-pomodoro
:type 'string)
;;; BREAK VALUES
(defcustom org-pomodoro-short-break-length 5
"The length of a short break in minutes."
:group 'org-pomodoro
:type 'integer)
(defcustom org-pomodoro-short-break-format "Short Break~%s"
"The format of the mode line string during a short break."
:group 'org-pomodoro
:type 'string)
(defcustom org-pomodoro-long-break-length 20
"The length of a long break in minutes."
:group 'org-pomodoro
:type 'integer)
(defcustom org-pomodoro-long-break-format "Long Break~%s"
"The format of the mode line string during a long break."
:group 'org-pomodoro
:type 'string)
(defcustom org-pomodoro-expiry-time 120
"The time in minutes for which a pomodoro group is valid.
The size of a pomodoro group is defined by `org-pomodoro-long-break-frequency'.
If you do not clock in for this period of time you will be prompted
whether to reset the pomodoro count next time you call `org-pomodoro'."
:group 'org-pomodoro
:type 'integer)
(defcustom org-pomodoro-keep-killed-pomodoro-time nil
"Keeps the clocked time of killed pomodoros."
:group 'org-pomodoro
:type 'boolean)
;; Hooks
(defvar org-pomodoro-started-hook nil
"Hooks run when a pomodoro is started.")
(defvar org-pomodoro-finished-hook nil
"Hooks run when a pomodoro is finished.")
(defvar org-pomodoro-overtime-hook nil
"Hooks run when a pomodoro enters overtime.")
(defvar org-pomodoro-killed-hook nil
"Hooks run when a pomodoro is killed.")
(defvar org-pomodoro-break-finished-hook nil
"Hook run after any break has finished.
Run before a break's specific hook.")
(defvar org-pomodoro-long-break-finished-hook nil
"Hooks run when a long break is finished.")
(defvar org-pomodoro-short-break-finished-hook nil
"Hooks run when short break is finished.")
(defvar org-pomodoro-tick-hook nil
"Hooks run every second during a pomodoro.")
;; Faces
(defface org-pomodoro-mode-line
'((t (:foreground "tomato1")))
"Face of a pomodoro in the modeline."
:group 'faces)
(defface org-pomodoro-mode-line-overtime
'((t (:foreground "tomato3" :weight bold)))
"Face of a pomodoro running overtime in the modeline."
:group 'faces)
(defface org-pomodoro-mode-line-break
'((t (:foreground "#2aa198")))
"Face of a pomodoro break in the modeline ."
:group 'faces)
;; Temporary Variables
(defvar org-pomodoro-mode-line "")
(put 'org-pomodoro-mode-line 'risky-local-variable t)
(defvar org-pomodoro-timer nil
"The timer while a pomodoro or a break.")
(defvar org-pomodoro-end-time nil
"The end time of the current pomodoro phase.")
(defvar org-pomodoro-state :none
"The current state of `org-pomodoro`.
It changes to :pomodoro when starting a pomodoro and to :longbreak
or :break when starting a break.")
(defvar org-pomodoro-count 0
"The number of pomodoros since the last long break.")
(defvar org-pomodoro-last-clock-in nil
"The last time the pomodoro was set.")
;;; Internal
;; Helper Functions
(defun org-pomodoro-active-p ()
"Retrieve whether org-pomodoro is active or not."
(not (eq org-pomodoro-state :none)))
(defun org-pomodoro-expires-p ()
"Return true when the last clock-in was more than `org-pomodoro-expiry-time`."
(let ((delta-minutes (/ (float-time (time-subtract (current-time) org-pomodoro-last-clock-in)) 60)))
(> delta-minutes org-pomodoro-expiry-time)))
(defun org-pomodoro-sound-p (type)
"Return whether to play sound of given TYPE."
(cl-case type
(:start org-pomodoro-start-sound-p)
(:pomodoro org-pomodoro-finished-sound-p)
(:overtime org-pomodoro-overtime-sound-p)
(:killed org-pomodoro-killed-sound-p)
(:short-break org-pomodoro-short-break-sound-p)
(:long-break org-pomodoro-long-break-sound-p)
(:tick org-pomodoro-ticking-sound-p)
(t (error "Unknown org-pomodoro sound: %S" type))))
(defun org-pomodoro-sound (type)
"Return the sound file for given TYPE."
(cl-case type
(:start org-pomodoro-start-sound)
(:pomodoro org-pomodoro-finished-sound)
(:overtime org-pomodoro-overtime-sound)
(:killed org-pomodoro-killed-sound)
(:short-break org-pomodoro-short-break-sound)
(:long-break org-pomodoro-long-break-sound)
(:tick org-pomodoro-ticking-sound)
(t (error "Unknown org-pomodoro sound: %S" type))))
(defun org-pomodoro-sound-args (type)
"Return the playback arguments for given TYPE."
(cl-case type
(:start org-pomodoro-start-sound-args)
(:pomodoro org-pomodoro-finished-sound-args)
(:overtime org-pomodoro-overtime-sound-args)
(:killed org-pomodoro-killed-sound-args)
(:short-break org-pomodoro-short-break-sound-args)
(:long-break org-pomodoro-long-break-sound-args)
(:tick org-pomodoro-ticking-sound-args)
(t (error "Unknown org-pomodoro sound: %S" type))))
(defun org-pomodoro-play-sound (type)
"Play an audio file specified by TYPE (:pomodoro, :short-break, :long-break)."
(let ((sound (org-pomodoro-sound type))
(args (org-pomodoro-sound-args type)))
(cond ((and (fboundp 'sound-wav-play)
org-pomodoro-play-sounds
sound)
(sound-wav-play sound))
((and org-pomodoro-audio-player
org-pomodoro-play-sounds
sound)
(start-process-shell-command
"org-pomodoro-audio-player" nil
(mapconcat 'identity
`(,org-pomodoro-audio-player
,@(delq nil (list args (shell-quote-argument (expand-file-name sound)))))
" "))))))
(defun org-pomodoro-maybe-play-sound (type)
"Play an audio file specified by TYPE."
(when (org-pomodoro-sound-p type)
(org-pomodoro-play-sound type)))
(defun org-pomodoro-remaining-seconds ()
"Return the number of seconds remaining in the current phase as a float.
Negative if the current phase is over."
(float-time (time-subtract org-pomodoro-end-time (current-time))))
(defun org-pomodoro-format-seconds ()
"Format the time remaining in the current phase with the format specified in
org-pomodoro-time-format."
(format-seconds org-pomodoro-time-format
(if (eq org-pomodoro-state :overtime)
(- (org-pomodoro-remaining-seconds))
(org-pomodoro-remaining-seconds))))
(defun org-pomodoro-update-mode-line ()
"Set the modeline accordingly to the current state."
(let ((s (cl-case org-pomodoro-state
(:pomodoro
(propertize org-pomodoro-format 'face 'org-pomodoro-mode-line))
(:overtime
(propertize org-pomodoro-overtime-format
'face 'org-pomodoro-mode-line-overtime))
(:short-break
(propertize org-pomodoro-short-break-format
'face 'org-pomodoro-mode-line-break))
(:long-break
(propertize org-pomodoro-long-break-format
'face 'org-pomodoro-mode-line-break)))))
(setq org-pomodoro-mode-line
(when (and (org-pomodoro-active-p) (> (length s) 0))
(list "[" (format s (org-pomodoro-format-seconds)) "] "))))
(force-mode-line-update t))
(defun org-pomodoro-kill ()
"Kill the current timer, reset the phase and update the modeline."
(org-pomodoro-killed))
(defun org-pomodoro-tick ()
"A callback that is invoked by the running timer each second.
It checks whether we reached the duration of the current phase, when 't it
invokes the handlers for finishing."
(when (and (not (org-pomodoro-active-p)) org-pomodoro-timer)
(org-pomodoro-reset))
(when (org-pomodoro-active-p)
;; The first element of a time value is the high-order part of the seconds
;; value. This is less than 0 if org-pomodoro-end-time is in the past of
;; the current-time.
(when (< (org-pomodoro-remaining-seconds) 0)
(cl-case org-pomodoro-state
(:pomodoro (if org-pomodoro-manual-break
(org-pomodoro-overtime)
(org-pomodoro-finished)))
(:short-break (org-pomodoro-short-break-finished))
(:long-break (org-pomodoro-long-break-finished))))
(run-hooks 'org-pomodoro-tick-hook)
(org-pomodoro-update-mode-line)
(when (and (member org-pomodoro-state org-pomodoro-ticking-sound-states)
(equal (mod (truncate (org-pomodoro-remaining-seconds))
org-pomodoro-ticking-frequency)
0))
(org-pomodoro-maybe-play-sound :tick))))
(defun org-pomodoro-set (state)
"Set the org-pomodoro STATE."
(setq org-pomodoro-state state
org-pomodoro-end-time
(cl-case state
(:pomodoro (time-add (current-time) (* 60 org-pomodoro-length)))
(:overtime (current-time))
(:short-break (time-add (current-time) (* 60 org-pomodoro-short-break-length)))
(:long-break (time-add (current-time) (* 60 org-pomodoro-long-break-length))))
org-pomodoro-timer (run-with-timer t 1 'org-pomodoro-tick)))
(defun org-pomodoro-start (&optional state)
"Start the `org-pomodoro` timer.
The argument STATE is optional. The default state is `:pomodoro`."
(when org-pomodoro-timer (cancel-timer org-pomodoro-timer))
;; add the org-pomodoro-mode-line to the global-mode-string
(unless global-mode-string (setq global-mode-string '("")))
(unless (memq 'org-pomodoro-mode-line global-mode-string)
(setq global-mode-string (append global-mode-string
'(org-pomodoro-mode-line))))
(org-pomodoro-set (or state :pomodoro))
(when (eq org-pomodoro-state :pomodoro)
(org-pomodoro-maybe-play-sound :start)
(run-hooks 'org-pomodoro-started-hook))
(org-pomodoro-update-mode-line)
(org-agenda-maybe-redo))
(defun org-pomodoro-reset ()
"Reset the org-pomodoro state."
(when org-pomodoro-timer
(cancel-timer org-pomodoro-timer))
(setq org-pomodoro-state :none
org-pomodoro-end-time nil)
(org-pomodoro-update-mode-line)
(org-agenda-maybe-redo))
(defun org-pomodoro-notify (title message)
"Send a notification with TITLE and MESSAGE using `alert'."
(alert message :title title :category 'org-pomodoro))
;; Handlers for pomodoro events.
(defun org-pomodoro-overtime ()
"Is invoked when the time for a pomodoro runs out.
Notify the user that the pomodoro should be finished by calling org-pomodoro"
(org-pomodoro-maybe-play-sound :overtime)
(org-pomodoro-notify "Pomodoro completed. Now on overtime!" "Start break by calling org-pomodoro")
(org-pomodoro-start :overtime)
(org-pomodoro-update-mode-line)
(run-hooks 'org-pomodoro-overtime-hook))
(defun org-pomodoro-finished ()
"Is invoked when a pomodoro was finished successfully.
This may send a notification, play a sound and start a pomodoro break."
(unless org-pomodoro-clock-break
(org-clock-out nil t))
(org-pomodoro-maybe-play-sound :pomodoro)
(setq org-pomodoro-count (+ org-pomodoro-count 1))
(if (zerop (mod org-pomodoro-count org-pomodoro-long-break-frequency))
(org-pomodoro-start :long-break)
(org-pomodoro-start :short-break))
(org-pomodoro-notify "Pomodoro completed!" "Time for a break.")
(org-pomodoro-update-mode-line)
(org-agenda-maybe-redo)
(run-hooks 'org-pomodoro-finished-hook))
(defun org-pomodoro-killed ()
"Is invoked when a pomodoro was killed.
This may send a notification, play a sound and adds log."
(org-pomodoro-reset)
(org-pomodoro-notify "Pomodoro killed." "One does not simply kill a pomodoro!")
(when (org-clocking-p)
(if org-pomodoro-keep-killed-pomodoro-time
(org-clock-out nil t)
(org-clock-cancel)))
(run-hooks 'org-pomodoro-killed-hook))
(defun org-pomodoro-short-break-finished ()
"Is invoked when a short break is finished.
This may send a notification and play a sound."
(when org-pomodoro-clock-break
(org-clock-out nil t))
(org-pomodoro-reset)
(org-pomodoro-notify "Short break finished." "Ready for another pomodoro?")
(org-pomodoro-maybe-play-sound :short-break)
(run-hooks 'org-pomodoro-break-finished-hook 'org-pomodoro-short-break-finished-hook))
(defun org-pomodoro-long-break-finished ()
"Is invoked when a long break is finished.
This may send a notification and play a sound."
(when org-pomodoro-clock-break
(org-clock-out nil t))
(org-pomodoro-reset)
(org-pomodoro-notify "Long break finished." "Ready for another pomodoro?")
(org-pomodoro-maybe-play-sound :long-break)
(run-hooks 'org-pomodoro-break-finished-hook 'org-pomodoro-long-break-finished-hook))
(defun org-pomodoro-extend-last-clock ()
"Extends last clock to `current-time'."
(interactive)
(save-window-excursion
(org-clock-goto)
(when (re-search-forward ":LOGBOOK:" (save-excursion (outline-next-heading)) t)
(org-flag-drawer nil))
(let ((last-clock (car org-clock-history)))
(switch-to-buffer (marker-buffer last-clock))
(goto-char last-clock)
(let ((item-end (save-excursion (org-end-of-subtree t))))
(when (re-search-forward "CLOCK: \\(\\[.*?\\]\\)" item-end t)
(kill-line)
(org-clock-clock-out
(cons (copy-marker (match-end 1) t)
(org-time-string-to-time (match-string 1)))))))))
;;;###autoload
(defun org-pomodoro (&optional arg)
"Start a new pomodoro or stop the current one.
When no timer is running for `org-pomodoro` a new pomodoro is started and
the current task is clocked in. Otherwise EMACS will ask whether we´d like to
kill the current timer, this may be a break or a running pomodoro."
(interactive "P")
(when (and org-pomodoro-last-clock-in
org-pomodoro-expiry-time
(org-pomodoro-expires-p)
(y-or-n-p "Reset pomodoro count? "))
(setq org-pomodoro-count 0))
(setq org-pomodoro-last-clock-in (current-time))
(cond
;; possibly break from overtime
((and (org-pomodoro-active-p) (eq org-pomodoro-state :overtime))
(org-pomodoro-finished))
;; Maybe kill running pomodoro
((org-pomodoro-active-p)
(if (or (not org-pomodoro-ask-upon-killing)
(y-or-n-p "There is already a running timer. Would you like to stop it? "))
(org-pomodoro-kill)
(message "Alright, keep up the good work!")))
;; or start and clock in pomodoro
(t
(cond
((equal arg '(4))
(let ((current-prefix-arg '(4)))
(call-interactively 'org-clock-in)))
((equal arg '(16))
(call-interactively 'org-clock-in-last))
((memq major-mode (list 'org-mode 'org-journal-mode))
(call-interactively 'org-clock-in))
((eq major-mode 'org-agenda-mode)
(org-with-point-at (org-get-at-bol 'org-hd-marker)
(call-interactively 'org-clock-in)))
(t (let ((current-prefix-arg '(4)))
(call-interactively 'org-clock-in))))
(org-pomodoro-start :pomodoro))))
(provide 'org-pomodoro)
;;; org-pomodoro.el ends here

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more