org-mode 利用appt.el和BurntToast在Windows10+上弹出agenda通知提醒

参考来源:

https://florianwinkelbauer.com/posts/2020-05-02-org-notifications/

操作流程:

安装BurntToast

考虑到国内网络环境推荐使用加速方式

Install-Module -Proxy "http://127.0.0.1:7890" -Name BurntToast
Set-ExecutionPolicy -ExecutionPolicy Unrestricted

emacs的配置

  (require 'appt)
  (setq appt-message-warning-time '0)
  (appt-activate t)
  (defun fw/org-agenda-to-appt ()
    "Rebuild all appt reminders using org."
    (interactive)
    (setq appt-time-msg-list nil)
    (org-agenda-to-appt))
  (fw/org-agenda-to-appt)
  (add-hook 'org-agenda-finalize-hook 'fw/org-agenda-to-appt)
  (defun fw/appt-disp-windows (min-to-app new-time msg)
    "A custom `appt-disp-window-function' which uses the PowerShell module 'BurntToast'"
    (shell-command (concat "PowerShell -Command New-BurntToastNotification -AppLogo " (concat my-org-dir1  "/emacs.png") " -Text '" msg "'")))
  (setq appt-display-format 'window)
  (setq appt-disp-window-function (function fw/appt-disp-windows))
  (setq appt-delete-window-function (lambda nil))

每次打开org-agenda时都会自动更新今日的提醒。

效果

Snipaste_2023-01-03_22-41-17

缺点

在同一时刻有多个TODO时只有一个会弹出提醒。

但是考虑到我们并不在Windows的通知中心进行操作,只是把通知中心当成一个提醒我们检查Emacs和Org-Agenda的工具,这个缺点似乎也变得无关紧要了。

5 个赞

可以试用一下 notify-py 也不错

1 个赞

目前尝试了改用Windows-Toasts来替代powershell,记录如下:

  1. ~/.emacs.d/中新建notify.py,内容如下:
import sys,os
from urllib.parse import unquote
from windows_toasts import Toast, WindowsToaster, ToastDisplayImage
toaster = WindowsToaster('Emacs Agenda')
newToast = Toast()
newToast.text_fields = [unquote(sys.argv[1])]
newToast.AddImage(ToastDisplayImage.fromPath(unquote(sys.argv[2])+"/org/phone/emacs.png"))
toaster.show_toast(newToast)
  1. 将先前的fw/appt-disp-windows改为
(defun fw/appt-disp-windows (min-to-app new-time msg)
    "A custom `appt-disp-window-function' which uses the PowerShell module 'BurntToast'"
    (shell-command (concat "python -X utf8 "(file-truename user-emacs-directory) "notify.py " (url-encode-url msg )" " (url-encode-url (file-truename user-emacs-directory))))
    )

经测试有效。使用python库的好处在于规避powershell的安装、策略设置过程,可以利用国内的pip镜像库,方便下载。

(参考 Windows 中,emacs 的 shell-command 传递参数,作为 python 的 argv[1] 编码问题 - #7,来自 blove

使用内建函数的新版

使用内建函数,减少外部依赖。

(defun fw/appt-disp-windows (min-to-app new-time msg)
  (let ((id (w32-notification-notify
             :level "info"
             :title msg
             :body "⚠️有新提醒,请查看Emacs!⚠️")))
    (run-at-time 1 nil #'w32-notification-close id)))
1 个赞

可以直接使用 org-notify,这样 macos 和 linux 也不需要专门配置,在 windows 也是调用 w32-notification-notify 实现的

(defun ringawho/appt-org-notify (min-to-app current-time appt-msg)
    "Appt notify (use org-notify)."
    (or (listp min-to-app)
        (setq min-to-app (list min-to-app)
              appt-msg (list appt-msg)))
    (dotimes (i (length min-to-app))
      (org-notify (format "[%s min]: %s"
                          (nth i min-to-app)
                          (nth i appt-msg))
                  org-clock-sound)))
1 个赞

org-show-notification函数硬编码了title,不过我根据它修改了一下自定义提醒函数。

(defun fw/appt-disp (min-to-app new-time msg)
  (cond ((fboundp 'w32-notification-notify)
         (let ((id (w32-notification-notify
                    :level "info"
                    :title msg
                    :body "⚠️有新提醒,请查看Emacs!⚠️")))
           (run-at-time 1 nil #'w32-notification-close id)))
        ((fboundp 'ns-do-applescript)
         (ns-do-applescript
          (format "display notification \"⚠️有新提醒,请查看Emacs!⚠️\" with title \"%s\""
                  (replace-regexp-in-string "\"" "#" msg))))
        ))
1 个赞