Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate org-gcal to aio #160

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
285d1b3
WIP: migrate org-gcal to aio
telotortium Jul 15, 2022
d94c6fb
Add aio-iter2 as a submodule
telotortium Jul 15, 2022
82c4be7
Port whole file to aio-iter2
telotortium Jul 15, 2022
73760e9
WIP Fix a few things in org-gcal
telotortium Jul 15, 2022
16925c9
Enable aio-cancel to cancel HTTP requests
telotortium Jul 15, 2022
c140604
Fix after rebase
telotortium Jul 15, 2022
ffaa420
Change aio-iter2 to use my upstream repo
telotortium Jul 15, 2022
5b8ed59
Vendor aio-iter2.el
telotortium Jul 15, 2022
2c7206f
WIP add tests for aio
telotortium Jul 15, 2022
4a22852
Remove autoloads from aio-iter2-defun functions
telotortium Jul 15, 2022
35b5d92
Port tests to aio
telotortium Jul 15, 2022
8055c6f
WIP testing #179
telotortium Jul 15, 2022
8f49b36
Bump version to 0.5.0
telotortium Nov 19, 2022
a03ca56
Make Commentary of org-gcal.el just point to README.org
telotortium Jul 15, 2022
63d27d9
Make into multi-file package
telotortium Jul 15, 2022
e806b82
Add Package-Requires to org-generic-id
telotortium Jul 15, 2022
a2a59ec
WIP fix compile errors
telotortium Jul 15, 2022
9f67a08
WIP fix compile
telotortium Jul 15, 2022
1b0702d
WIP fix compile
telotortium Jul 15, 2022
9d49437
Make any prompts for user input fail during tests
telotortium Jul 15, 2022
0eb976d
Enable autoload for async functions
telotortium Jul 15, 2022
85e9e3b
org-gcal--aio-request-catch-error
telotortium Jul 15, 2022
656379f
Use org-gcal--aio-request-catch-error everywhere
telotortium Jul 15, 2022
e70dd9e
Simplify org-gcal-fetch-buffer-aio
telotortium Jul 15, 2022
3b70d9f
Update docs
telotortium Jul 15, 2022
5c7004a
Enhance test logic
telotortium Jul 15, 2022
8e60ec9
Allow overriding URL for Calendar API
telotortium Jul 15, 2022
92071d4
Add elnode as dependency
telotortium Jul 15, 2022
37253b0
WIP iterating closer to the finish line
telotortium Jul 15, 2022
ca22da3
Test helper to print each test name before running
telotortium Jul 15, 2022
f4067fa
WIP: trying to debug why org-gcal-sync-aio only scans one buffer
telotortium Jul 15, 2022
1732064
Add checkdoc test
telotortium Jul 15, 2022
1ad427d
WIP fix tests
telotortium Jul 15, 2022
c2502b7
WIP fix checkdoc errors
telotortium Jul 15, 2022
6052f8a
WIP fix more checkdoc failures
telotortium Jul 28, 2022
4db070d
fix: correctly log events whose titles contain backslash
telotortium Aug 23, 2022
17ed712
WIP catch errors
telotortium Sep 11, 2022
0863204
Use org-combine-change-calls when modifying org buffer
telotortium Apr 26, 2024
9e3a25a
Use deferred:wait-idle to improve responsiveness
telotortium Apr 26, 2024
e8df2f6
Remove useless trailing stuff at end of file
telotortium Apr 26, 2024
82547a4
Add debug message on sync-lock and sync-unlock
telotortium Apr 26, 2024
3e68cde
WIP
telotortium Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 50 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
THIS_MAKEFILE_DIR = $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
EMACS ?= emacs
SRC=org-gcal.el org-generic-id.el oauth2-auto.el
SRC=org-gcal.el org-generic-id.el aio-iter2.el oauth2-auto.el
TEST=test/org-gcal-test.el test/org-generic-id-test.el
TEST_DEPS=test/org-gcal-test.el
TEST_HELPER=test/test-helper.el
TEST_PATTERN ?= '.*'
BUILD_LOG = build.log
CASK ?= cask
PKG_DIR := $(shell $(CASK) package-directory)
ELCFILES = $(SRC:.el=.elc)
.DEFAULT_GOAL := all

.PHONY: all clean load-path compile test elpa update-oauth2-auto
.PHONY: all clean load-path compile test test-checkdoc test-ert elpa \
update-aio-iter2 update-oauth2-auto

all: compile test

Expand All @@ -24,9 +28,50 @@ compile: $(SRC) elpa
$(CASK) build 2>&1 | tee $(BUILD_LOG); \
! ( grep -E -e ':(Warning|Error):' $(BUILD_LOG) )

test: $(SRC) $(TEST) elpa
$(CASK) exec ert-runner -L $(THIS_MAKEFILE_DIR) \
$(foreach test,$(TEST),$(addprefix $(THIS_MAKEFILE_DIR)/,$(test)))
test: test-checkdoc test-unit

test-checkdoc: $(SRC) elpa compile
FILES="$(SRC)" $(CASK) eval '\
(let* ((files (split-string (getenv "FILES") " "))) \
(dolist (file files) \
(let ((pkg (intern-soft (file-name-base file)))) \
(require pkg) \
(checkdoc-file file))) \
(when (get-buffer "*Warnings*") \
(kill-emacs 1)))'
# (get-buffer "*Warnings") checks if any warnings were generated.


test-unit: $(SRC) $(TEST) $(TEST_DEPS) $(TEST_HELPER) elpa
# Collect output for running all tests at once. Use </dev/null to
# ensure any input from user fails.
test_pattern () { \
set -x; \
$(CASK) exec ert-runner --debug \
-l $(addprefix $(THIS_MAKEFILE_DIR)/,$(TEST_HELPER)) \
-L $(THIS_MAKEFILE_DIR) \
-p "$$1" \
$(foreach test,$(TEST),$(addprefix $(THIS_MAKEFILE_DIR)/,$(test))) \
</dev/null; \
rv=$$?; set +x; return $$rv; \
}; \
output=$$(test_pattern $(TEST_PATTERN) 2>&1); \
ran_test=$$(echo "$$output" | grep -E '^Ran [0-9]+ test'); \
if [ -z "$$ran_test" ]; then printf "Running tests failed. Output: %%s" "$$output"; exit 1; fi; \
failed_tests=$$(echo "$$output" | awk '/^[0-9]+ unexpected results:$$/ { print_test = 1 } /^ *FAILED */ { if (!print_test) { next; } sub("^ *FAILED *", ""); print; }'); \
if [ -z "$$failed_tests" ]; then exit 0; fi; \
echo "*** Failed tests - now rerunning individually:" $$failed_tests; echo; \
rv=0; \
final_failed_tests=""; \
for test in $$failed_tests; do if ! test_pattern "$$test"; then final_failed_tests="$$final_failed_tests $$test"; rv=$$?; fi; done; \
if [ -z "$$final_failed_tests" -a $$rv -eq 0 ]; then echo "*** Final success"; exit 0; fi; \
echo "*** Final failed tests:" $$final_failed_tests; \
exit $$rv

# Vendor aio-iter2 from my fork until aio-iter2 is added to MELPA.
update-aio-iter2:
curl -o aio-iter2.el \
https://raw.githubusercontent.com/telotortium/emacs-aio-iter2/master/aio-iter2.el

# Vendor oauth2-auto from my fork until oauth2-auto is added to MELPA.
update-oauth2-auto:
Expand Down
106 changes: 106 additions & 0 deletions aio-iter2.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
;;; aio-iter2.el --- Reimplement aio using iter2 -*- lexical-binding: t; -*-

;; This is free and unencumbered software released into the public domain.

;; Author: Robert Irelan <rirelan@gmail.com>, Christopher Wellons <wellons@nullprogram.com>
;; URL: https://github.com/telotortium/emacs-aio-iter2.el
;; Version: 1.0
;;
;; Keep in sync with org-gcal-pkg.el.
;; Package-Requires: ((emacs "26.1") (aio "1.0") (iter2 "1.0"))

;;; Commentary:

;; `aio-iter2` provides new versions of the `aio-lambda`, `aio-defun`, and `aio-with-async`
;; macros that are defined using `iter2-lambda` instead of `iter-lambda`, in order to
;; obtain the benefits of `iter2-lambda` in `aio`-using code.

;;; Code:

(require 'cl-lib)
(require 'font-lock)
(require 'generator)
(require 'iter2)
(require 'aio)
(require 'rx)

(defmacro aio-iter2-lambda (arglist &rest body)
"Like `lambda', but define an async function.

ARGLIST and BODY are as in ‘lambda’. The body of this function may use
`aio-await' to wait on promises. When an async function is called, it
immediately returns a promise that will resolve to the function's return value,
or any uncaught error signal.

Replacement of `aio-lambda` that uses `iter2-lambda` instead
of `iter-lambda`."
(declare (indent defun)
(doc-string 3)
(debug (&define lambda-list lambda-doc
[&optional ("interactive" interactive)]
&rest sexp)))
(let ((args (make-symbol "args"))
(promise (make-symbol "promise"))
(split-body (macroexp-parse-body body)))
`(lambda (&rest ,args)
,@(car split-body)
(let* ((,promise (aio-promise))
(iter (apply (iter2-lambda ,arglist
(aio-with-promise ,promise
,@(cdr split-body)))
,args)))
(prog1 ,promise
(aio--step iter ,promise nil))))))

(defmacro aio-iter2-defun (name arglist &rest body)
"Like `aio-iter2-lambda' but gives the function a name like `defun'.
NAME, ARGLIST, and BODY are as in ‘defun’."
(declare (indent defun)
(doc-string 3)
(debug (&define name lambda-list &rest sexp)))
`(progn
(defalias ',name (aio-iter2-lambda ,arglist ,@body))
(function-put ',name 'aio-defun-p t)
;; Evaluates to the name of the function, like ‘defun’.
',name))

(defmacro aio-iter2-with-async (&rest body)
"Evaluate BODY asynchronously as if it was inside `aio-iter2-lambda'.

Since BODY is evalued inside an asynchronous lambda, `aio-await'
is available here. This macro evaluates to a promise for BODY's
eventual result.

Beware: Dynamic bindings that are lexically outside
‘aio-iter2-with-async’ blocks have no effect. For example,

(defvar dynamic-var nil)
(defun my-func ()
(let ((dynamic-var 123))
(aio-iter2-with-async dynamic-var)))
(let ((dynamic-var 456))
(aio-wait-for (my-func)))
⇒ 456

Other global state such as the current buffer behaves likewise."
(declare (indent 0)
(debug (&rest sexp)))
`(let ((promise (funcall (aio-iter2-lambda ()
(aio-await (aio-sleep 0))
,@body))))
(prog1 promise
;; The is the main feature: Force the final result to be
;; realized so that errors are reported.
(aio-listen promise #'funcall))))

;; `emacs-lisp-mode' font lock

(font-lock-add-keywords
'emacs-lisp-mode
`((,(rx "(aio-iter2-defun" (+ blank)
(group (+ (or (syntax word) (syntax symbol)))))
1 'font-lock-function-name-face)))

(provide 'aio-iter2)

;;; aio-iter2.el ends here
3 changes: 2 additions & 1 deletion org-gcal-pkg.el
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
;; Keep in sync with Package-Requires lines in the package files.
(define-package "org-gcal" "0.4.2"
(define-package "org-gcal" "0.5.0"
"Org sync with Google Calendar"
'((aio "1.0")
(alert "1.2")
(elnode "20190702.1509")
(emacs "26.1")
(iter2 "1.0")
(org "9.3")
(persist "0.4")
(request "20190901")
Expand Down
Loading
Loading