update eaf package
This commit is contained in:
80
README.md
80
README.md
@@ -1,39 +1,44 @@
|
||||
|
||||
# Table of Contents
|
||||
|
||||
1. [Requirements](#org5ff850e)
|
||||
2. [Installation](#org0e5b75a)
|
||||
3. [Key bindings and functions](#org9907e5a)
|
||||
4. [Packages](#orgccb3d6a)
|
||||
5. [Information](#orgdd0b988)
|
||||
6. [Errors](#org2fbb7be)
|
||||
1. [failed execution of bibtex2html](#orgd3ccf34)
|
||||
1. [Requirements](#orgf4fd69f)
|
||||
2. [Installation](#orgeb12447)
|
||||
3. [Key bindings and functions](#orgb4f8fdc)
|
||||
4. [Packages](#orga8c6216)
|
||||
5. [Information](#orgaf15aed)
|
||||
6. [Errors](#org7c7dda9)
|
||||
1. [failed execution of bibtex2html](#org79a8e5c)
|
||||
|
||||
This is an ongoing evolution of Emacs configuration files, inspired by
|
||||
a bunch of online resources.
|
||||
|
||||
|
||||
<a id="org5ff850e"></a>
|
||||
<a id="orgf4fd69f"></a>
|
||||
|
||||
# Requirements
|
||||
|
||||
- external packages
|
||||
- aspell/hunspell (flyspell-buffer)
|
||||
- biber (for org-mode latex-mode)
|
||||
- bibtex2html (for org-mode)
|
||||
- ledger (for ledger-mode)
|
||||
- languagetool (for langtool)
|
||||
- python-pylint (for python-mode)
|
||||
- for EAF emacs-application-framework
|
||||
yay -S python-pyqt5 python-pyqt5-sip python-pyqtwebengine python-qrcode python-feedparser python-dbus python-pyinotify python-markdown nodejs aria2 libreoffice python-pymupdf python-grip filebrowser-bin
|
||||
- copy/merge the texmf directory into your home directory
|
||||
- copy all files of this directory into your ~/.config/emacs directory
|
||||
- for Emacs version < 27 create symbolic link to the init file
|
||||
- `ln -s ~/.config/emacs/init ~/.emacs` (or `~/.emacs.el`,
|
||||
`~/.emacs.d/init.el`)
|
||||
external packages:
|
||||
|
||||
# flyspell-buffer
|
||||
yay -S aspell hunspell
|
||||
# org-mode latex-mode
|
||||
yay -S biber bibtex2html
|
||||
# ledger-mode
|
||||
yay -S ledger
|
||||
# langtool
|
||||
yay -S languagetool
|
||||
# python-mode
|
||||
yay -S python-pylint
|
||||
# emacs-application-famework EAF
|
||||
yay -S --needed git nodejs aria2 libreoffice wmctrl xdotool jre-openjdk \
|
||||
python-pyqt5 python-pyqt5-sip python-pyqtwebengine python-qrcode \
|
||||
python-feedparser python-dbus python-pyinotify python-markdown \
|
||||
python-grip filebrowser-bin python-epc
|
||||
|
||||
Optional package for EAF see in Installation.
|
||||
|
||||
|
||||
<a id="org0e5b75a"></a>
|
||||
<a id="orgeb12447"></a>
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -41,8 +46,27 @@ Install into `~/.config/emacs` (must be empty)
|
||||
|
||||
git clone http://gogs.weseng.de/daniel/emacs.git ~/.config/emacs
|
||||
|
||||
or copy all files of this directory into your ~/.config/emacs directory
|
||||
|
||||
<a id="org9907e5a"></a>
|
||||
- for Emacs version < 27 create symbolic link to the init file
|
||||
- `ln -s ~/.config/emacs/init ~/.emacs` (or `~/.emacs.el`,
|
||||
`~/.emacs.d/init.el`)
|
||||
|
||||
copy/merge the texmf directory into your home directory
|
||||
|
||||
optional for EAF
|
||||
|
||||
yay --editmenu -S mupdf python-pymupdf
|
||||
|
||||
edit `PGKBUILD` file for `python-pymupdf` to:
|
||||
|
||||
prepare() {
|
||||
cd "${_name}-${pkgver}"
|
||||
patch --forward --strip=1 --input="${HOME}/.config/emacs/scripts/fix-pymupdf-library-linking-for-arcolinux.patch"
|
||||
}
|
||||
|
||||
|
||||
<a id="orgb4f8fdc"></a>
|
||||
|
||||
# Key bindings and functions
|
||||
|
||||
@@ -321,7 +345,7 @@ Install into `~/.config/emacs` (must be empty)
|
||||
</table>
|
||||
|
||||
|
||||
<a id="orgccb3d6a"></a>
|
||||
<a id="orga8c6216"></a>
|
||||
|
||||
# Packages
|
||||
|
||||
@@ -330,7 +354,7 @@ Install into `~/.config/emacs` (must be empty)
|
||||
colors with the color they represent as background.
|
||||
|
||||
|
||||
<a id="orgdd0b988"></a>
|
||||
<a id="orgaf15aed"></a>
|
||||
|
||||
# Information
|
||||
|
||||
@@ -340,12 +364,12 @@ but interlocks to prevent the simultaneous editing of the same
|
||||
file. See [Interlocking](https://www.emacswiki.org/info-ref?find=Interlocking) in the [EmacsManual](https://www.emacswiki.org/emacs/EmacsManual) for details.
|
||||
|
||||
|
||||
<a id="org2fbb7be"></a>
|
||||
<a id="org7c7dda9"></a>
|
||||
|
||||
# Errors
|
||||
|
||||
|
||||
<a id="orgd3ccf34"></a>
|
||||
<a id="org79a8e5c"></a>
|
||||
|
||||
## failed execution of bibtex2html
|
||||
|
||||
|
||||
57
README.org
57
README.org
@@ -4,27 +4,54 @@ This is an ongoing evolution of Emacs configuration files, inspired by
|
||||
a bunch of online resources.
|
||||
|
||||
* Requirements
|
||||
- external packages
|
||||
- aspell/hunspell (flyspell-buffer)
|
||||
- biber (for org-mode latex-mode)
|
||||
- bibtex2html (for org-mode)
|
||||
- ledger (for ledger-mode)
|
||||
- languagetool (for langtool)
|
||||
- python-pylint (for python-mode)
|
||||
- for EAF emacs-application-framework
|
||||
yay -S python-pyqt5 python-pyqt5-sip python-pyqtwebengine python-qrcode python-feedparser python-dbus python-pyinotify python-markdown nodejs aria2 libreoffice python-pymupdf python-grip filebrowser-bin
|
||||
- copy/merge the texmf directory into your home directory
|
||||
- copy all files of this directory into your ~/.config/emacs directory
|
||||
- for Emacs version < 27 create symbolic link to the init file
|
||||
- =ln -s ~/.config/emacs/init ~/.emacs= (or =~/.emacs.el=,
|
||||
=~/.emacs.d/init.el=)
|
||||
external packages:
|
||||
#+begin_src shell
|
||||
# flyspell-buffer
|
||||
yay -S aspell hunspell
|
||||
# org-mode latex-mode
|
||||
yay -S biber bibtex2html
|
||||
# ledger-mode
|
||||
yay -S ledger
|
||||
# langtool
|
||||
yay -S languagetool
|
||||
# python-mode
|
||||
yay -S python-pylint
|
||||
# emacs-application-famework EAF
|
||||
yay -S --needed git nodejs aria2 libreoffice wmctrl xdotool jre-openjdk \
|
||||
python-pyqt5 python-pyqt5-sip python-pyqtwebengine python-qrcode \
|
||||
python-feedparser python-dbus python-pyinotify python-markdown \
|
||||
python-grip filebrowser-bin python-epc
|
||||
#+end_src
|
||||
Optional package for EAF see in Installation.
|
||||
|
||||
* Installation
|
||||
Install into =~/.config/emacs= (must be empty)
|
||||
#+begin_src sh
|
||||
git clone http://gogs.weseng.de/daniel/emacs.git ~/.config/emacs
|
||||
git clone http://gogs.weseng.de/daniel/emacs.git ~/.config/emacs
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
|
||||
or copy all files of this directory into your ~/.config/emacs directory
|
||||
- for Emacs version < 27 create symbolic link to the init file
|
||||
- =ln -s ~/.config/emacs/init ~/.emacs= (or =~/.emacs.el=,
|
||||
=~/.emacs.d/init.el=)
|
||||
|
||||
copy/merge the texmf directory into your home directory
|
||||
|
||||
optional for EAF
|
||||
#+begin_src shell
|
||||
yay --editmenu -S mupdf python-pymupdf
|
||||
#+end_src
|
||||
|
||||
edit =PGKBUILD= file for =python-pymupdf= to:
|
||||
#+begin_example
|
||||
prepare() {
|
||||
cd "${_name}-${pkgver}"
|
||||
patch --forward --strip=1 --input="${HOME}/.config/emacs/scripts/fix-pymupdf-library-linking-for-arcolinux.patch"
|
||||
}
|
||||
#+end_example
|
||||
|
||||
* Key bindings and functions
|
||||
#+caption: General
|
||||
| M-> | end-of-buffer | |
|
||||
|
||||
503
lisp/concurrent.el
Normal file
503
lisp/concurrent.el
Normal file
@@ -0,0 +1,503 @@
|
||||
;;; concurrent.el --- Concurrent utility functions for emacs lisp -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2010-2016 SAKURAI Masashi
|
||||
|
||||
;; Author: SAKURAI Masashi <m.sakurai at kiwanami.net>
|
||||
;; Version: 0.5.0
|
||||
;; Package-Version: 20161229.330
|
||||
;; Package-Commit: 2239671d94b38d92e9b28d4e12fd79814cfb9c16
|
||||
;; Keywords: deferred, async, concurrent
|
||||
;; Package-Requires: ((emacs "24.3") (deferred "0.5.0"))
|
||||
;; URL: https://github.com/kiwanami/emacs-deferred/blob/master/README-concurrent.markdown
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; 'concurrent.el' is a higher level library for concurrent tasks
|
||||
;; based on 'deferred.el'. This library has following features:
|
||||
;;
|
||||
;; - Generator
|
||||
;; - Green thread
|
||||
;; - Semaphore
|
||||
;; - Dataflow
|
||||
;; - Signal/Channel
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
(require 'deferred)
|
||||
|
||||
(defvar cc:version nil "version number")
|
||||
(setq cc:version "0.3")
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
|
||||
(defmacro cc:aif (test-form then-form &rest else-forms)
|
||||
(declare (debug (form form &rest form)))
|
||||
`(let ((it ,test-form))
|
||||
(if it ,then-form ,@else-forms)))
|
||||
(put 'cc:aif 'lisp-indent-function 2)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Generator
|
||||
|
||||
(defun cc:generator-replace-yield (tree)
|
||||
"[internal] Replace `yield' symbols to calling a function in TREE."
|
||||
(let (ret)
|
||||
(cl-loop for i in tree
|
||||
do (cond
|
||||
((eq i 'yield)
|
||||
(push 'funcall ret)
|
||||
(push i ret))
|
||||
((listp i)
|
||||
(push (cc:generator-replace-yield i) ret))
|
||||
(t
|
||||
(push i ret))))
|
||||
(nreverse ret)))
|
||||
|
||||
(defun cc:generator-line (chain line)
|
||||
"[internal] Return a macro expansion to execute the sexp LINE
|
||||
asynchronously."
|
||||
(cond
|
||||
;; function object
|
||||
((functionp line)
|
||||
`(setq ,chain (deferred:nextc ,chain ,line)))
|
||||
;; while loop form
|
||||
((eq 'while (car line))
|
||||
(let ((condition (cadr line))
|
||||
(body (cddr line)))
|
||||
`(setq ,chain
|
||||
(deferred:nextc ,chain
|
||||
(deferred:lambda (x)
|
||||
(if ,condition
|
||||
(deferred:nextc
|
||||
(progn
|
||||
,@(cc:generator-replace-yield body)) self)))))))
|
||||
;; statement
|
||||
(t
|
||||
`(setq ,chain
|
||||
(deferred:nextc ,chain
|
||||
(deferred:lambda (x) ,(cc:generator-replace-yield line)))))))
|
||||
|
||||
(defmacro cc:generator (callback &rest body)
|
||||
"Create a generator object. If BODY has `yield' symbols, it
|
||||
means calling callback function CALLBACK."
|
||||
(let ((chain (cl-gensym))
|
||||
(cc (cl-gensym))
|
||||
(waiter (cl-gensym)))
|
||||
`(let* (,chain
|
||||
(,cc ,callback)
|
||||
(,waiter (deferred:new))
|
||||
(yield (lambda (x) (funcall ,cc x) ,waiter)))
|
||||
(setq ,chain ,waiter)
|
||||
,@(cl-loop for i in body
|
||||
collect
|
||||
(cc:generator-line chain i))
|
||||
(lambda () (deferred:callback ,waiter)))))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Thread
|
||||
|
||||
(defun cc:thread-line (wait-time chain line)
|
||||
"[internal] Return a macro expansion to execute the sexp LINE asynchronously.
|
||||
WAIT-TIME is an interval time between tasks.
|
||||
CHAIN is the previous deferred task."
|
||||
(cond
|
||||
;; function object
|
||||
((functionp line)
|
||||
`(setq ,chain (deferred:nextc ,chain ,line)))
|
||||
;; while loop form
|
||||
((eq 'while (car line))
|
||||
(let ((condition (cadr line))
|
||||
(body (cddr line))
|
||||
(retsym (cl-gensym)))
|
||||
`(setq ,chain
|
||||
(deferred:nextc ,chain
|
||||
(deferred:lambda (x)
|
||||
(if ,condition
|
||||
(deferred:nextc
|
||||
(let ((,retsym (progn ,@body)))
|
||||
(if (deferred-p ,retsym) ,retsym
|
||||
(deferred:wait ,wait-time)))
|
||||
self)))))))
|
||||
;; statement
|
||||
(t
|
||||
`(setq ,chain
|
||||
(deferred:nextc ,chain
|
||||
(lambda (x) ,line))))))
|
||||
|
||||
(defmacro cc:thread (wait-time-msec &rest body)
|
||||
"Return a thread object."
|
||||
(let ((chain (cl-gensym))
|
||||
(dstart (cl-gensym)))
|
||||
`(let* (,chain
|
||||
(,dstart (deferred:new)))
|
||||
(setq ,chain ,dstart)
|
||||
,@(cl-loop for i in body
|
||||
collect
|
||||
(cc:thread-line wait-time-msec chain i))
|
||||
(deferred:callback ,dstart))))
|
||||
(put 'cc:thread 'lisp-indent-function 1)
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Semaphore
|
||||
|
||||
(cl-defstruct cc:semaphore max-permits permits waiting-deferreds)
|
||||
|
||||
(defun cc:semaphore-create(permits-num)
|
||||
"Return a semaphore object with PERMITS-NUM permissions."
|
||||
(make-cc:semaphore :max-permits permits-num :permits permits-num))
|
||||
|
||||
(defun cc:semaphore-acquire(semaphore)
|
||||
"Acquire an execution permission and return deferred object to chain.
|
||||
If this semaphore object has permissions, the subsequent deferred
|
||||
task is executed immediately. If this semaphore object has no
|
||||
permissions, the subsequent deferred task is blocked. After the
|
||||
permission is returned, the task is executed."
|
||||
(cond
|
||||
((< 0 (cc:semaphore-permits semaphore))
|
||||
(cl-decf (cc:semaphore-permits semaphore))
|
||||
(deferred:succeed))
|
||||
(t
|
||||
(let ((d (deferred:new)))
|
||||
(push d (cc:semaphore-waiting-deferreds semaphore))
|
||||
d))))
|
||||
|
||||
(defun cc:semaphore-release(semaphore)
|
||||
"Release an execution permission. The programmer is responsible to return the permissions."
|
||||
(when (<= (cc:semaphore-max-permits semaphore)
|
||||
(cc:semaphore-permits semaphore))
|
||||
(error "Too many calling semaphore-release. [max:%s <= permits:%s]"
|
||||
(cc:semaphore-max-permits semaphore)
|
||||
(cc:semaphore-permits semaphore)))
|
||||
(let ((waiting-deferreds
|
||||
(cc:semaphore-waiting-deferreds semaphore)))
|
||||
(cond
|
||||
(waiting-deferreds
|
||||
(let* ((d (car (last waiting-deferreds))))
|
||||
(setf (cc:semaphore-waiting-deferreds semaphore)
|
||||
(nbutlast waiting-deferreds))
|
||||
(deferred:callback-post d)))
|
||||
(t
|
||||
(cl-incf (cc:semaphore-permits semaphore)))))
|
||||
semaphore)
|
||||
|
||||
(defun cc:semaphore-with (semaphore body-func &optional error-func)
|
||||
"Execute the task BODY-FUNC asynchronously with the semaphore block."
|
||||
(deferred:try
|
||||
(deferred:nextc (cc:semaphore-acquire semaphore) body-func)
|
||||
:catch
|
||||
error-func
|
||||
:finally
|
||||
(lambda (_x) (cc:semaphore-release semaphore))))
|
||||
(put 'cc:semaphore-with 'lisp-indent-function 1)
|
||||
|
||||
(defun cc:semaphore-release-all (semaphore)
|
||||
"Release all permissions for resetting the semaphore object.
|
||||
If the semaphore object has some blocked tasks, this function
|
||||
return a list of the tasks and clear the list of the blocked
|
||||
tasks in the semaphore object."
|
||||
(setf (cc:semaphore-permits semaphore)
|
||||
(cc:semaphore-max-permits semaphore))
|
||||
(let ((ds (cc:semaphore-waiting-deferreds semaphore)))
|
||||
(when ds
|
||||
(setf (cc:semaphore-waiting-deferreds semaphore) nil))
|
||||
ds))
|
||||
|
||||
(defun cc:semaphore-interrupt-all (semaphore)
|
||||
"Clear the list of the blocked tasks in the semaphore and return a deferred object to chain.
|
||||
This function is used for the interruption cases."
|
||||
(when (cc:semaphore-waiting-deferreds semaphore)
|
||||
(setf (cc:semaphore-waiting-deferreds semaphore) nil)
|
||||
(setf (cc:semaphore-permits semaphore) 0))
|
||||
(cc:semaphore-acquire semaphore))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Signal / Channel
|
||||
|
||||
(defun cc:signal-channel (&optional name parent-channel)
|
||||
"Create a channel.
|
||||
NAME is a channel name for debug.
|
||||
PARENT-CHANNEL is an upstream channel. The observers of this channel can receive the upstream signals.
|
||||
In the case of using the function `cc:signal-send', the observers of the upstream channel can not receive the signals of this channel. The function `cc:signal-send-global' can send a signal to the upstream channels from the downstream channels."
|
||||
(let ((ch (cons
|
||||
(or name (format "signal%s" (deferred:uid))) ; name for debug
|
||||
(cons
|
||||
parent-channel ; parent-channel
|
||||
nil)))) ; observers
|
||||
(when parent-channel
|
||||
(cc:signal-connect
|
||||
parent-channel
|
||||
t (lambda (event)
|
||||
(cl-destructuring-bind
|
||||
(event-name event-args) event
|
||||
(apply 'cc:signal-send
|
||||
ch event-name event-args)))))
|
||||
ch))
|
||||
|
||||
(defmacro cc:signal-name (ch)
|
||||
"[internal] Return signal name."
|
||||
`(car ,ch))
|
||||
|
||||
(defmacro cc:signal-parent-channel (ch)
|
||||
"[internal] Return parent channel object."
|
||||
`(cadr ,ch))
|
||||
|
||||
(defmacro cc:signal-observers (ch)
|
||||
"[internal] Return observers."
|
||||
`(cddr ,ch))
|
||||
|
||||
(defun cc:signal-connect (channel event-sym &optional callback)
|
||||
"Append an observer for EVENT-SYM of CHANNEL and return a deferred object.
|
||||
If EVENT-SYM is `t', the observer receives all signals of the channel.
|
||||
If CALLBACK function is given, the deferred object executes the
|
||||
CALLBACK function asynchronously. One can connect subsequent
|
||||
tasks to the returned deferred object."
|
||||
(let ((d (if callback
|
||||
(deferred:new callback)
|
||||
(deferred:new))))
|
||||
(push (cons event-sym d)
|
||||
(cc:signal-observers channel))
|
||||
d))
|
||||
|
||||
(defun cc:signal-send (channel event-sym &rest args)
|
||||
"Send a signal to CHANNEL. If ARGS values are given, observers can get the values by following code: (lambda (event) (destructuring-bind (event-sym (args)) event ... )). "
|
||||
(let ((observers (cc:signal-observers channel))
|
||||
(event (list event-sym args)))
|
||||
(cl-loop for i in observers
|
||||
for name = (car i)
|
||||
for d = (cdr i)
|
||||
if (or (eq event-sym name) (eq t name))
|
||||
do (deferred:callback-post d event))))
|
||||
|
||||
(defun cc:signal-send-global (channel event-sym &rest args)
|
||||
"Send a signal to the most upstream channel. "
|
||||
(cc:aif (cc:signal-parent-channel channel)
|
||||
(apply 'cc:signal-send-global it event-sym args)
|
||||
(apply 'cc:signal-send channel event-sym args)))
|
||||
|
||||
|
||||
(defun cc:signal-disconnect (channel deferred)
|
||||
"Remove the observer object DEFERRED from CHANNEL and return
|
||||
the removed deferred object. "
|
||||
(let ((observers (cc:signal-observers channel)) deleted)
|
||||
(setf
|
||||
(cc:signal-observers channel) ; place
|
||||
(cl-loop for i in observers
|
||||
for d = (cdr i)
|
||||
unless (eq d deferred)
|
||||
collect i
|
||||
else
|
||||
do (push i deleted)))
|
||||
deleted))
|
||||
|
||||
(defun cc:signal-disconnect-all (channel)
|
||||
"Remove all observers."
|
||||
(setf
|
||||
(cc:signal-observers channel) ; place
|
||||
nil))
|
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Dataflow
|
||||
|
||||
;; Dataflow variable entry
|
||||
(cl-defstruct cc:dataflow key (value 'cc:dataflow-undefine) deferred-list)
|
||||
|
||||
(defun cc:dataflow-undefine-p (obj)
|
||||
"[internal] If the variable entry is not bound, return `t'."
|
||||
(eq 'cc:dataflow-undefine (cc:dataflow-value obj)))
|
||||
|
||||
(defmacro cc:dataflow-parent-environment (df)
|
||||
"[internal] Return the parent environment."
|
||||
`(car ,df))
|
||||
|
||||
(defmacro cc:dataflow-test (df)
|
||||
"[internal] Return the test function."
|
||||
`(cadr ,df))
|
||||
|
||||
(defmacro cc:dataflow-channel (df)
|
||||
"[internal] Return the channel object."
|
||||
`(cl-caddr ,df))
|
||||
|
||||
(defmacro cc:dataflow-list (df)
|
||||
"[internal] Return the list of deferred object which are waiting for value binding."
|
||||
`(cl-cdddr ,df))
|
||||
|
||||
(defun cc:dataflow-environment (&optional parent-env test-func channel)
|
||||
"Create a dataflow environment.
|
||||
PARENT-ENV is the default environment. If this environment doesn't have the entry A and the parent one has the entry A, this environment can return the entry A. One can override the entry, setting another entry A to this environment.
|
||||
TEST-FUNC is a test function that compares the entry keys. The default function is `equal'.
|
||||
CHANNEL is a channel object that sends signals of variable events. Observers can receive following signals:
|
||||
-get-first : the fist referrer is waiting for binding,
|
||||
-get-waiting : another referrer is waiting for binding,
|
||||
-set : a value is bound,
|
||||
-get : returned a bound value,
|
||||
-clear : cleared one entry,
|
||||
-clear-all : cleared all entries.
|
||||
"
|
||||
(let ((this (list parent-env
|
||||
(or test-func 'equal)
|
||||
(or channel
|
||||
(cc:signal-channel
|
||||
'dataflow
|
||||
(and parent-env
|
||||
(cc:dataflow-channel parent-env)))))))
|
||||
(cc:dataflow-init-connect this)
|
||||
this))
|
||||
|
||||
(defun cc:dataflow-init-connect (df)
|
||||
"[internal] Initialize the channel object."
|
||||
(cc:dataflow-connect
|
||||
df 'set
|
||||
(lambda (args)
|
||||
(cl-destructuring-bind (_event (key)) args
|
||||
(let* ((obj (cc:dataflow-get-object-for-value df key))
|
||||
(value (and obj (cc:dataflow-value obj))))
|
||||
(when obj
|
||||
(cl-loop for i in (cc:aif (cc:dataflow-get-object-for-deferreds df key)
|
||||
(cc:dataflow-deferred-list it) nil)
|
||||
do (deferred:callback-post i value))
|
||||
(setf (cc:dataflow-deferred-list obj) nil)))))))
|
||||
|
||||
(defun cc:dataflow-get-object-for-value (df key)
|
||||
"[internal] Return an entry object that is indicated by KEY.
|
||||
If the environment DF doesn't have the entry and the parent one has the entry, this function returns the entry of the parent environment. This function doesn't affect the waiting list."
|
||||
(or
|
||||
(cl-loop for i in (cc:dataflow-list df)
|
||||
with test = (cc:dataflow-test df)
|
||||
if (and (funcall test key (cc:dataflow-key i))
|
||||
(not (cc:dataflow-undefine-p i)))
|
||||
return i)
|
||||
(deferred:aand
|
||||
(cc:dataflow-parent-environment df)
|
||||
(cc:dataflow-get-object-for-value it key))))
|
||||
|
||||
(defun cc:dataflow-get-object-for-deferreds (df key)
|
||||
"[internal] Return a list of the deferred objects those are waiting for value binding.
|
||||
This function doesn't affect the waiting list and doesn't refer the parent environment."
|
||||
(cl-loop for i in (cc:dataflow-list df)
|
||||
with test = (cc:dataflow-test df)
|
||||
if (funcall test key (cc:dataflow-key i))
|
||||
return i))
|
||||
|
||||
(defun cc:dataflow-connect (df event-sym &optional callback)
|
||||
"Append an observer for EVENT-SYM of the channel of DF and return a deferred object.
|
||||
See the docstring of `cc:dataflow-environment' for details."
|
||||
(cc:signal-connect (cc:dataflow-channel df) event-sym callback))
|
||||
|
||||
(defun cc:dataflow-signal (df event &optional arg)
|
||||
"[internal] Send a signal to the channel of DF."
|
||||
(cc:signal-send (cc:dataflow-channel df) event arg))
|
||||
|
||||
(defun cc:dataflow-get (df key)
|
||||
"Return a deferred object that can refer the value which is indicated by KEY.
|
||||
If DF has the entry that bound value, the subsequent deferred task is executed immediately.
|
||||
If not, the task is deferred till a value is bound."
|
||||
(let ((obj (cc:dataflow-get-object-for-value df key)))
|
||||
(cond
|
||||
((and obj (cc:dataflow-value obj))
|
||||
(cc:dataflow-signal df 'get key)
|
||||
(deferred:succeed (cc:dataflow-value obj)))
|
||||
(t
|
||||
(setq obj (cc:dataflow-get-object-for-deferreds df key))
|
||||
(unless obj
|
||||
(setq obj (make-cc:dataflow :key key))
|
||||
(push obj (cc:dataflow-list df))
|
||||
(cc:dataflow-signal df 'get-first key))
|
||||
(let ((d (deferred:new)))
|
||||
(push d (cc:dataflow-deferred-list obj))
|
||||
(cc:dataflow-signal df 'get-waiting key)
|
||||
d)))))
|
||||
|
||||
(defun cc:dataflow-get-sync (df key)
|
||||
"Return the value which is indicated by KEY synchronously.
|
||||
If the environment DF doesn't have an entry of KEY, this function returns nil."
|
||||
(let ((obj (cc:dataflow-get-object-for-value df key)))
|
||||
(and obj (cc:dataflow-value obj))))
|
||||
|
||||
(defun cc:dataflow-set (df key value)
|
||||
"Bind the VALUE to KEY in the environment DF.
|
||||
If DF already has the bound entry of KEY, this function throws an error signal.
|
||||
VALUE can be nil as a value."
|
||||
(let ((obj (cc:dataflow-get-object-for-deferreds df key)))
|
||||
(cond
|
||||
((and obj (not (cc:dataflow-undefine-p obj)))
|
||||
;; overwrite!
|
||||
(error "Can not set a dataflow value. The key [%s] has already had a value. NEW:[%s] OLD:[%s]" key value (cc:dataflow-value obj)))
|
||||
(obj
|
||||
(setf (cc:dataflow-value obj) value))
|
||||
(t
|
||||
;; just value arrived
|
||||
(push (make-cc:dataflow :key key :value value)
|
||||
(cc:dataflow-list df))))
|
||||
;; value arrived and start deferred objects
|
||||
(cc:dataflow-signal df 'set key)
|
||||
value))
|
||||
|
||||
(defun cc:dataflow-clear (df key)
|
||||
"Clear the entry which is indicated by KEY.
|
||||
This function does nothing for the waiting deferred objects."
|
||||
(cc:dataflow-signal df 'clear key)
|
||||
(setf (cc:dataflow-list df)
|
||||
(cl-loop for i in (cc:dataflow-list df)
|
||||
with test = (cc:dataflow-test df)
|
||||
unless (funcall test key (cc:dataflow-key i))
|
||||
collect i)))
|
||||
|
||||
(defun cc:dataflow-get-avalable-pairs (df)
|
||||
"Return an available key-value alist in the environment DF and the parent ones."
|
||||
(append
|
||||
(cl-loop for i in (cc:dataflow-list df)
|
||||
for key = (cc:dataflow-key i)
|
||||
for val = (cc:dataflow-value i)
|
||||
unless (cc:dataflow-undefine-p i) collect (cons key val))
|
||||
(deferred:aand
|
||||
(cc:dataflow-parent-environment df)
|
||||
(cc:dataflow-get-avalable-pairs it))))
|
||||
|
||||
(defun cc:dataflow-get-waiting-keys (df)
|
||||
"Return a list of keys which have waiting deferred objects in the environment DF and the parent ones."
|
||||
(append
|
||||
(cl-loop for i in (cc:dataflow-list df)
|
||||
for key = (cc:dataflow-key i)
|
||||
if (cc:dataflow-undefine-p i) collect key)
|
||||
(deferred:aand
|
||||
(cc:dataflow-parent-environment df)
|
||||
(cc:dataflow-get-waiting-keys it))))
|
||||
|
||||
(defun cc:dataflow-clear-all (df)
|
||||
"Clear all entries in the environment DF.
|
||||
This function does nothing for the waiting deferred objects."
|
||||
(cc:dataflow-signal df 'clear-all)
|
||||
(setf (cc:dataflow-list df) nil))
|
||||
|
||||
|
||||
(provide 'concurrent)
|
||||
|
||||
;; Local Variables:
|
||||
;; byte-compile-warnings: (not cl-functions)
|
||||
;; End:
|
||||
|
||||
;;; concurrent.el ends here
|
||||
973
lisp/deferred.el
Normal file
973
lisp/deferred.el
Normal file
@@ -0,0 +1,973 @@
|
||||
;;; deferred.el --- Simple asynchronous functions for emacs lisp -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2010-2016 SAKURAI Masashi
|
||||
|
||||
;; Author: SAKURAI Masashi <m.sakurai at kiwanami.net>
|
||||
;; Version: 0.5.1
|
||||
;; Package-Version: 20170901.1330
|
||||
;; Package-Commit: 2239671d94b38d92e9b28d4e12fd79814cfb9c16
|
||||
;; Keywords: deferred, async
|
||||
;; Package-Requires: ((emacs "24.4"))
|
||||
;; URL: https://github.com/kiwanami/emacs-deferred
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; 'deferred.el' is a simple library for asynchronous tasks.
|
||||
;; [https://github.com/kiwanami/emacs-deferred]
|
||||
|
||||
;; The API is almost the same as JSDeferred written by cho45. See the
|
||||
;; JSDeferred and Mochikit.Async web sites for further documentations.
|
||||
;; [https://github.com/cho45/jsdeferred]
|
||||
;; [http://mochikit.com/doc/html/MochiKit/Async.html]
|
||||
|
||||
;; A good introduction document (JavaScript)
|
||||
;; [http://cho45.stfuawsc.com/jsdeferred/doc/intro.en.html]
|
||||
|
||||
;;; Samples:
|
||||
|
||||
;; ** HTTP Access
|
||||
|
||||
;; (require 'url)
|
||||
;; (deferred:$
|
||||
;; (deferred:url-retrieve "http://www.gnu.org")
|
||||
;; (deferred:nextc it
|
||||
;; (lambda (buf)
|
||||
;; (insert (with-current-buffer buf (buffer-string)))
|
||||
;; (kill-buffer buf))))
|
||||
|
||||
;; ** Invoking command tasks
|
||||
|
||||
;; (deferred:$
|
||||
;; (deferred:process "wget" "-O" "a.jpg" "http://www.gnu.org/software/emacs/tour/images/splash.png")
|
||||
;; (deferred:nextc it
|
||||
;; (lambda (x) (deferred:process "convert" "a.jpg" "-resize" "100x100" "jpg:b.jpg")))
|
||||
;; (deferred:nextc it
|
||||
;; (lambda (x)
|
||||
;; (insert-image (create-image (expand-file-name "b.jpg") 'jpeg nil)))))
|
||||
|
||||
;; See the readme for further API documentation.
|
||||
|
||||
;; ** Applications
|
||||
|
||||
;; *Inertial scrolling for Emacs
|
||||
;; [https://github.com/kiwanami/emacs-inertial-scroll]
|
||||
|
||||
;; This program makes simple multi-thread function, using
|
||||
;; deferred.el.
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'subr-x)
|
||||
|
||||
(declare-function pp-display-expression 'pp)
|
||||
|
||||
(defvar deferred:version nil "deferred.el version")
|
||||
(setq deferred:version "0.5.0")
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defmacro deferred:aand (test &rest rest)
|
||||
"[internal] Anaphoric AND."
|
||||
(declare (debug ("test" form &rest form)))
|
||||
`(let ((it ,test))
|
||||
(if it ,(if rest `(deferred:aand ,@rest) 'it))))
|
||||
|
||||
(defmacro deferred:$ (&rest elements)
|
||||
"Anaphoric function chain macro for deferred chains."
|
||||
(declare (debug (&rest form)))
|
||||
`(let (it)
|
||||
,@(cl-loop for i in elements
|
||||
collect
|
||||
`(setq it ,i))
|
||||
it))
|
||||
|
||||
(defmacro deferred:lambda (args &rest body)
|
||||
"Anaphoric lambda macro for self recursion."
|
||||
(declare (debug ("args" form &rest form)))
|
||||
(let ((argsyms (cl-loop repeat (length args) collect (cl-gensym))))
|
||||
`(lambda (,@argsyms)
|
||||
(let (self)
|
||||
(setq self (lambda( ,@args ) ,@body))
|
||||
(funcall self ,@argsyms)))))
|
||||
|
||||
(cl-defmacro deferred:try (d &key catch finally)
|
||||
"Try-catch-finally macro. This macro simulates the
|
||||
try-catch-finally block asynchronously. CATCH and FINALLY can be
|
||||
nil. Because of asynchrony, this macro does not ensure that the
|
||||
task FINALLY should be called."
|
||||
(let ((chain
|
||||
(if catch `((deferred:error it ,catch)))))
|
||||
(when finally
|
||||
(setq chain (append chain `((deferred:watch it ,finally)))))
|
||||
`(deferred:$ ,d ,@chain)))
|
||||
|
||||
(defun deferred:setTimeout (f msec)
|
||||
"[internal] Timer function that emulates the `setTimeout' function in JS."
|
||||
(run-at-time (/ msec 1000.0) nil f))
|
||||
|
||||
(defun deferred:cancelTimeout (id)
|
||||
"[internal] Timer cancellation function that emulates the `cancelTimeout' function in JS."
|
||||
(cancel-timer id))
|
||||
|
||||
(defun deferred:run-with-idle-timer (sec f)
|
||||
"[internal] Wrapper function for run-with-idle-timer."
|
||||
(run-with-idle-timer sec nil f))
|
||||
|
||||
(defun deferred:call-lambda (f &optional arg)
|
||||
"[internal] Call a function with one or zero argument safely.
|
||||
The lambda function can define with zero and one argument."
|
||||
(condition-case err
|
||||
(funcall f arg)
|
||||
('wrong-number-of-arguments
|
||||
(display-warning 'deferred "\
|
||||
Callback that takes no argument may be specified.
|
||||
Passing callback with no argument is deprecated.
|
||||
Callback must take one argument.
|
||||
Or, this error is coming from somewhere inside of the callback: %S" err)
|
||||
(condition-case nil
|
||||
(funcall f)
|
||||
('wrong-number-of-arguments
|
||||
(signal 'wrong-number-of-arguments (cdr err))))))) ; return the first error
|
||||
|
||||
;; debug
|
||||
|
||||
(eval-and-compile
|
||||
(defvar deferred:debug nil "Debug output switch."))
|
||||
(defvar deferred:debug-count 0 "[internal] Debug output counter.")
|
||||
|
||||
(defmacro deferred:message (&rest args)
|
||||
"[internal] Debug log function."
|
||||
(when deferred:debug
|
||||
`(progn
|
||||
(with-current-buffer (get-buffer-create "*deferred:debug*")
|
||||
(save-excursion
|
||||
(goto-char (point-max))
|
||||
(insert (format "%5i %s\n" deferred:debug-count (format ,@args)))))
|
||||
(cl-incf deferred:debug-count))))
|
||||
|
||||
(defun deferred:message-mark ()
|
||||
"[internal] Debug log function."
|
||||
(interactive)
|
||||
(deferred:message "==================== mark ==== %s"
|
||||
(format-time-string "%H:%M:%S" (current-time))))
|
||||
|
||||
(defun deferred:pp (d)
|
||||
(require 'pp)
|
||||
(deferred:$
|
||||
(deferred:nextc d
|
||||
(lambda (x)
|
||||
(pp-display-expression x "*deferred:pp*")))
|
||||
(deferred:error it
|
||||
(lambda (e)
|
||||
(pp-display-expression e "*deferred:pp*")))
|
||||
(deferred:nextc it
|
||||
(lambda (_x) (pop-to-buffer "*deferred:pp*")))))
|
||||
|
||||
(defvar deferred:debug-on-signal nil
|
||||
"If non nil, the value `debug-on-signal' is substituted this
|
||||
value in the `condition-case' form in deferred
|
||||
implementations. Then, Emacs debugger can catch an error occurred
|
||||
in the asynchronous tasks.")
|
||||
|
||||
(defmacro deferred:condition-case (var protected-form &rest handlers)
|
||||
"[internal] Custom condition-case. See the comment for
|
||||
`deferred:debug-on-signal'."
|
||||
(declare (debug condition-case)
|
||||
(indent 2))
|
||||
`(let ((debug-on-signal
|
||||
(or debug-on-signal deferred:debug-on-signal)))
|
||||
(condition-case ,var
|
||||
,protected-form
|
||||
,@handlers)))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Back end functions of deferred tasks
|
||||
|
||||
(defvar deferred:tick-time 0.001
|
||||
"Waiting time between asynchronous tasks (second).
|
||||
The shorter waiting time increases the load of Emacs. The end
|
||||
user can tune this parameter. However, applications should not
|
||||
modify it because the applications run on various environments.")
|
||||
|
||||
(defvar deferred:queue nil
|
||||
"[internal] The execution queue of deferred objects.
|
||||
See the functions `deferred:post-task' and `deferred:worker'.")
|
||||
|
||||
(defmacro deferred:pack (a b c)
|
||||
`(cons ,a (cons ,b ,c)))
|
||||
|
||||
(defun deferred:schedule-worker ()
|
||||
"[internal] Schedule consuming a deferred task in the execution queue."
|
||||
(run-at-time deferred:tick-time nil 'deferred:worker))
|
||||
|
||||
(defun deferred:post-task (d which &optional arg)
|
||||
"[internal] Add a deferred object to the execution queue
|
||||
`deferred:queue' and schedule to execute.
|
||||
D is a deferred object. WHICH is a symbol, `ok' or `ng'. ARG is
|
||||
an argument value for execution of the deferred task."
|
||||
(push (deferred:pack d which arg) deferred:queue)
|
||||
(deferred:message "QUEUE-POST [%s]: %s"
|
||||
(length deferred:queue) (deferred:pack d which arg))
|
||||
(deferred:schedule-worker)
|
||||
d)
|
||||
|
||||
(defun deferred:clear-queue ()
|
||||
"Clear the execution queue. For test and debugging."
|
||||
(interactive)
|
||||
(deferred:message "QUEUE-CLEAR [%s -> 0]" (length deferred:queue))
|
||||
(setq deferred:queue nil))
|
||||
|
||||
(defun deferred:worker ()
|
||||
"[internal] Consume a deferred task.
|
||||
Mainly this function is called by timer asynchronously."
|
||||
(when deferred:queue
|
||||
(let* ((pack (car (last deferred:queue)))
|
||||
(d (car pack))
|
||||
(which (cadr pack))
|
||||
(arg (cddr pack)) value)
|
||||
(setq deferred:queue (nbutlast deferred:queue))
|
||||
(condition-case err
|
||||
(setq value (deferred:exec-task d which arg))
|
||||
(error
|
||||
(deferred:message "ERROR : %s" err)
|
||||
(message "deferred error : %s" err)))
|
||||
value)))
|
||||
|
||||
(defun deferred:flush-queue! ()
|
||||
"Call all deferred tasks synchronously. For test and debugging."
|
||||
(let (value)
|
||||
(while deferred:queue
|
||||
(setq value (deferred:worker)))
|
||||
value))
|
||||
|
||||
(defun deferred:sync! (d)
|
||||
"Wait for the given deferred task. For test and debugging.
|
||||
Error is raised if it is not processed within deferred chain D."
|
||||
(progn
|
||||
(let ((last-value 'deferred:undefined*)
|
||||
uncaught-error)
|
||||
(deferred:try
|
||||
(deferred:nextc d
|
||||
(lambda (x) (setq last-value x)))
|
||||
:catch
|
||||
(lambda (err) (setq uncaught-error err)))
|
||||
(while (and (eq 'deferred:undefined* last-value)
|
||||
(not uncaught-error))
|
||||
(sit-for 0.05)
|
||||
(sleep-for 0.05))
|
||||
(when uncaught-error
|
||||
(deferred:resignal uncaught-error))
|
||||
last-value)))
|
||||
|
||||
|
||||
|
||||
;; Struct: deferred
|
||||
;;
|
||||
;; callback : a callback function (default `deferred:default-callback')
|
||||
;; errorback : an errorback function (default `deferred:default-errorback')
|
||||
;; cancel : a canceling function (default `deferred:default-cancel')
|
||||
;; next : a next chained deferred object (default nil)
|
||||
;; status : if 'ok or 'ng, this deferred has a result (error) value. (default nil)
|
||||
;; value : saved value (default nil)
|
||||
;;
|
||||
(cl-defstruct deferred
|
||||
(callback 'deferred:default-callback)
|
||||
(errorback 'deferred:default-errorback)
|
||||
(cancel 'deferred:default-cancel)
|
||||
next status value)
|
||||
|
||||
(defun deferred:default-callback (i)
|
||||
"[internal] Default callback function."
|
||||
(identity i))
|
||||
|
||||
(defun deferred:default-errorback (err)
|
||||
"[internal] Default errorback function."
|
||||
(deferred:resignal err))
|
||||
|
||||
(defun deferred:resignal (err)
|
||||
"[internal] Safely resignal ERR as an Emacs condition.
|
||||
|
||||
If ERR is a cons (ERROR-SYMBOL . DATA) where ERROR-SYMBOL has an
|
||||
`error-conditions' property, it is re-signaled unchanged. If ERR
|
||||
is a string, it is signaled as a generic error using `error'.
|
||||
Otherwise, ERR is formatted into a string as if by `print' before
|
||||
raising with `error'."
|
||||
(cond ((and (listp err)
|
||||
(symbolp (car err))
|
||||
(get (car err) 'error-conditions))
|
||||
(signal (car err) (cdr err)))
|
||||
((stringp err)
|
||||
(error "%s" err))
|
||||
(t
|
||||
(error "%S" err))))
|
||||
|
||||
(defun deferred:default-cancel (d)
|
||||
"[internal] Default canceling function."
|
||||
(deferred:message "CANCEL : %s" d)
|
||||
(setf (deferred-callback d) 'deferred:default-callback)
|
||||
(setf (deferred-errorback d) 'deferred:default-errorback)
|
||||
(setf (deferred-next d) nil)
|
||||
d)
|
||||
|
||||
(defvar deferred:onerror nil
|
||||
"Default error handler. This value is nil or a function that
|
||||
have one argument for the error message.")
|
||||
|
||||
(defun deferred:exec-task (d which &optional arg)
|
||||
"[internal] Executing deferred task. If the deferred object has
|
||||
next deferred task or the return value is a deferred object, this
|
||||
function adds the task to the execution queue.
|
||||
D is a deferred object. WHICH is a symbol, `ok' or `ng'. ARG is
|
||||
an argument value for execution of the deferred task."
|
||||
(deferred:message "EXEC : %s / %s / %s" d which arg)
|
||||
(when (null d) (error "deferred:exec-task was given a nil."))
|
||||
(let ((callback (if (eq which 'ok)
|
||||
(deferred-callback d)
|
||||
(deferred-errorback d)))
|
||||
(next-deferred (deferred-next d)))
|
||||
(cond
|
||||
(callback
|
||||
(deferred:condition-case err
|
||||
(let ((value (deferred:call-lambda callback arg)))
|
||||
(cond
|
||||
((deferred-p value)
|
||||
(deferred:message "WAIT NEST : %s" value)
|
||||
(if next-deferred
|
||||
(deferred:set-next value next-deferred)
|
||||
value))
|
||||
(t
|
||||
(if next-deferred
|
||||
(deferred:post-task next-deferred 'ok value)
|
||||
(setf (deferred-status d) 'ok)
|
||||
(setf (deferred-value d) value)
|
||||
value))))
|
||||
(error
|
||||
(cond
|
||||
(next-deferred
|
||||
(deferred:post-task next-deferred 'ng err))
|
||||
(deferred:onerror
|
||||
(deferred:call-lambda deferred:onerror err))
|
||||
(t
|
||||
(deferred:message "ERROR : %S" err)
|
||||
(message "deferred error : %S" err)
|
||||
(setf (deferred-status d) 'ng)
|
||||
(setf (deferred-value d) err)
|
||||
err)))))
|
||||
(t ; <= (null callback)
|
||||
(cond
|
||||
(next-deferred
|
||||
(deferred:exec-task next-deferred which arg))
|
||||
((eq which 'ok) arg)
|
||||
(t ; (eq which 'ng)
|
||||
(deferred:resignal arg)))))))
|
||||
|
||||
(defun deferred:set-next (prev next)
|
||||
"[internal] Connect deferred objects."
|
||||
(setf (deferred-next prev) next)
|
||||
(cond
|
||||
((eq 'ok (deferred-status prev))
|
||||
(setf (deferred-status prev) nil)
|
||||
(let ((ret (deferred:exec-task
|
||||
next 'ok (deferred-value prev))))
|
||||
(if (deferred-p ret) ret
|
||||
next)))
|
||||
((eq 'ng (deferred-status prev))
|
||||
(setf (deferred-status prev) nil)
|
||||
(let ((ret (deferred:exec-task next 'ng (deferred-value prev))))
|
||||
(if (deferred-p ret) ret
|
||||
next)))
|
||||
(t
|
||||
next)))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Basic functions for deferred objects
|
||||
|
||||
(defun deferred:new (&optional callback)
|
||||
"Create a deferred object."
|
||||
(if callback
|
||||
(make-deferred :callback callback)
|
||||
(make-deferred)))
|
||||
|
||||
(defun deferred:callback (d &optional arg)
|
||||
"Start deferred chain with a callback message."
|
||||
(deferred:exec-task d 'ok arg))
|
||||
|
||||
(defun deferred:errorback (d &optional arg)
|
||||
"Start deferred chain with an errorback message."
|
||||
(deferred:exec-task d 'ng arg))
|
||||
|
||||
(defun deferred:callback-post (d &optional arg)
|
||||
"Add the deferred object to the execution queue."
|
||||
(deferred:post-task d 'ok arg))
|
||||
|
||||
(defun deferred:errorback-post (d &optional arg)
|
||||
"Add the deferred object to the execution queue."
|
||||
(deferred:post-task d 'ng arg))
|
||||
|
||||
(defun deferred:cancel (d)
|
||||
"Cancel all callbacks and deferred chain in the deferred object."
|
||||
(deferred:message "CANCEL : %s" d)
|
||||
(funcall (deferred-cancel d) d)
|
||||
d)
|
||||
|
||||
(defun deferred:status (d)
|
||||
"Return a current status of the deferred object. The returned value means following:
|
||||
`ok': the callback was called and waiting for next deferred.
|
||||
`ng': the errorback was called and waiting for next deferred.
|
||||
nil: The neither callback nor errorback was not called."
|
||||
(deferred-status d))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Basic utility functions
|
||||
|
||||
(defun deferred:succeed (&optional arg)
|
||||
"Create a synchronous deferred object."
|
||||
(let ((d (deferred:new)))
|
||||
(deferred:exec-task d 'ok arg)
|
||||
d))
|
||||
|
||||
(defun deferred:fail (&optional arg)
|
||||
"Create a synchronous deferred object."
|
||||
(let ((d (deferred:new)))
|
||||
(deferred:exec-task d 'ng arg)
|
||||
d))
|
||||
|
||||
(defun deferred:next (&optional callback arg)
|
||||
"Create a deferred object and schedule executing. This function
|
||||
is a short cut of following code:
|
||||
(deferred:callback-post (deferred:new callback))."
|
||||
(let ((d (if callback
|
||||
(make-deferred :callback callback)
|
||||
(make-deferred))))
|
||||
(deferred:callback-post d arg)
|
||||
d))
|
||||
|
||||
(defun deferred:nextc (d callback)
|
||||
"Create a deferred object with OK callback and connect it to the given deferred object."
|
||||
(let ((nd (make-deferred :callback callback)))
|
||||
(deferred:set-next d nd)))
|
||||
|
||||
(defun deferred:error (d callback)
|
||||
"Create a deferred object with errorback and connect it to the given deferred object."
|
||||
(let ((nd (make-deferred :errorback callback)))
|
||||
(deferred:set-next d nd)))
|
||||
|
||||
(defun deferred:watch (d callback)
|
||||
"Create a deferred object with watch task and connect it to the given deferred object.
|
||||
The watch task CALLBACK can not affect deferred chains with
|
||||
return values. This function is used in following purposes,
|
||||
simulation of try-finally block in asynchronous tasks, progress
|
||||
monitoring of tasks."
|
||||
(let* ((callback callback)
|
||||
(normal (lambda (x) (ignore-errors (deferred:call-lambda callback x)) x))
|
||||
(err (lambda (e)
|
||||
(ignore-errors (deferred:call-lambda callback e))
|
||||
(deferred:resignal e))))
|
||||
(let ((nd (make-deferred :callback normal :errorback err)))
|
||||
(deferred:set-next d nd))))
|
||||
|
||||
(defun deferred:wait (msec)
|
||||
"Return a deferred object scheduled at MSEC millisecond later."
|
||||
(let ((d (deferred:new)) (start-time (float-time)) timer)
|
||||
(deferred:message "WAIT : %s" msec)
|
||||
(setq timer (deferred:setTimeout
|
||||
(lambda ()
|
||||
(deferred:exec-task d 'ok
|
||||
(* 1000.0 (- (float-time) start-time)))
|
||||
nil) msec))
|
||||
(setf (deferred-cancel d)
|
||||
(lambda (x)
|
||||
(deferred:cancelTimeout timer)
|
||||
(deferred:default-cancel x)))
|
||||
d))
|
||||
|
||||
(defun deferred:wait-idle (msec)
|
||||
"Return a deferred object which will run when Emacs has been
|
||||
idle for MSEC millisecond."
|
||||
(let ((d (deferred:new)) (start-time (float-time)) timer)
|
||||
(deferred:message "WAIT-IDLE : %s" msec)
|
||||
(setq timer
|
||||
(deferred:run-with-idle-timer
|
||||
(/ msec 1000.0)
|
||||
(lambda ()
|
||||
(deferred:exec-task d 'ok
|
||||
(* 1000.0 (- (float-time) start-time)))
|
||||
nil)))
|
||||
(setf (deferred-cancel d)
|
||||
(lambda (x)
|
||||
(deferred:cancelTimeout timer)
|
||||
(deferred:default-cancel x)))
|
||||
d))
|
||||
|
||||
(defun deferred:call (f &rest args)
|
||||
"Call the given function asynchronously."
|
||||
(deferred:next
|
||||
(lambda (_x)
|
||||
(apply f args))))
|
||||
|
||||
(defun deferred:apply (f &optional args)
|
||||
"Call the given function asynchronously."
|
||||
(deferred:next
|
||||
(lambda (_x)
|
||||
(apply f args))))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Utility functions
|
||||
|
||||
(defun deferred:empty-p (times-or-seq)
|
||||
"[internal] Return non-nil if TIMES-OR-SEQ is the number zero or nil."
|
||||
(or (and (numberp times-or-seq) (<= times-or-seq 0))
|
||||
(and (sequencep times-or-seq) (= (length times-or-seq) 0))))
|
||||
|
||||
(defun deferred:loop (times-or-seq func)
|
||||
"Return a iteration deferred object."
|
||||
(deferred:message "LOOP : %s" times-or-seq)
|
||||
(if (deferred:empty-p times-or-seq) (deferred:next)
|
||||
(let* (items (rd
|
||||
(cond
|
||||
((numberp times-or-seq)
|
||||
(cl-loop for i from 0 below times-or-seq
|
||||
with ld = (deferred:next)
|
||||
do
|
||||
(push ld items)
|
||||
(setq ld
|
||||
(let ((i i))
|
||||
(deferred:nextc ld
|
||||
(lambda (_x) (deferred:call-lambda func i)))))
|
||||
finally return ld))
|
||||
((sequencep times-or-seq)
|
||||
(cl-loop for i in (append times-or-seq nil) ; seq->list
|
||||
with ld = (deferred:next)
|
||||
do
|
||||
(push ld items)
|
||||
(setq ld
|
||||
(let ((i i))
|
||||
(deferred:nextc ld
|
||||
(lambda (_x) (deferred:call-lambda func i)))))
|
||||
finally return ld)))))
|
||||
(setf (deferred-cancel rd)
|
||||
(lambda (x) (deferred:default-cancel x)
|
||||
(cl-loop for i in items
|
||||
do (deferred:cancel i))))
|
||||
rd)))
|
||||
|
||||
(defun deferred:trans-multi-args (args self-func list-func main-func)
|
||||
"[internal] Check the argument values and dispatch to methods."
|
||||
(cond
|
||||
((and (= 1 (length args)) (consp (car args)) (not (functionp (car args))))
|
||||
(let ((lst (car args)))
|
||||
(cond
|
||||
((or (null lst) (null (car lst)))
|
||||
(deferred:next))
|
||||
((deferred:aand lst (car it) (or (functionp it) (deferred-p it)))
|
||||
;; a list of deferred objects
|
||||
(funcall list-func lst))
|
||||
((deferred:aand lst (consp it))
|
||||
;; an alist of deferred objects
|
||||
(funcall main-func lst))
|
||||
(t (error "Wrong argument type. %s" args)))))
|
||||
(t (funcall self-func args))))
|
||||
|
||||
(defun deferred:parallel-array-to-alist (lst)
|
||||
"[internal] Translation array to alist."
|
||||
(cl-loop for d in lst
|
||||
for i from 0 below (length lst)
|
||||
collect (cons i d)))
|
||||
|
||||
(defun deferred:parallel-alist-to-array (alst)
|
||||
"[internal] Translation alist to array."
|
||||
(cl-loop for pair in
|
||||
(sort alst (lambda (x y)
|
||||
(< (car x) (car y))))
|
||||
collect (cdr pair)))
|
||||
|
||||
(defun deferred:parallel-func-to-deferred (alst)
|
||||
"[internal] Normalization for parallel and earlier arguments."
|
||||
(cl-loop for pair in alst
|
||||
for d = (cdr pair)
|
||||
collect
|
||||
(progn
|
||||
(unless (deferred-p d)
|
||||
(setf (cdr pair) (deferred:next d)))
|
||||
pair)))
|
||||
|
||||
(defun deferred:parallel-main (alst)
|
||||
"[internal] Deferred alist implementation for `deferred:parallel'. "
|
||||
(deferred:message "PARALLEL<KEY . VALUE>" )
|
||||
(let ((nd (deferred:new))
|
||||
(len (length alst))
|
||||
values)
|
||||
(cl-loop for pair in
|
||||
(deferred:parallel-func-to-deferred alst)
|
||||
with cd ; current child deferred
|
||||
do
|
||||
(let ((name (car pair)))
|
||||
(setq cd
|
||||
(deferred:nextc (cdr pair)
|
||||
(lambda (x)
|
||||
(push (cons name x) values)
|
||||
(deferred:message "PARALLEL VALUE [%s/%s] %s"
|
||||
(length values) len (cons name x))
|
||||
(when (= len (length values))
|
||||
(deferred:message "PARALLEL COLLECTED")
|
||||
(deferred:post-task nd 'ok (nreverse values)))
|
||||
nil)))
|
||||
(deferred:error cd
|
||||
(lambda (e)
|
||||
(push (cons name e) values)
|
||||
(deferred:message "PARALLEL ERROR [%s/%s] %s"
|
||||
(length values) len (cons name e))
|
||||
(when (= (length values) len)
|
||||
(deferred:message "PARALLEL COLLECTED")
|
||||
(deferred:post-task nd 'ok (nreverse values)))
|
||||
nil))))
|
||||
nd))
|
||||
|
||||
(defun deferred:parallel-list (lst)
|
||||
"[internal] Deferred list implementation for `deferred:parallel'. "
|
||||
(deferred:message "PARALLEL<LIST>" )
|
||||
(let* ((pd (deferred:parallel-main (deferred:parallel-array-to-alist lst)))
|
||||
(rd (deferred:nextc pd 'deferred:parallel-alist-to-array)))
|
||||
(setf (deferred-cancel rd)
|
||||
(lambda (x) (deferred:default-cancel x)
|
||||
(deferred:cancel pd)))
|
||||
rd))
|
||||
|
||||
(defun deferred:parallel (&rest args)
|
||||
"Return a deferred object that calls given deferred objects or
|
||||
functions in parallel and wait for all callbacks. The following
|
||||
deferred task will be called with an array of the return
|
||||
values. ARGS can be a list or an alist of deferred objects or
|
||||
functions."
|
||||
(deferred:message "PARALLEL : %s" args)
|
||||
(deferred:trans-multi-args args
|
||||
'deferred:parallel 'deferred:parallel-list 'deferred:parallel-main))
|
||||
|
||||
(defun deferred:earlier-main (alst)
|
||||
"[internal] Deferred alist implementation for `deferred:earlier'. "
|
||||
(deferred:message "EARLIER<KEY . VALUE>" )
|
||||
(let ((nd (deferred:new))
|
||||
(len (length alst))
|
||||
value results)
|
||||
(cl-loop for pair in
|
||||
(deferred:parallel-func-to-deferred alst)
|
||||
with cd ; current child deferred
|
||||
do
|
||||
(let ((name (car pair)))
|
||||
(setq cd
|
||||
(deferred:nextc (cdr pair)
|
||||
(lambda (x)
|
||||
(push (cons name x) results)
|
||||
(cond
|
||||
((null value)
|
||||
(setq value (cons name x))
|
||||
(deferred:message "EARLIER VALUE %s" (cons name value))
|
||||
(deferred:post-task nd 'ok value))
|
||||
(t
|
||||
(deferred:message "EARLIER MISS [%s/%s] %s" (length results) len (cons name value))
|
||||
(when (eql (length results) len)
|
||||
(deferred:message "EARLIER COLLECTED"))))
|
||||
nil)))
|
||||
(deferred:error cd
|
||||
(lambda (e)
|
||||
(push (cons name e) results)
|
||||
(deferred:message "EARLIER ERROR [%s/%s] %s" (length results) len (cons name e))
|
||||
(when (and (eql (length results) len) (null value))
|
||||
(deferred:message "EARLIER FAILED")
|
||||
(deferred:post-task nd 'ok nil))
|
||||
nil))))
|
||||
nd))
|
||||
|
||||
(defun deferred:earlier-list (lst)
|
||||
"[internal] Deferred list implementation for `deferred:earlier'. "
|
||||
(deferred:message "EARLIER<LIST>" )
|
||||
(let* ((pd (deferred:earlier-main (deferred:parallel-array-to-alist lst)))
|
||||
(rd (deferred:nextc pd (lambda (x) (cdr x)))))
|
||||
(setf (deferred-cancel rd)
|
||||
(lambda (x) (deferred:default-cancel x)
|
||||
(deferred:cancel pd)))
|
||||
rd))
|
||||
|
||||
|
||||
(defun deferred:earlier (&rest args)
|
||||
"Return a deferred object that calls given deferred objects or
|
||||
functions in parallel and wait for the first callback. The
|
||||
following deferred task will be called with the first return
|
||||
value. ARGS can be a list or an alist of deferred objects or
|
||||
functions."
|
||||
(deferred:message "EARLIER : %s" args)
|
||||
(deferred:trans-multi-args args
|
||||
'deferred:earlier 'deferred:earlier-list 'deferred:earlier-main))
|
||||
|
||||
(defmacro deferred:timeout (timeout-msec timeout-form d)
|
||||
"Time out macro on a deferred task D. If the deferred task D
|
||||
does not complete within TIMEOUT-MSEC, this macro cancels the
|
||||
deferred task and return the TIMEOUT-FORM."
|
||||
`(deferred:earlier
|
||||
(deferred:nextc (deferred:wait ,timeout-msec)
|
||||
(lambda (x) ,timeout-form))
|
||||
,d))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Application functions
|
||||
|
||||
(defvar deferred:uid 0 "[internal] Sequence number for some utilities. See the function `deferred:uid'.")
|
||||
|
||||
(defun deferred:uid ()
|
||||
"[internal] Generate a sequence number."
|
||||
(cl-incf deferred:uid))
|
||||
|
||||
(defun deferred:buffer-string (strformat buf)
|
||||
"[internal] Return a string in the buffer with the given format."
|
||||
(format strformat
|
||||
(with-current-buffer buf (buffer-string))))
|
||||
|
||||
(defun deferred:process (command &rest args)
|
||||
"A deferred wrapper of `start-process'. Return a deferred
|
||||
object. The process name and buffer name of the argument of the
|
||||
`start-process' are generated by this function automatically.
|
||||
The next deferred object receives stdout and stderr string from
|
||||
the command process."
|
||||
(deferred:process-gen 'start-process command args))
|
||||
|
||||
(defun deferred:process-shell (command &rest args)
|
||||
"A deferred wrapper of `start-process-shell-command'. Return a deferred
|
||||
object. The process name and buffer name of the argument of the
|
||||
`start-process-shell-command' are generated by this function automatically.
|
||||
The next deferred object receives stdout and stderr string from
|
||||
the command process."
|
||||
(deferred:process-gen 'start-process-shell-command command args))
|
||||
|
||||
(defun deferred:process-buffer (command &rest args)
|
||||
"A deferred wrapper of `start-process'. Return a deferred
|
||||
object. The process name and buffer name of the argument of the
|
||||
`start-process' are generated by this function automatically.
|
||||
The next deferred object receives stdout and stderr buffer from
|
||||
the command process."
|
||||
(deferred:process-buffer-gen 'start-process command args))
|
||||
|
||||
(defun deferred:process-shell-buffer (command &rest args)
|
||||
"A deferred wrapper of `start-process-shell-command'. Return a deferred
|
||||
object. The process name and buffer name of the argument of the
|
||||
`start-process-shell-command' are generated by this function automatically.
|
||||
The next deferred object receives stdout and stderr buffer from
|
||||
the command process."
|
||||
(deferred:process-buffer-gen 'start-process-shell-command command args))
|
||||
|
||||
(defun deferred:process-gen (f command args)
|
||||
"[internal]"
|
||||
(let ((pd (deferred:process-buffer-gen f command args)) d)
|
||||
(setq d (deferred:nextc pd
|
||||
(lambda (buf)
|
||||
(prog1
|
||||
(with-current-buffer buf (buffer-string))
|
||||
(kill-buffer buf)))))
|
||||
(setf (deferred-cancel d)
|
||||
(lambda (_x)
|
||||
(deferred:default-cancel d)
|
||||
(deferred:default-cancel pd)))
|
||||
d))
|
||||
|
||||
(defun deferred:process-buffer-gen (f command args)
|
||||
"[internal]"
|
||||
(let ((d (deferred:next)) (uid (deferred:uid)))
|
||||
(let ((proc-name (format "*deferred:*%s*:%s" command uid))
|
||||
(buf-name (format " *deferred:*%s*:%s" command uid))
|
||||
(pwd default-directory)
|
||||
(env process-environment)
|
||||
(con-type process-connection-type)
|
||||
(nd (deferred:new)) proc-buf proc)
|
||||
(deferred:nextc d
|
||||
(lambda (_x)
|
||||
(setq proc-buf (get-buffer-create buf-name))
|
||||
(condition-case err
|
||||
(let ((default-directory pwd)
|
||||
(process-environment env)
|
||||
(process-connection-type con-type))
|
||||
(setq proc
|
||||
(if (null (car args))
|
||||
(apply f proc-name buf-name command nil)
|
||||
(apply f proc-name buf-name command args)))
|
||||
(set-process-sentinel
|
||||
proc
|
||||
(lambda (proc event)
|
||||
(unless (process-live-p proc)
|
||||
(if (zerop (process-exit-status proc))
|
||||
(deferred:post-task nd 'ok proc-buf)
|
||||
(let ((msg (format "Deferred process exited abnormally:\n command: %s\n exit status: %s %s\n event: %s\n buffer contents: %S"
|
||||
command
|
||||
(process-status proc)
|
||||
(process-exit-status proc)
|
||||
(string-trim-right event)
|
||||
(if (buffer-live-p proc-buf)
|
||||
(with-current-buffer proc-buf
|
||||
(buffer-string))
|
||||
"(unavailable)"))))
|
||||
(kill-buffer proc-buf)
|
||||
(deferred:post-task nd 'ng msg))))))
|
||||
(setf (deferred-cancel nd)
|
||||
(lambda (x) (deferred:default-cancel x)
|
||||
(when proc
|
||||
(kill-process proc)
|
||||
(kill-buffer proc-buf)))))
|
||||
(error (deferred:post-task nd 'ng err)))
|
||||
nil))
|
||||
nd)))
|
||||
|
||||
(defmacro deferred:processc (d command &rest args)
|
||||
"Process chain of `deferred:process'."
|
||||
`(deferred:nextc ,d
|
||||
(lambda (,(cl-gensym)) (deferred:process ,command ,@args))))
|
||||
|
||||
(defmacro deferred:process-bufferc (d command &rest args)
|
||||
"Process chain of `deferred:process-buffer'."
|
||||
`(deferred:nextc ,d
|
||||
(lambda (,(cl-gensym)) (deferred:process-buffer ,command ,@args))))
|
||||
|
||||
(defmacro deferred:process-shellc (d command &rest args)
|
||||
"Process chain of `deferred:process'."
|
||||
`(deferred:nextc ,d
|
||||
(lambda (,(cl-gensym)) (deferred:process-shell ,command ,@args))))
|
||||
|
||||
(defmacro deferred:process-shell-bufferc (d command &rest args)
|
||||
"Process chain of `deferred:process-buffer'."
|
||||
`(deferred:nextc ,d
|
||||
(lambda (,(cl-gensym)) (deferred:process-shell-buffer ,command ,@args))))
|
||||
|
||||
;; Special variables defined in url-vars.el.
|
||||
(defvar url-request-data)
|
||||
(defvar url-request-method)
|
||||
(defvar url-request-extra-headers)
|
||||
|
||||
(declare-function url-http-symbol-value-in-buffer "url-http"
|
||||
(symbol buffer &optional unbound-value))
|
||||
|
||||
(declare-function deferred:url-param-serialize "request" (params))
|
||||
|
||||
(declare-function deferred:url-escape "request" (val))
|
||||
|
||||
(eval-after-load "url"
|
||||
;; for url package
|
||||
;; TODO: proxy, charaset
|
||||
;; List of gloabl variables to preserve and restore before url-retrieve call
|
||||
'(let ((url-global-variables '(url-request-data
|
||||
url-request-method
|
||||
url-request-extra-headers)))
|
||||
|
||||
(defun deferred:url-retrieve (url &optional cbargs silent inhibit-cookies)
|
||||
"A wrapper function for url-retrieve. The next deferred
|
||||
object receives the buffer object that URL will load
|
||||
into. Values of dynamically bound 'url-request-data', 'url-request-method' and
|
||||
'url-request-extra-headers' are passed to url-retrieve call."
|
||||
(let ((nd (deferred:new))
|
||||
buf
|
||||
(local-values (mapcar (lambda (symbol) (symbol-value symbol)) url-global-variables)))
|
||||
(deferred:next
|
||||
(lambda (_x)
|
||||
(cl-progv url-global-variables local-values
|
||||
(condition-case err
|
||||
(setq buf
|
||||
(url-retrieve
|
||||
url (lambda (_xx) (deferred:post-task nd 'ok buf))
|
||||
cbargs silent inhibit-cookies))
|
||||
(error (deferred:post-task nd 'ng err)))
|
||||
nil)))
|
||||
(setf (deferred-cancel nd)
|
||||
(lambda (_x)
|
||||
(when (buffer-live-p buf)
|
||||
(kill-buffer buf))))
|
||||
nd))
|
||||
|
||||
(defun deferred:url-delete-header (buf)
|
||||
(with-current-buffer buf
|
||||
(let ((pos (url-http-symbol-value-in-buffer
|
||||
'url-http-end-of-headers buf)))
|
||||
(when pos
|
||||
(delete-region (point-min) (1+ pos)))))
|
||||
buf)
|
||||
|
||||
(defun deferred:url-delete-buffer (buf)
|
||||
(when (and buf (buffer-live-p buf))
|
||||
(kill-buffer buf))
|
||||
nil)
|
||||
|
||||
(defun deferred:url-get (url &optional params &rest args)
|
||||
"Perform a HTTP GET method with `url-retrieve'. PARAMS is
|
||||
a parameter list of (key . value) or key. ARGS will be appended
|
||||
to deferred:url-retrieve args list. The next deferred
|
||||
object receives the buffer object that URL will load into."
|
||||
(when params
|
||||
(setq url
|
||||
(concat url "?" (deferred:url-param-serialize params))))
|
||||
(let ((d (deferred:$
|
||||
(apply 'deferred:url-retrieve url args)
|
||||
(deferred:nextc it 'deferred:url-delete-header))))
|
||||
(deferred:set-next
|
||||
d (deferred:new 'deferred:url-delete-buffer))
|
||||
d))
|
||||
|
||||
(defun deferred:url-post (url &optional params &rest args)
|
||||
"Perform a HTTP POST method with `url-retrieve'. PARAMS is
|
||||
a parameter list of (key . value) or key. ARGS will be appended
|
||||
to deferred:url-retrieve args list. The next deferred
|
||||
object receives the buffer object that URL will load into."
|
||||
(let ((url-request-method "POST")
|
||||
(url-request-extra-headers
|
||||
(append url-request-extra-headers
|
||||
'(("Content-Type" . "application/x-www-form-urlencoded"))))
|
||||
(url-request-data (deferred:url-param-serialize params)))
|
||||
(let ((d (deferred:$
|
||||
(apply 'deferred:url-retrieve url args)
|
||||
(deferred:nextc it 'deferred:url-delete-header))))
|
||||
(deferred:set-next
|
||||
d (deferred:new 'deferred:url-delete-buffer))
|
||||
d)))
|
||||
|
||||
(defun deferred:url-escape (val)
|
||||
"[internal] Return a new string that is VAL URI-encoded."
|
||||
(unless (stringp val)
|
||||
(setq val (format "%s" val)))
|
||||
(url-hexify-string
|
||||
(encode-coding-string val 'utf-8)))
|
||||
|
||||
(defun deferred:url-param-serialize (params)
|
||||
"[internal] Serialize a list of (key . value) cons cells
|
||||
into a query string."
|
||||
(when params
|
||||
(mapconcat
|
||||
'identity
|
||||
(cl-loop for p in params
|
||||
collect
|
||||
(cond
|
||||
((consp p)
|
||||
(concat
|
||||
(deferred:url-escape (car p)) "="
|
||||
(deferred:url-escape (cdr p))))
|
||||
(t
|
||||
(deferred:url-escape p))))
|
||||
"&")))
|
||||
))
|
||||
|
||||
|
||||
(provide 'deferred)
|
||||
;;; deferred.el ends here
|
||||
6
lisp/emacs-application-framework/.gitattributes
vendored
Normal file
6
lisp/emacs-application-framework/.gitattributes
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
core/aria2-ng/index.html linguist-vendored
|
||||
core/js/dark_mode.js linguist-vendored
|
||||
core/js/caret_browsing.js linguist-vendored
|
||||
app/mindmap/*.js linguist-vendored
|
||||
28
lisp/emacs-application-framework/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
28
lisp/emacs-application-framework/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: EAF Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Ensure you're on the latest master branch, then note the steps to reproduce the behavior.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Versions (please complete the following info):**
|
||||
- Distro and DE/WM:
|
||||
- Versions of Dependencies:
|
||||
- M-x emacs-version:
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
lisp/emacs-application-framework/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
lisp/emacs-application-framework/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: EAF Feature request
|
||||
about: Suggest an idea for the Emacs Application Framework
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of an alternative solutions or features you've considered, if any.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
11
lisp/emacs-application-framework/.github/dependabot.yml
vendored
Normal file
11
lisp/emacs-application-framework/.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm" # See https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
8
lisp/emacs-application-framework/.gitignore
vendored
Executable file
8
lisp/emacs-application-framework/.gitignore
vendored
Executable file
@@ -0,0 +1,8 @@
|
||||
*.elc
|
||||
*.pyc
|
||||
/.log/
|
||||
/app/js-video-player/node_modules/
|
||||
/app/mermaid/node_modules/
|
||||
/app/terminal/node_modules/
|
||||
/app/image-viewer/node_modules/
|
||||
/app/markdown-previewer/node_modules/
|
||||
@@ -6,7 +6,7 @@ EAF is a GUI application framework that revolutionizes Emacs graphical capabilit
|
||||
## EAF Application Overview
|
||||
EAF is an extensible framework, one can develop any Qt5 application and integrate it into Emacs.
|
||||
|
||||
| Browser | Markdown Previewer |
|
||||
| Browser | Markdown Previewer (support Mermaid and PlantUML) |
|
||||
| :--------: | :----: |
|
||||
| <img src="./screenshot/browser.gif" width="400"> | <img src="./screenshot/markdown_previewer.gif" width="400"> |
|
||||
|
||||
@@ -31,7 +31,7 @@ EAF is an extensible framework, one can develop any Qt5 application and integrat
|
||||
| <img src="./screenshot/air_share.png" width="400"> | <img src="./screenshot/org_previewer.gif" width="400"> |
|
||||
| | |
|
||||
|
||||
| Terminal Emulator | RSS Reader |
|
||||
| Terminal Emulator | RSS Reader (Integrated with Elfeed) |
|
||||
| :--------: | :------: |
|
||||
| <img src="./screenshot/terminal.gif" width="400"> | <img src="./screenshot/rss_reader.gif" width="400"> |
|
||||
| | |
|
||||
@@ -42,92 +42,101 @@ EAF is an extensible framework, one can develop any Qt5 application and integrat
|
||||
| | |
|
||||
|
||||
|
||||
| Mermaid | EAF Interleave |
|
||||
| Jupyter | EAF Interleave |
|
||||
| :--------: | :----------: |
|
||||
| <img src="./screenshot/mermaid.gif" width="400"> | <img src="./screenshot/eaf-interleave.gif" width="400"> |
|
||||
| <img src="./screenshot/jupyter.png" width="400"> | <img src="./screenshot/eaf-interleave.gif" width="400"> |
|
||||
| | |
|
||||
|
||||
## EmacsConf2020 - Extend Emacs to Modern GUI Applications with EAF
|
||||
- EAF talk & demo at EmacsConf2020, presented to you by [MatthewZMD](https://github.com/MatthewZMD)
|
||||
- Homepage (Q&A included): https://emacsconf.org/2020/talks/34/
|
||||
- Youtube link:
|
||||
|
||||
[](https://www.youtube.com/watch?v=HK_f8KTuR0s)
|
||||
|
||||
## Install
|
||||
1. Install EAF dependencies, an explaination of each dependency can be found in [Dependency List](#dependency-list).
|
||||
|
||||
The following line is for *Archlinux*, same packages should be available to install on your particular distribution:
|
||||
|
||||
1. Download EAF
|
||||
```Bash
|
||||
yay -S python-pyqt5 python-pyqt5-sip python-pyqtwebengine python-qrcode python-feedparser python-dbus python-pyinotify python-markdown nodejs aria2 libreoffice python-pymupdf python-grip filebrowser-bin
|
||||
git clone --depth=1 -b master https://github.com/manateelazycat/emacs-application-framework.git ~/.emacs.d/site-lisp/emacs-application-framework/
|
||||
```
|
||||
|
||||
2. Clone this repository.
|
||||
|
||||
```Bash
|
||||
git clone https://github.com/manateelazycat/emacs-application-framework.git --depth=1
|
||||
Alternatively, you can use a [Quelpa recipe](https://github.com/quelpa/quelpa)
|
||||
```Emacs-lisp
|
||||
(quelpa '(eaf (:fetcher github
|
||||
:repo "manateelazycat/emacs-application-framework"
|
||||
:files ("*"))))
|
||||
```
|
||||
|
||||
3. Add the full path to the EAF installation directory to your Emacs ```load-path```, then add the following to `init.el`:
|
||||
2. Install EAF dependencies using `M-x install-eaf-dependencies`.
|
||||
|
||||
If you prefer to manually call the installation script in the terminal,
|
||||
|
||||
- If you use GNU/Linux,
|
||||
|
||||
```Bash
|
||||
cd emacs-application-framework
|
||||
chmod +x ./install-eaf.sh
|
||||
./install-eaf.sh
|
||||
```
|
||||
|
||||
- If you use Windows,
|
||||
|
||||
```shell
|
||||
cd emacs-application-framework
|
||||
node ./install-eaf-win32.js
|
||||
```
|
||||
|
||||
Feel free to inspect the install script yourself. An explanation of each dependency can be found at [Dependency List](#dependency-list).
|
||||
|
||||
3. Install Elisp packages:
|
||||
- [emacs-ctable](https://github.com/kiwanami/emacs-ctable)
|
||||
- [emacs-deferred](https://github.com/kiwanami/emacs-deferred)
|
||||
- [emacs-epc](https://github.com/kiwanami/emacs-epc)
|
||||
- [s.el](https://github.com/magnars/s.el)
|
||||
|
||||
4. From here on, you can either add the full path to the EAF installation directory to your Emacs ```load-path```, then add the following to `init.el`:
|
||||
|
||||
```Elisp
|
||||
(add-to-list 'load-path "~/.emacs.d/site-lisp/emacs-application-framework/")
|
||||
(require 'eaf)
|
||||
```
|
||||
|
||||
If you use [use-package](https://github.com/jwiegley/use-package), a sample configuration has been provided.
|
||||
or, if you use [use-package](https://github.com/jwiegley/use-package), you can use the following *sample* configuration for your convenience.
|
||||
|
||||
```Elisp
|
||||
(use-package eaf
|
||||
:load-path "~/.emacs.d/site-lisp/emacs-application-framework" ; Set to "/usr/share/emacs/site-lisp/eaf" if installed from AUR
|
||||
:init
|
||||
(use-package epc :defer t)
|
||||
(use-package ctable :defer t)
|
||||
(use-package deferred :defer t)
|
||||
(use-package s :defer t :ensure t)
|
||||
:custom
|
||||
(eaf-find-alternate-file-in-dired t)
|
||||
(eaf-browser-continue-where-left-off t)
|
||||
:config
|
||||
(eaf-setq eaf-browser-enable-adblocker "true")
|
||||
(eaf-bind-key scroll_up "C-n" eaf-pdf-viewer-keybinding)
|
||||
(eaf-bind-key scroll_down "C-p" eaf-pdf-viewer-keybinding)
|
||||
(eaf-bind-key take_photo "p" eaf-camera-keybinding))
|
||||
(eaf-bind-key take_photo "p" eaf-camera-keybinding)
|
||||
(eaf-bind-key nil "M-q" eaf-browser-keybinding)) ;; unbind, see more in the Wiki
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
If you use [Chemacs](https://github.com/plexus/chemacs), a sample `init.el` is provided as follows:
|
||||
|
||||
```Elisp
|
||||
;; An example of init.el
|
||||
|
||||
(defun add-subdirs-to-load-path (dir)
|
||||
"Recursive add directories to `load-path'."
|
||||
(let ((default-directory (file-name-as-directory dir)))
|
||||
(add-to-list 'load-path dir)
|
||||
(normal-top-level-add-subdirs-to-load-path)))
|
||||
(add-subdirs-to-load-path "~/.emacs.d/")
|
||||
|
||||
(require 'eaf)
|
||||
```
|
||||
|
||||
During EAF installation, you only need to modify the parameter value when calling function `add-subdirs-to-load-path`, change it into your full path to the EAF installation directory. The sample gives a situation when you install EAF at `~/.emacs.d/`.
|
||||
|
||||
After EAF installation, let's assume your EAF installation directory is `~/eaf`, you only have Emacs configurations at `~/.emacs.d` and EAF installed on your computer, and you have installed Chemacs, then the `.emacs-profiles.el` should look like this:
|
||||
|
||||
```Elisp
|
||||
(("default" . ((user-emacs-directory . "~/.emacs.d")))
|
||||
("EAF" . ((user-emacs-directory . "~/eaf"))))
|
||||
```
|
||||
|
||||
When you want to use EAF by chemacs, you can excute `emacs --with-profile EAF` in the terminal.
|
||||
|
||||
### Dependency List
|
||||
|
||||
Packages listed as **Core** are mandatory for EAF to work, whereas other packages are optional - install if you want to use corresponding EAF Application.
|
||||
|
||||
| Package | Dependent | Description |
|
||||
| :-------- | :------ | :------ |
|
||||
| python-pyqt5, python-pyqt5-sip | Core | Essential GUI library |
|
||||
| python-dbus | Core | DBus IPC to connect Python with Elisp |
|
||||
| python-pyqtwebengine | Core | Chromium based web rendering engine |
|
||||
| wmctrl | Core | Activate Emacs window input focus |
|
||||
| python-pymupdf | PDF Viewer | PDF rendering engine |
|
||||
| python-grip | Markdown Previewer | Markdown rendering server |
|
||||
| python-qrcode | File Sender, File Receiver, Airshare | Render QR code pointing to local files |
|
||||
| python-feedparser | RSS Reader | Parse RSS feeds |
|
||||
| python-pyinotify | Mermaid | Monitor *.mmd file change status |
|
||||
| python-markdown | Mermaid | Covert markdown format to mermaid html format |
|
||||
| nodejs | Terminal | Communicate between browser and local TTY |
|
||||
| aria2 | Browser | Download files from the web |
|
||||
| libreoffice | Doc Viewer | Convert doc file to pdf |
|
||||
| filebrowser-bin | File Browser | Share files between computer and smartphone |
|
||||
| qtconsole | Jupyter | Provide RichJupyterWidget |
|
||||
| java-openjdk | Markdown Previewer | Make mume.js can render PlantUML content |
|
||||
|
||||
## Launch EAF Applications
|
||||
| Application Name | Launch |
|
||||
@@ -145,62 +154,59 @@ Packages listed as **Core** are mandatory for EAF to work, whereas other package
|
||||
| File Sender | `M-x eaf-file-sender-qrcode` or `eaf-file-sender-qrcode-in-dired` |
|
||||
| File Browser | `M-x eaf-file-browser-qrcode` |
|
||||
| Airshare | `M-x eaf-open-airshare` |
|
||||
| RSS Reader | `M-x eaf-open-rss-reader` |
|
||||
| Mindmap | `M-x eaf-create-mindmap` or `M-x eaf-open-mindmap` |
|
||||
| MS Office Viewer | `M-x eaf-open-office` |
|
||||
| Mermaid | `M-x eaf-open` Mermaid file (*.mmd) |
|
||||
| Jupyter | `M-x eaf-open-jupyter` |
|
||||
| Demo | `M-x eaf-open-demo` to verify basic functionality |
|
||||
|
||||
- To open the file under the cursor in `dired` using appropriate EAF Application, use `eaf-open-this-from-dired` instead.
|
||||
- EAF Browser and PDF Viewer support Emacs built-in bookmark operation, with `M-x bookmark-set` (defaulted to `C-x r m`) and `M-x bookmark-bmenu-list` (defaulted to `C-x r l`).
|
||||
|
||||
```
|
||||
NOTE:
|
||||
EAF use DBus' session bus, it must run by a general user.
|
||||
Please don't use EAF when Emacs is started with sudo or root user, a root user can only access DBus's system bus.
|
||||
```
|
||||
|
||||
## Wiki
|
||||
|
||||
It is **highly** suggested to read the [Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki) first before using EAF.
|
||||
|
||||
Wiki consists of documentations on Keybinding, Customization, Design and TODOLIST. There also are some helpful tips to make EAF work with Docker, Helm, etc.
|
||||
Wiki consists of documentations on:
|
||||
* Keybindings
|
||||
* Customization
|
||||
* Design
|
||||
* TODOLIST
|
||||
|
||||
There also are some helpful tips to make EAF work with Docker, Helm, etc.
|
||||
|
||||
## FAQ
|
||||
|
||||
### How does EAF work?
|
||||
EAF implements three major functionalities:
|
||||
1. Integrate PyQt program window into Emacs frame using QWindow Reparent technology.
|
||||
2. Listen to EAF buffer's keyboard event flow and control the keyboard input of PyQt program via DBus IPC.
|
||||
2. Listen to EAF buffer's keyboard event flow and control the keyboard input of PyQt program via Python EPC.
|
||||
3. Create a window compositer to make a PyQt program window adapt Emacs's Window/Buffer design.
|
||||
|
||||
Learn more from the [Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki/Hacking)!
|
||||
|
||||
### EAF vs EXWM?
|
||||
1. EAF and EXWM share a common goal: enhance collaboration between the standard GNU Emacs with other GUI tools.
|
||||
2. EXWM is an X11 Window Manager, it manages and controls other software using a keyboard, but it cannot modify, customize and extend the behavior of other software. For example, it cannot modify the behavior when you press a key in Chrome or a PDF viewer.
|
||||
2. EXWM is an X11 Window Manager, it manages and controls other software using a keyboard, but it cannot modify, customize and extend the behavior of other software.
|
||||
3. EAF is *not* a Window Manager, it utilizes the windows managing capabilities of Emacs to display its applications.
|
||||
4. The intention of EAF is to provide a framework to write PyQt5 applications that extends the multimedia experience of Emacs. From the perspective of Emacs' buffer/mode design, EAF is not different from any other package, with the former uses Qt for drawing contents while the latter uses Emacs' built-in text libraries instead.
|
||||
5. Through EAF's design, one can use Elisp to control Python and vice versa, and even able to use Elisp to control JavaScript in EAF Browser. EAF enables Emacs to the world of **multi-language scripting**.
|
||||
|
||||
Both projects are similar in terms of interface, but they are two completely different projects with different goals in mind. Sometimes one may find EAF is more suitable than EXWM, sometimes it's the other way around. Please do not meaninglessly compare them.
|
||||
|
||||
### EAF is (currently) Linux only. Why?
|
||||
1. DBus is Linux-specific technology, it's difficult to support DBus in other operating systems.
|
||||
2. Qt5's QGraphicsScene technology does not work on MacOS.
|
||||
### EAF can't works on MacOS. Why?
|
||||
1. Qt5's QGraphicsScene technology does not work on MacOS.
|
||||
2. QWindow Reparent technology need use the original API of Mac platform for replacement.
|
||||
|
||||
If you've figure them out, PRs are always welcome!
|
||||
|
||||
### `[EAF] *eaf* aborted (core dumped)` error
|
||||
Please check the `*eaf*` buffer, something is wrong on the Python side. Usually due to Python dependencies are not installed correctly.
|
||||
### EAF js-video-player can't play some video on Windows. Why?
|
||||
`js-video-player` requires that qtwebengine built against ffmpeg to support proprietary codecs like `h264/aac`.
|
||||
|
||||
If you're sure Python dependences are installed correctly, please create an issue with the `*eaf*` buffer content, it contains many clues that can help us locate the problem faster.
|
||||
### Why doesn't EAF receive input events on WM?
|
||||
EAF confirms that the desktop environment or window manager you can work includes: KDE, GNOME2, GNOME3, Mate, Xfce, LXDE, I3, QTILE, Xpra.
|
||||
|
||||
### What is Github Personal Access Tokens?
|
||||
If you use EAF Markdown Previewer, to get consistent previewing, you need to access [Github Personal access token site](https://github.com/settings/tokens/new?scopes=), fill something in "Token description" and click button "Generate token" to get your personal token. Then set the token:
|
||||
We suspect there are some issues with how all the Window Managers implement their x11 protocols.
|
||||
|
||||
```Elisp
|
||||
(setq eaf-grip-token "yourtokencode")
|
||||
```
|
||||
|
||||
Although Markdown Previewer works for the first few times by entering empty string when prompted, eventually it stops working and gives "GitHub Rate Limit Reached" error.
|
||||
One workaround is to name of command `wmctrl -m` to the elisp list `eaf-wm-focus-fix-wms`. Fill an issue if it still doesn't work.
|
||||
|
||||
### Proxy
|
||||
If you need to use proxy to access internet, one can configure the proxy settings.
|
||||
@@ -227,11 +233,13 @@ If we missed your package, please make a PR to add it to the list.
|
||||
|
||||
## Report bug
|
||||
|
||||
For any installation and configuration assistance, please read the [Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki) first!
|
||||
### For any installation and configuration assistance, please read the [Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki) first!
|
||||
|
||||
If you encounter any problem with EAF, please use command `emacs -q` with a minimal setup that only contains EAF and verify the bug is reproducible. If `emacs -q` works fine, probably something is wrong with your Emacs config.
|
||||
If you encounter a problem with EAF, and it occured after pulling the latest commit, please check the [Discussions](https://github.com/manateelazycat/emacs-application-framework/discussions/527) page first.
|
||||
|
||||
If the problem persists, please [report bug here](https://github.com/manateelazycat/emacs-application-framework/issues/new).
|
||||
For any other problems, please use `emacs -q` and load a minimal setup with only EAF to verify that the bug is reproducible. If `emacs -q` works fine, probably something is wrong with your Emacs config.
|
||||
|
||||
If the problem persists, please report it [here](https://github.com/manateelazycat/emacs-application-framework/issues/new) with `*eaf*` buffer content, it contains many clues that can help us locate the problem faster.
|
||||
|
||||
If you got segfault error, please use the following way to collect crash information:
|
||||
1. Install gdb and turn on option `eaf-enable-debug`
|
||||
|
||||
@@ -6,7 +6,7 @@ EAF 是一个全新的图形应用框架,通过扩展Emacs的多媒体能力
|
||||
## EAF 应用展示
|
||||
EAF是一个可编程扩展的框架,你可以开发自己的Qt5应用并集成在Emacs中。
|
||||
|
||||
| 浏览器 | Markdown预览程序 |
|
||||
| 浏览器 | Markdown预览(支持Mermaid和PlantUML) |
|
||||
| :--------: | :----: |
|
||||
| <img src="./screenshot/browser.gif" width="400"> | <img src="./screenshot/markdown_previewer.gif" width="400"> |
|
||||
|
||||
@@ -31,7 +31,7 @@ EAF是一个可编程扩展的框架,你可以开发自己的Qt5应用并集
|
||||
| <img src="./screenshot/air_share.png" width="400"> | <img src="./screenshot/org_previewer.gif" width="400"> |
|
||||
| | |
|
||||
|
||||
| 终端模拟器 | RSS阅读器 |
|
||||
| 终端模拟器 | RSS阅读器 (集成Elfeed) |
|
||||
| :--------: | :------: |
|
||||
| <img src="./screenshot/terminal.gif" width="400"> | <img src="./screenshot/rss_reader.gif" width="400"> |
|
||||
| | |
|
||||
@@ -41,92 +41,102 @@ EAF是一个可编程扩展的框架,你可以开发自己的Qt5应用并集
|
||||
| <img src="./screenshot/aria2.gif" width="400"> | <img src="./screenshot/mindmap.gif" width="400"> |
|
||||
| | |
|
||||
|
||||
| 流程图 | 笔记管理系统 |
|
||||
| Jupyter | 笔记管理系统 |
|
||||
| :--------: | :--------: |
|
||||
| <img src="./screenshot/mermaid.gif" width="400"> | <img src="./screenshot/eaf-interleave.gif" width="400"> |
|
||||
| <img src="./screenshot/jupyter.png" width="400"> | <img src="./screenshot/eaf-interleave.gif" width="400"> |
|
||||
| | |
|
||||
|
||||
## EmacsConf2020 - Extend Emacs to Modern GUI Applications with EAF(暂无中文字幕)
|
||||
- 由[MatthewZMD](https://github.com/MatthewZMD)在EmacsConf2020的演讲和demo。
|
||||
- 官网(内附Q&A): https://emacsconf.org/2020/talks/34/
|
||||
- Youtube链接:
|
||||
|
||||
[](https://www.youtube.com/watch?v=HK_f8KTuR0s)
|
||||
|
||||
## 安装
|
||||
1. 安装EAF依赖,对于每个依赖的解释可以在[依赖列表](#依赖列表)找到。
|
||||
|
||||
以下这行是针对*Archlinux*,同样的包的安装方式在别的发行版略有不同,请善用搜索引擎:
|
||||
|
||||
1. 下载EAF:
|
||||
```Bash
|
||||
yay -S python-pyqt5 python-pyqt5-sip python-pyqtwebengine python-qrcode python-feedparser python-dbus python-pyinotify python-markdown nodejs aria2 libreoffice python-pymupdf python-grip filebrowser-bin
|
||||
git clone --depth=1 -b master https://github.com/manateelazycat/emacs-application-framework.git ~/.emacs.d/site-lisp/emacs-application-framework/
|
||||
```
|
||||
|
||||
2. 使用 ```git clone``` 下载这个仓库.
|
||||
|
||||
```Bash
|
||||
git clone https://github.com/manateelazycat/emacs-application-framework.git --depth=1
|
||||
你也可以通过[Quelpa](https://github.com/quelpa/quelpa)来下载
|
||||
```Emacs-lisp
|
||||
(quelpa '(eaf (:fetcher github
|
||||
:repo "manateelazycat/emacs-application-framework"
|
||||
:files ("*"))))
|
||||
```
|
||||
|
||||
3. 把EAF加入Emacs的 ```load-path```,然后在 `init.el` 中写入:
|
||||
2. 通过`M-x install-eaf-dependencies`安装EAF依赖,
|
||||
|
||||
如果你更喜欢手动执行安装脚本,
|
||||
|
||||
- GNU/Linux用户:
|
||||
|
||||
```Bash
|
||||
cd emacs-application-framework
|
||||
chmod +x ./install-eaf.sh
|
||||
./install-eaf.sh
|
||||
```
|
||||
|
||||
- Windows用户:
|
||||
|
||||
```shell
|
||||
>>>>>>> Update README and eaf-install-dependencies (need Windows testing)
|
||||
cd emacs-application-framework
|
||||
node ./install-eaf-win32.js
|
||||
```
|
||||
|
||||
脚本里安装的每一个依赖的解释可以在[依赖列表](#依赖列表)找到。
|
||||
|
||||
3. 安装Elisp依赖包:
|
||||
- [emacs-ctable](https://github.com/kiwanami/emacs-ctable)
|
||||
- [emacs-deferred](https://github.com/kiwanami/emacs-deferred)
|
||||
- [emacs-epc](https://github.com/kiwanami/emacs-epc)
|
||||
- [s.el](https://github.com/magnars/s.el)
|
||||
|
||||
4. 从这里开始,你可以把EAF加入Emacs的 ```load-path```,然后在 `init.el` 中写入:
|
||||
|
||||
```Elisp
|
||||
(add-to-list 'load-path "~/.emacs.d/site-lisp/emacs-application-framework/")
|
||||
(require 'eaf)
|
||||
```
|
||||
|
||||
如果你使用[use-package](https://github.com/jwiegley/use-package),下面有一个简单的配置文件供你参考:
|
||||
或者,如果你使用[use-package](https://github.com/jwiegley/use-package),下面有一个简单的配置文件供你参考:
|
||||
|
||||
```Elisp
|
||||
(use-package eaf
|
||||
:load-path "~/.emacs.d/site-lisp/emacs-application-framework" ; Set to "/usr/share/emacs/site-lisp/eaf" if installed from AUR
|
||||
:init
|
||||
(use-package epc :defer t)
|
||||
(use-package ctable :defer t)
|
||||
(use-package deferred :defer t)
|
||||
(use-package s :defer t :ensure t)
|
||||
:custom
|
||||
(eaf-find-alternate-file-in-dired t)
|
||||
(eaf-browser-continue-where-left-off t)
|
||||
:config
|
||||
(eaf-setq eaf-browser-enable-adblocker "true")
|
||||
(eaf-bind-key scroll_up "C-n" eaf-pdf-viewer-keybinding)
|
||||
(eaf-bind-key scroll_down "C-p" eaf-pdf-viewer-keybinding)
|
||||
(eaf-bind-key take_photo "p" eaf-camera-keybinding))
|
||||
(eaf-bind-key take_photo "p" eaf-camera-keybinding)
|
||||
(eaf-bind-key nil "M-q" eaf-browser-keybinding)) ;; unbind, see more in the Wiki
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
如果你使用[Chemacs](https://github.com/plexus/chemacs), 下面是一份 `init.el`的配置示例:
|
||||
|
||||
```Elisp
|
||||
;; An example of init.el
|
||||
|
||||
(defun add-subdirs-to-load-path (dir)
|
||||
"Recursive add directories to `load-path'."
|
||||
(let ((default-directory (file-name-as-directory dir)))
|
||||
(add-to-list 'load-path dir)
|
||||
(normal-top-level-add-subdirs-to-load-path)))
|
||||
(add-subdirs-to-load-path "~/.emacs.d/")
|
||||
|
||||
(require 'eaf)
|
||||
```
|
||||
|
||||
在安装EAF时,你仅需要修改此文件中调用函数`add-subdirs-to-load-path`的参数值,将其更改为你的EAF安装位置的绝对路径。 配置示例中的EAF是安装在`~/.emacs.d/`.
|
||||
|
||||
在EAF安装完成后,假设你将它安装到了`~/eaf`,你电脑中只有存放在`~/.emacs.d`的Emacs配置文件和安装的EAF,并且你电脑中安装了Chemacs,此时`.emacs-profiles.el`应该这样配置:
|
||||
|
||||
```Elisp
|
||||
(("default" . ((user-emacs-directory . "~/.emacs.d")))
|
||||
("EAF" . ((user-emacs-directory . "~/eaf"))))
|
||||
```
|
||||
|
||||
当你想使用Chemacs打开EAF,只需在终端中执行`emacs --with-profile EAF`。
|
||||
|
||||
### 依赖列表
|
||||
**核心** 分类代表必备依赖,这些包必须安装好EAF才能工作。其余依赖都可选,若想其使用对应的应用时,你才需要安装这些依赖。当然我们推荐先把所有依赖都安装好,等到真正使用的时候就不用再次折腾。
|
||||
|
||||
| 包名 | 依赖 | 解释 |
|
||||
| :-------- | :------ | :------ |
|
||||
| python-pyqt5, python-pyqt5-sip | 核心 | GUI图形库 |
|
||||
| python-dbus | 核心 | DBus库,用于在Emacs和Python进程间通讯 |
|
||||
| python-pyqtwebengine | 核心 | 基于Chromium的浏览器引擎 |
|
||||
| wmctrl | 核心 | 激活Emacs窗口输入焦点 |
|
||||
| python-pymupdf | PDF阅读器 | 解析PDF文件 |
|
||||
| python-grip | Markdown预览 | 建立Markdown文件的HTML服务 |
|
||||
| python-qrcode | 文件上传,文件下载,文字传输 | 根据文件信息生成二维码 |
|
||||
| python-feedparser | RSS阅读器 | 解析RSS/Atom信息 |
|
||||
| python-pyinotify | 流程图 | 监听 mmd 格式文件的变动 |
|
||||
| python-markdown | 流程图 | 转换 mmd 格式为 mermaid 识别的 html 格式 |
|
||||
| aria2 | 浏览器 | 下载网络文件 |
|
||||
| nodejs | 终端模拟器 | 通过浏览器与本地TTY交互 |
|
||||
| libreoffice | 办公文档阅读器 | 转换doc文件为pdf格式 |
|
||||
| filebrowser-bin | 文件浏览器 | 在电脑和手机之间快速共享文件 |
|
||||
| qtconsole | jupyter | 提供RichJupyterWidget |
|
||||
| java-openjdk | Markdown 预览 | 正常渲染Markdown文档中的PlantUML代码 |
|
||||
|
||||
## EAF应用启动命令
|
||||
| 应用名称 | 启动命令 |
|
||||
@@ -144,36 +154,37 @@ git clone https://github.com/manateelazycat/emacs-application-framework.git --de
|
||||
| 二维码下载文件 | `M-x eaf-file-sender-qrcode` or `eaf-file-sender-qrcode-in-dired` |
|
||||
| 二维码在线浏览器 | `M-x eaf-file-browser-qrcode` |
|
||||
| 无线分享 | `M-x eaf-open-airshare` 输入要分享给手机的字符串 |
|
||||
| RSS新闻阅读器 | `M-x eaf-open-rss-reader` |
|
||||
| 思维导图 | `M-x eaf-create-mindmap` or `M-x eaf-open-mindmap` |
|
||||
| 微软Office阅读器 | `M-x eaf-open-office` |
|
||||
| 流程图 | `M-x eaf-open` 输入 mmd 格式文件 |
|
||||
| jupyter | `M-x eaf-open-jupyter` |
|
||||
| 演示程序 | `M-x eaf-open-demo` |
|
||||
|
||||
- 在`dired`文件管理器中,建议绑定按键到命令 `eaf-open-this-from-dired` ,它会自动用合适的EAF应用来打开文件。
|
||||
- EAF浏览器以及PDF浏览器支持Emacs内置书签操作,通过使用`M-x bookmark-set`(默认`C-x r m`)以及`M-x bookmark-bmenu-list`(默认`C-x r l`)。
|
||||
|
||||
```
|
||||
注意:
|
||||
EAF使用DBus的普通权限总线 (session bus),请不要用 sudo 来启动EAF,root用户只能访问系统权限总线 (system bus)
|
||||
```
|
||||
|
||||
## Wiki
|
||||
强烈建议使用EAF之前浏览一遍[Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki)。
|
||||
|
||||
Wiki包括架构设计,按键绑定,自定义选项和任务列表等文档。你还会在Wiki发现很多有用的技巧,比如Docker,Helm等,
|
||||
Wiki囊括了各种你想了解的EAF相关文档,包括了:
|
||||
1. 按键绑定
|
||||
2. 自定义选项
|
||||
3. 架构设计
|
||||
4. 任务列表
|
||||
|
||||
你还会在Wiki发现很多有用的技巧,如Docker,Helm等,
|
||||
|
||||
## 常用问题
|
||||
|
||||
### EAF是怎么工作的?
|
||||
EAF主要实现这几个功能:
|
||||
1. 利用QWindow的Reparent技术来实现PyQt应用进程的窗口粘贴到Emacs对应的Buffer区域
|
||||
2. 通过DBus IPC来实现Emacs进程和Python进程的控制指令和跨进程消息通讯
|
||||
2. 通过Python EPC来实现Emacs进程和Python进程的控制指令和跨进程消息通讯
|
||||
3. 通过Qt5的QGraphicsScene来实现镜像窗口,以对应Emacs的Buffer/Window模型
|
||||
|
||||
若想了解更多EAF设计背景,请看[Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki/Hacking)
|
||||
|
||||
### EAF vs EXWM?
|
||||
1. EAF和EXWM的共同点都是:“提升Emacs和别的程序的协作效率“
|
||||
2. EXWM是一个X11窗口管理器,通过X11协议来控制Emacs和其他程序,但是EXWM只是管理其他程序,但是它并不会修改别的程序。比如它没法修改Chrome,PDF阅读器等GUI程序内在的行为
|
||||
2. EXWM是一个X11窗口管理器,通过X11协议来控制Emacs和其他程序,但是EXWM只是管理其他程序,但是它并不会修改应用程序的内在行为。
|
||||
3. EAF不是一个窗口管理器,EAF只是依赖Emacs自身的窗口管理功能显示自己
|
||||
4. EAF的目标是通过PyQt创造新的应用来扩展Emacs的多媒体能力。从Emacs本身的Buffer/Mode设计上看,它和你平常用的 `xx-mode` 插件没有啥区别,只是它用Qt来绘制内容,而不是Emacs自身的文本库来绘制内容
|
||||
5. EAF通过造轮子的方式,把大多数程序员常用的应用写出来以后,达到Live in Emacs的最终目标
|
||||
@@ -181,23 +192,19 @@ EAF主要实现这几个功能:
|
||||
|
||||
或许EAF和EXWM看起来有点相似,但它们在设计和理念上是两个完全不同的项目。所以请大家多多学习X11和Qt的区别,理解技术的本质,避免无意义的比较和争论。
|
||||
|
||||
### 为什么EAF只能在Linux下工作?
|
||||
1. DBus是Linux下专用的进程间通讯技术,其他操作系统可能无法支持DBus
|
||||
2. Qt5的QGraphicsScene技术无法在MacOS下正常工作,也就无法实现Qt5应用的镜像窗口以支持Emacs的Buffer/Window模型
|
||||
### 为什么EAF无法在MacOS下工作?
|
||||
1. Qt5的QGraphicsScene技术无法在MacOS下正常工作,也就无法实现Qt5应用的镜像窗口以支持Emacs的Buffer/Window模型
|
||||
2. QWindow Reparent技术无法在MacOS下正常工作,也就无法实现Qt应用进程的窗口粘贴到Emacs对应的Buffer区域
|
||||
|
||||
欢迎操作系统级别黑客移植EAF,目前为止,我知道的主要的迁移障碍就只有两个:DBus,QGraphicsScene
|
||||
### 为什么EAF的js-video-player在Windows下无法播放视频文件?
|
||||
`js-video-player`需要qtwebengine编译时链接到ffmpeg,才能支持额外的编码如`h264/aac`.
|
||||
|
||||
### `[EAF] *eaf* aborted (core dumped)` 奔溃了怎么办?
|
||||
请检查 `*eaf*` 这个窗口的内容。通常是EAF的Python依赖没有安装好,如果你确定依赖没有问题,请附带 `*eaf*` 窗口的内容给我们提交issue,那里面有很多线索可以帮助我们排查问题。
|
||||
### 为什么通过窗口管理器使用EAF无法接收输入信息?
|
||||
EAF确认可以工作的桌面环境或者窗口管理器包括:KDE、Gnome2、Gnome3、Mate、XFce、LXDE、i3、QTile、Xpra.
|
||||
|
||||
### Github 个人访问标记干什么用的?
|
||||
Markdown预览程序依赖grip,你需要访问[Github Personal access token](https://github.com/settings/tokens/new?scopes=)去获取你个人的标记,然后通过下面的命令设置标记后,grip才能正常的工作:
|
||||
我们认为不同的窗口管理器对于X11协议的支持不够完善才导致这样的问题。
|
||||
|
||||
```Elisp
|
||||
(setq eaf-grip-token "yourtokencode")
|
||||
```
|
||||
|
||||
尽管不设置访问标记一开始也能成功使用,但Github过段时间会弹出 "GitHub Rate Limit Reached" 的错误。
|
||||
现在的解决方案是将命令`wmctrl -m`中Name的值加入`eaf-wm-focus-fix-wms`,如果还有问题,请在Github提出issue。
|
||||
|
||||
### 代理
|
||||
可以通过下面设置来通过代理访问互联网:
|
||||
@@ -224,9 +231,11 @@ Markdown预览程序依赖grip,你需要访问[Github Personal access token](h
|
||||
|
||||
### 反馈安装和配置问题之前,请一定先阅读[Wiki](https://github.com/manateelazycat/emacs-application-framework/wiki)!!!
|
||||
|
||||
如果你遇到任何问题,请先用命令 `emacs -q` 并只添加EAF配置,做一个对比测试,如果 `emacs -q` 的时候可以工作,请检查你个人的配置文件。
|
||||
如果你使用中遇到任何问题,并且问题是`git pull`后出现的,请先阅读[Discussions](https://github.com/manateelazycat/emacs-application-framework/discussions/527)页面。
|
||||
|
||||
如果```emacs -q```环境下问题依旧,请到[这里](https://github.com/manateelazycat/emacs-application-framework/issues/new)反馈。
|
||||
关于其他问题,请用命令 `emacs -q` 并只添加EAF配置做一个对比测试,如果 `emacs -q` 可以正常工作,请检查你个人的配置文件。
|
||||
|
||||
如果`emacs -q`环境下问题依旧,请到[这里](https://github.com/manateelazycat/emacs-application-framework/issues/new)反馈, 并附带 `*eaf*` 窗口的内容给我们提交issue,那里面有很多线索可以帮助我们排查问题。。
|
||||
|
||||
如果你遇到崩溃的问题, 请用下面的方式来收集崩溃信息:
|
||||
1. 先安装gdb并打开选项 `eaf-enable-debug`
|
||||
|
||||
@@ -49,12 +49,18 @@ class AppBuffer(BrowserBuffer):
|
||||
self.buffer_widget.translate_selected_text.connect(self.translate_text)
|
||||
|
||||
self.buffer_widget.open_url_in_new_tab.connect(self.open_url_in_new_tab)
|
||||
self.buffer_widget.duplicate_page_in_new_tab.connect(self.duplicate_page_in_new_tab)
|
||||
self.buffer_widget.open_url_in_background_tab.connect(self.open_url_in_background_tab)
|
||||
|
||||
# Reset to default zoom when page init or url changed.
|
||||
self.reset_default_zoom()
|
||||
self.buffer_widget.urlChanged.connect(self.set_adblocker)
|
||||
self.buffer_widget.urlChanged.connect(self.caret_exit)
|
||||
|
||||
# Record url when url changed.
|
||||
self.buffer_widget.urlChanged.connect(self.update_url)
|
||||
|
||||
def update_url(self, url):
|
||||
self.reset_default_zoom()
|
||||
self.url = self.buffer_widget.url().toString()
|
||||
|
||||
def set_adblocker(self, url):
|
||||
if self.emacs_var_dict["eaf-browser-enable-adblocker"] == "true" and not self.page_closed:
|
||||
self.buffer_widget.load_adblocker()
|
||||
|
||||
@@ -24,7 +24,7 @@ from PyQt5.QtGui import QBrush
|
||||
from PyQt5.QtGui import QColor
|
||||
from PyQt5.QtMultimedia import QCameraInfo, QCamera, QCameraImageCapture
|
||||
from PyQt5.QtMultimediaWidgets import QGraphicsVideoItem
|
||||
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView
|
||||
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QFrame
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout
|
||||
from core.buffer import Buffer
|
||||
from pathlib import Path
|
||||
@@ -34,6 +34,9 @@ import os
|
||||
class AppBuffer(Buffer):
|
||||
def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, module_path):
|
||||
Buffer.__init__(self, buffer_id, url, arguments, emacs_var_dict, module_path, True)
|
||||
|
||||
self.background_color = QColor(0, 0, 0)
|
||||
|
||||
self.add_widget(CameraWidget(QColor(0, 0, 0, 255)))
|
||||
|
||||
def all_views_hide(self):
|
||||
@@ -46,9 +49,12 @@ class AppBuffer(Buffer):
|
||||
|
||||
def take_photo(self):
|
||||
if os.path.exists(os.path.expanduser(self.emacs_var_dict["eaf-camera-save-path"])):
|
||||
self.buffer_widget.take_photo(self.emacs_var_dict["eaf-camera-save-path"])
|
||||
location = self.emacs_var_dict["eaf-camera-save-path"]
|
||||
else:
|
||||
self.buffer_widget.take_photo("~/Downloads")
|
||||
location = "~/Downloads"
|
||||
result = self.buffer_widget.take_photo(location)
|
||||
if result:
|
||||
self.message_to_emacs.emit("Captured Photo at " + location)
|
||||
|
||||
def destroy_buffer(self):
|
||||
self.buffer_widget.stop_camera()
|
||||
@@ -65,13 +71,13 @@ class CameraWidget(QWidget):
|
||||
self.graphics_view = QGraphicsView(self.scene)
|
||||
self.graphics_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.graphics_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.graphics_view.setFrameStyle(0)
|
||||
self.graphics_view.setStyleSheet("QGraphicsView {background: transparent; border: 3px; outline: none;}")
|
||||
self.graphics_view.setFrameStyle(QFrame.NoFrame)
|
||||
self.graphics_view.scale(-1, 1) # this make live video from camero mirror.
|
||||
self.video_item = QGraphicsVideoItem()
|
||||
self.scene.addItem(self.video_item)
|
||||
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.layout.setSpacing(0)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.layout.addWidget(self.graphics_view)
|
||||
|
||||
@@ -93,9 +99,8 @@ class CameraWidget(QWidget):
|
||||
def take_photo(self, camera_save_path):
|
||||
image_capture = QCameraImageCapture(self.camera)
|
||||
save_path = str(Path(os.path.expanduser(camera_save_path)))
|
||||
photo_path = os.path.join(save_path, "EAF_Camera_Photo_" + time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime(int(time.time()))))
|
||||
image_capture.capture(photo_path)
|
||||
self.message_to_emacs.emit("Captured Photo at " + photo_path)
|
||||
photo_path = os.path.join(save_path, "EAF_Camera_Photo_" + time.strftime("%Y%m%d_%H%M%S", time.localtime(int(time.time()))))
|
||||
return image_capture.capture(photo_path)
|
||||
|
||||
def stop_camera(self):
|
||||
self.camera.stop()
|
||||
|
||||
@@ -28,6 +28,7 @@ import subprocess
|
||||
import os
|
||||
import qrcode
|
||||
import signal
|
||||
import tempfile
|
||||
|
||||
from core.buffer import Buffer
|
||||
|
||||
@@ -76,7 +77,7 @@ class FileUploaderWidget(QWidget):
|
||||
self.file_name_font.setPointSize(24)
|
||||
|
||||
self.file_name_label = QLabel(self)
|
||||
self.file_name_label.setText("Your file will be share at\n{0}".format(url))
|
||||
self.file_name_label.setText("Your smartphone file will be shared at\n{0}".format(url))
|
||||
self.file_name_label.setFont(self.file_name_font)
|
||||
self.file_name_label.setAlignment(Qt.AlignCenter)
|
||||
self.file_name_label.setStyleSheet("color: #eee")
|
||||
@@ -86,7 +87,7 @@ class FileUploaderWidget(QWidget):
|
||||
self.notify_font = QFont()
|
||||
self.notify_font.setPointSize(12)
|
||||
self.notify_label = QLabel(self)
|
||||
self.notify_label.setText("Scan QR code above to upload a file from your smartphone.\nMake sure the smartphone is connected to the same WiFi network as this computer.")
|
||||
self.notify_label.setText("Scan the QR code above to upload a file from your smartphone.\nMake sure the smartphone is connected to the same WiFi network as this computer.")
|
||||
self.notify_label.setFont(self.notify_font)
|
||||
self.notify_label.setAlignment(Qt.AlignCenter)
|
||||
self.notify_label.setStyleSheet("color: #eee")
|
||||
@@ -107,8 +108,10 @@ class FileUploaderWidget(QWidget):
|
||||
|
||||
self.qrcode_label.setPixmap(qrcode.make(self.address, image_factory=Image).pixmap())
|
||||
|
||||
tmp_db_file = os.path.join(tempfile.gettempdir(), "filebrowser.db")
|
||||
self.background_process = subprocess.Popen(
|
||||
"cd {0} && filebrowser --noauth -d /tmp/filebrowser.db --address {1} -p {2}".format(url, self.local_ip, self.port),
|
||||
"filebrowser --noauth -d {0} --address {1} -p {2}".format(tmp_db_file, self.local_ip, self.port),
|
||||
cwd=url,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=True)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtGui import QColor
|
||||
from core.browser import BrowserBuffer
|
||||
from core.utils import PostGui
|
||||
from core.utils import interactive
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
@@ -30,16 +30,20 @@ class AppBuffer(BrowserBuffer):
|
||||
def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, module_path):
|
||||
BrowserBuffer.__init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, module_path, False)
|
||||
|
||||
self.index_file = os.path.join(os.path.dirname(__file__), "index.html")
|
||||
self.load_image(url)
|
||||
|
||||
def load_image(self, url):
|
||||
self.url = url
|
||||
self.parent_dir = os.path.abspath(os.path.join(url, os.pardir))
|
||||
self.image_name = os.path.basename(url)
|
||||
self.buffer_widget.setUrl(QUrl("file://" + self.url))
|
||||
|
||||
with open(self.index_file, "r") as f:
|
||||
html = f.read().replace("%1", os.path.join(os.path.dirname(__file__))).replace("%2", os.path.join("file://", url))
|
||||
self.buffer_widget.setHtml(html, QUrl("file://"))
|
||||
|
||||
def is_image_file(self, f):
|
||||
return Path(f).suffix.lower() in ["jpg", "jpeg", "png", "bmp", "gif", "svg", "webp"]
|
||||
return Path(f).suffix[1:].lower() in ["jpg", "jpeg", "png", "bmp", "gif", "svg", "webp"]
|
||||
|
||||
def get_same_dir_images(self):
|
||||
files = [f for f in os.listdir(self.parent_dir) if os.path.isfile(os.path.join(self.parent_dir, f))]
|
||||
@@ -54,7 +58,9 @@ class AppBuffer(BrowserBuffer):
|
||||
else:
|
||||
image_index += 1
|
||||
|
||||
self.load_image(os.path.join(self.parent_dir, images[image_index]))
|
||||
self.image_name = images[image_index]
|
||||
self.load_image(os.path.join(self.parent_dir, self.image_name))
|
||||
self.change_title(self.image_name)
|
||||
|
||||
def load_prev_image(self):
|
||||
images = self.get_same_dir_images()
|
||||
@@ -65,4 +71,39 @@ class AppBuffer(BrowserBuffer):
|
||||
else:
|
||||
image_index -= 1
|
||||
|
||||
self.load_image(os.path.join(self.parent_dir, images[image_index]))
|
||||
self.image_name = images[image_index]
|
||||
self.load_image(os.path.join(self.parent_dir, self.image_name))
|
||||
self.change_title(self.image_name)
|
||||
|
||||
@interactive
|
||||
def rotate_left(self):
|
||||
self.buffer_widget.eval_js("rotate_left();")
|
||||
|
||||
@interactive
|
||||
def rotate_right(self):
|
||||
self.buffer_widget.eval_js("rotate_right();")
|
||||
|
||||
@interactive
|
||||
def zoom_out(self):
|
||||
self.buffer_widget.eval_js("zoom_out();")
|
||||
|
||||
@interactive
|
||||
def zoom_in(self):
|
||||
self.buffer_widget.eval_js("zoom_in();")
|
||||
|
||||
@interactive
|
||||
def zoom_reset(self):
|
||||
self.buffer_widget.eval_js("zoom_reset();")
|
||||
|
||||
@interactive
|
||||
def zoom_toggle(self):
|
||||
self.buffer_widget.eval_js("zoom_toggle();")
|
||||
|
||||
@interactive
|
||||
def flip_horizontal(self):
|
||||
self.buffer_widget.eval_js("flip_horizontal();")
|
||||
|
||||
@interactive
|
||||
def flip_vertical(self):
|
||||
self.buffer_widget.eval_js("flip_vertical();")
|
||||
|
||||
|
||||
88
lisp/emacs-application-framework/app/image-viewer/index.html
Normal file
88
lisp/emacs-application-framework/app/image-viewer/index.html
Normal file
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<script type="text/javascript" src="%1/node_modules/viewerjs/dist/viewer.js"></script>
|
||||
<link rel="stylesheet" href="%1/node_modules/viewerjs/dist/viewer.css" />
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: #7F7F7F;
|
||||
}
|
||||
|
||||
img {
|
||||
display: none;
|
||||
background: #7F7F7F;
|
||||
}
|
||||
|
||||
.viewer-fullscreen, .viewer-fullscreen-exit {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<img id="image" src="%2">
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
// View an image
|
||||
const viewer = new Viewer(document.getElementById('image'), {
|
||||
inline: true,
|
||||
navbar: false,
|
||||
transition: false,
|
||||
toolbar: {
|
||||
zoomIn: 4,
|
||||
zoomOut: 4,
|
||||
oneToOne: 4,
|
||||
reset: 4,
|
||||
rotateLeft: 4,
|
||||
rotateRight: 4,
|
||||
flipHorizontal: 4,
|
||||
flipVertical: 4,
|
||||
},
|
||||
view() {
|
||||
viewer.full();
|
||||
},
|
||||
});
|
||||
|
||||
function rotate_left() {
|
||||
viewer.rotate(-90);
|
||||
}
|
||||
|
||||
function rotate_right() {
|
||||
viewer.rotate(90);
|
||||
}
|
||||
|
||||
function zoom_out() {
|
||||
viewer.zoom(-0.1, true);
|
||||
}
|
||||
|
||||
function zoom_in() {
|
||||
viewer.zoom(0.1, true);
|
||||
}
|
||||
|
||||
function zoom_reset() {
|
||||
viewer.reset();
|
||||
}
|
||||
|
||||
function zoom_toggle() {
|
||||
viewer.toggle();
|
||||
}
|
||||
|
||||
function flip_horizontal() {
|
||||
viewer.scaleX(-viewer.imageData.scaleX || -1);
|
||||
}
|
||||
|
||||
function flip_vertical() {
|
||||
viewer.scaleY(-viewer.imageData.scaleY || -1);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
13
lisp/emacs-application-framework/app/image-viewer/package-lock.json
generated
Normal file
13
lisp/emacs-application-framework/app/image-viewer/package-lock.json
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "eaf-image-viewer",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"viewerjs": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npm.taobao.org/viewerjs/download/viewerjs-1.9.0.tgz",
|
||||
"integrity": "sha1-bfr1REDDsvdpG4Vma6bSdwjtlZI="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "eaf-image-viewer",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/manateelazycat/emacs-application-framework.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"bugs": {
|
||||
"url": "https://github.com/manateelazycat/emacs-application-framework/issues"
|
||||
},
|
||||
"homepage": "https://github.com/manateelazycat/emacs-application-framework#readme",
|
||||
"dependencies": {
|
||||
"viewerjs": "^1.9.0"
|
||||
}
|
||||
}
|
||||
@@ -193,7 +193,7 @@ buffer."
|
||||
))
|
||||
|
||||
(defun eaf-interleave-add-file-url ()
|
||||
"Add new url on note if property is none. else modify current url"
|
||||
"Add a new url on note if the property is none, else modify current url."
|
||||
(interactive)
|
||||
(let ((url (read-file-name "Please specify path: " nil nil t)))
|
||||
(org-entry-put (point) eaf-interleave--url-prop url)))
|
||||
@@ -212,7 +212,7 @@ This show the previous notes and synchronizes the PDF to the right page number."
|
||||
(eaf-interleave-sync-current-note))
|
||||
|
||||
(defun eaf-interleave-open-notes-file ()
|
||||
"Find current EAF url corresponding note files if exists"
|
||||
"Find current EAF url corresponding note files if it exists."
|
||||
(interactive)
|
||||
(if (derived-mode-p 'eaf-mode)
|
||||
(cond ((equal eaf--buffer-app-name "pdf-viewer")
|
||||
@@ -463,12 +463,12 @@ Consider a headline with property PROPERTY as parent headline."
|
||||
(defun eaf-interleave--pdf-viewer-current-page (url)
|
||||
"get current page index."
|
||||
(let ((id (buffer-local-value 'eaf--buffer-id (eaf-interleave--find-buffer url))))
|
||||
(string-to-number (eaf-call "call_function" id "current_page"))))
|
||||
(string-to-number (eaf-call-sync "call_function" id "current_page"))))
|
||||
|
||||
(defun eaf-interleave--pdf-viewer-goto-page (url page)
|
||||
"goto page"
|
||||
(let ((id (buffer-local-value 'eaf--buffer-id (eaf-interleave--find-buffer url))))
|
||||
(eaf-call "handle_input_message" id "jump_page" page)))
|
||||
(eaf-call-async "handle_input_response" id "jump_page" page)))
|
||||
|
||||
(defun eaf-interleave--ensure-buffer-window (buffer)
|
||||
"If BUFFER don't display, will use other window display"
|
||||
|
||||
@@ -36,8 +36,8 @@ class AppBuffer(BrowserBuffer):
|
||||
BrowserBuffer.__init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, module_path, False)
|
||||
|
||||
self.url = url
|
||||
index_file = "file://" + (os.path.join(os.path.dirname(__file__), "index.html"))
|
||||
self.buffer_widget.setUrl(QUrl(index_file))
|
||||
index_file = os.path.join(os.path.dirname(__file__), "index.html")
|
||||
self.buffer_widget.setUrl(QUrl.fromLocalFile(index_file))
|
||||
|
||||
for method_name in ["toggle_play", "forward", "backward", "restart", "increase_volume", "decrease_volume"]:
|
||||
self.build_js_method(method_name)
|
||||
@@ -55,7 +55,7 @@ class AppBuffer(BrowserBuffer):
|
||||
self.buffer_widget.eval_js("set_current_time('{}');".format(self.position))
|
||||
|
||||
def play_video(self):
|
||||
self.buffer_widget.eval_js("play('{}');".format("file://" + self.url))
|
||||
self.buffer_widget.eval_js("play(\"{}\");".format(QUrl.fromLocalFile(self.url).toString()))
|
||||
|
||||
def build_js_method(self, method_name):
|
||||
def _do ():
|
||||
|
||||
19
lisp/emacs-application-framework/app/js-video-player/node_modules/core-js/LICENSE
generated
vendored
19
lisp/emacs-application-framework/app/js-video-player/node_modules/core-js/LICENSE
generated
vendored
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2014-2020 Denis Pushkarev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
58
lisp/emacs-application-framework/app/js-video-player/node_modules/core-js/README.md
generated
vendored
58
lisp/emacs-application-framework/app/js-video-player/node_modules/core-js/README.md
generated
vendored
@@ -1,58 +0,0 @@
|
||||
# core-js
|
||||
|
||||
[](#sponsors) [](#backers) [](https://gitter.im/zloirock/core-js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://www.npmjs.com/package/core-js) [](http://npm-stat.com/charts.html?package=core-js&author=&from=2014-11-18) [](https://travis-ci.org/zloirock/core-js) [](https://david-dm.org/zloirock/core-js?type=dev)
|
||||
|
||||
> Modular standard library for JavaScript. Includes polyfills for [ECMAScript up to 2019](https://github.com/zloirock/core-js#ecmascript): [promises](https://github.com/zloirock/core-js#ecmascript-promise), [symbols](https://github.com/zloirock/core-js#ecmascript-symbol), [collections](https://github.com/zloirock/core-js#ecmascript-collections), iterators, [typed arrays](https://github.com/zloirock/core-js#ecmascript-typed-arrays), many other features, [ECMAScript proposals](https://github.com/zloirock/core-js#ecmascript-proposals), [some cross-platform WHATWG / W3C features and proposals](#web-standards) like [`URL`](https://github.com/zloirock/core-js#url-and-urlsearchparams). You can load only required features or use it without global namespace pollution.
|
||||
|
||||
## As advertising: the author is looking for a good job -)
|
||||
|
||||
## [core-js@3, babel and a look into the future](https://github.com/zloirock/core-js/tree/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md)
|
||||
|
||||
## Raising funds
|
||||
|
||||
`core-js` isn't backed by a company, so the future of this project depends on you. Become a sponsor or a backer [**on Open Collective**](https://opencollective.com/core-js) or [**on Patreon**](https://www.patreon.com/zloirock) if you are interested in `core-js`.
|
||||
|
||||
---
|
||||
|
||||
<a href="https://opencollective.com/core-js/sponsor/0/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/0/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/1/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/1/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/2/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/2/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/3/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/3/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/4/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/4/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/5/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/5/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/6/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/6/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/7/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/7/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/8/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/8/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/9/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/9/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/10/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/10/avatar.svg"></a><a href="https://opencollective.com/core-js/sponsor/11/website" target="_blank"><img src="https://opencollective.com/core-js/sponsor/11/avatar.svg"></a>
|
||||
|
||||
---
|
||||
|
||||
<a href="https://opencollective.com/core-js#backers" target="_blank"><img src="https://opencollective.com/core-js/backers.svg?width=890"></a>
|
||||
|
||||
---
|
||||
|
||||
[*Example*](http://goo.gl/a2xexl):
|
||||
```js
|
||||
import 'core-js'; // <- at the top of your entry point
|
||||
|
||||
Array.from(new Set([1, 2, 3, 2, 1])); // => [1, 2, 3]
|
||||
[1, [2, 3], [4, [5]]].flat(2); // => [1, 2, 3, 4, 5]
|
||||
Promise.resolve(32).then(x => console.log(x)); // => 32
|
||||
```
|
||||
|
||||
*You can load only required features*:
|
||||
```js
|
||||
import 'core-js/features/array/from'; // <- at the top of your entry point
|
||||
import 'core-js/features/array/flat'; // <- at the top of your entry point
|
||||
import 'core-js/features/set'; // <- at the top of your entry point
|
||||
import 'core-js/features/promise'; // <- at the top of your entry point
|
||||
|
||||
Array.from(new Set([1, 2, 3, 2, 1])); // => [1, 2, 3]
|
||||
[1, [2, 3], [4, [5]]].flat(2); // => [1, 2, 3, 4, 5]
|
||||
Promise.resolve(32).then(x => console.log(x)); // => 32
|
||||
```
|
||||
|
||||
*Or use it without global namespace pollution*:
|
||||
```js
|
||||
import from from 'core-js-pure/features/array/from';
|
||||
import flat from 'core-js-pure/features/array/flat';
|
||||
import Set from 'core-js-pure/features/set';
|
||||
import Promise from 'core-js-pure/features/promise';
|
||||
|
||||
from(new Set([1, 2, 3, 2, 1])); // => [1, 2, 3]
|
||||
flat([1, [2, 3], [4, [5]]], 2); // => [1, 2, 3, 4, 5]
|
||||
Promise.resolve(32).then(x => console.log(x)); // => 32
|
||||
```
|
||||
|
||||
**It's a global version (first 2 examples), for more info see [`core-js` documentation](https://github.com/zloirock/core-js/blob/master/README.md).**
|
||||
@@ -1,23 +0,0 @@
|
||||
var has = require('./internals/has');
|
||||
var isArray = require('./internals/is-array');
|
||||
var isForced = require('./internals/is-forced');
|
||||
var shared = require('./internals/shared-store');
|
||||
|
||||
var data = isForced.data;
|
||||
var normalize = isForced.normalize;
|
||||
var USE_FUNCTION_CONSTRUCTOR = 'USE_FUNCTION_CONSTRUCTOR';
|
||||
var ASYNC_ITERATOR_PROTOTYPE = 'AsyncIteratorPrototype';
|
||||
|
||||
var setAggressivenessLevel = function (object, constant) {
|
||||
if (isArray(object)) for (var i = 0; i < object.length; i++) data[normalize(object[i])] = constant;
|
||||
};
|
||||
|
||||
module.exports = function (options) {
|
||||
if (typeof options == 'object') {
|
||||
setAggressivenessLevel(options.useNative, isForced.NATIVE);
|
||||
setAggressivenessLevel(options.usePolyfill, isForced.POLYFILL);
|
||||
setAggressivenessLevel(options.useFeatureDetection, null);
|
||||
if (has(options, USE_FUNCTION_CONSTRUCTOR)) shared[USE_FUNCTION_CONSTRUCTOR] = !!options[USE_FUNCTION_CONSTRUCTOR];
|
||||
if (has(options, ASYNC_ITERATOR_PROTOTYPE)) shared[USE_FUNCTION_CONSTRUCTOR] = options[ASYNC_ITERATOR_PROTOTYPE];
|
||||
}
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
This folder contains entry points for [stable ECMAScript features](https://github.com/zloirock/core-js/tree/v3#ecmascript) with dependencies.
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../modules/es.array-buffer.constructor');
|
||||
require('../../modules/es.object.to-string');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.ArrayBuffer;
|
||||
@@ -1,7 +0,0 @@
|
||||
require('../../modules/es.array-buffer.constructor');
|
||||
require('../../modules/es.array-buffer.is-view');
|
||||
require('../../modules/es.array-buffer.slice');
|
||||
require('../../modules/es.object.to-string');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.ArrayBuffer;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array-buffer.is-view');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.ArrayBuffer.isView;
|
||||
@@ -1 +0,0 @@
|
||||
require('../../modules/es.array-buffer.slice');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.concat');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'concat');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.copy-within');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'copyWithin');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.iterator');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'entries');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.every');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'every');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.fill');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'fill');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.filter');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'filter');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.find-index');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'findIndex');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.find');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'find');
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../modules/es.array.flat-map');
|
||||
require('../../modules/es.array.unscopables.flat-map');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'flatMap');
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../modules/es.array.flat');
|
||||
require('../../modules/es.array.unscopables.flat');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'flat');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.for-each');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'forEach');
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../modules/es.string.iterator');
|
||||
require('../../modules/es.array.from');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Array.from;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.includes');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'includes');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.index-of');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'indexOf');
|
||||
@@ -1,33 +0,0 @@
|
||||
require('../../modules/es.string.iterator');
|
||||
require('../../modules/es.array.from');
|
||||
require('../../modules/es.array.is-array');
|
||||
require('../../modules/es.array.of');
|
||||
require('../../modules/es.array.concat');
|
||||
require('../../modules/es.array.copy-within');
|
||||
require('../../modules/es.array.every');
|
||||
require('../../modules/es.array.fill');
|
||||
require('../../modules/es.array.filter');
|
||||
require('../../modules/es.array.find');
|
||||
require('../../modules/es.array.find-index');
|
||||
require('../../modules/es.array.flat');
|
||||
require('../../modules/es.array.flat-map');
|
||||
require('../../modules/es.array.for-each');
|
||||
require('../../modules/es.array.includes');
|
||||
require('../../modules/es.array.index-of');
|
||||
require('../../modules/es.array.iterator');
|
||||
require('../../modules/es.array.join');
|
||||
require('../../modules/es.array.last-index-of');
|
||||
require('../../modules/es.array.map');
|
||||
require('../../modules/es.array.reduce');
|
||||
require('../../modules/es.array.reduce-right');
|
||||
require('../../modules/es.array.reverse');
|
||||
require('../../modules/es.array.slice');
|
||||
require('../../modules/es.array.some');
|
||||
require('../../modules/es.array.sort');
|
||||
require('../../modules/es.array.species');
|
||||
require('../../modules/es.array.splice');
|
||||
require('../../modules/es.array.unscopables.flat');
|
||||
require('../../modules/es.array.unscopables.flat-map');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Array;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.is-array');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Array.isArray;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.iterator');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'values');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.join');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'join');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.iterator');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'keys');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.last-index-of');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'lastIndexOf');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.map');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'map');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.of');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Array.of;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.reduce-right');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'reduceRight');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.reduce');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'reduce');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.reverse');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'reverse');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.slice');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'slice');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.some');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'some');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.sort');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'sort');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.splice');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'splice');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.array.iterator');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Array', 'values');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.concat');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').concat;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.copy-within');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').copyWithin;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.iterator');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').entries;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.every');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').every;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.fill');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').fill;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.filter');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').filter;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.find-index');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').findIndex;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.find');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').find;
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../../modules/es.array.flat-map');
|
||||
require('../../../modules/es.array.unscopables.flat-map');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').flatMap;
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../../modules/es.array.flat');
|
||||
require('../../../modules/es.array.unscopables.flat');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').flat;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.for-each');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').forEach;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.includes');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').includes;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.index-of');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').indexOf;
|
||||
@@ -1,29 +0,0 @@
|
||||
require('../../../modules/es.array.concat');
|
||||
require('../../../modules/es.array.copy-within');
|
||||
require('../../../modules/es.array.every');
|
||||
require('../../../modules/es.array.fill');
|
||||
require('../../../modules/es.array.filter');
|
||||
require('../../../modules/es.array.find');
|
||||
require('../../../modules/es.array.find-index');
|
||||
require('../../../modules/es.array.flat');
|
||||
require('../../../modules/es.array.flat-map');
|
||||
require('../../../modules/es.array.for-each');
|
||||
require('../../../modules/es.array.includes');
|
||||
require('../../../modules/es.array.index-of');
|
||||
require('../../../modules/es.array.iterator');
|
||||
require('../../../modules/es.array.join');
|
||||
require('../../../modules/es.array.last-index-of');
|
||||
require('../../../modules/es.array.map');
|
||||
require('../../../modules/es.array.reduce');
|
||||
require('../../../modules/es.array.reduce-right');
|
||||
require('../../../modules/es.array.reverse');
|
||||
require('../../../modules/es.array.slice');
|
||||
require('../../../modules/es.array.some');
|
||||
require('../../../modules/es.array.sort');
|
||||
require('../../../modules/es.array.species');
|
||||
require('../../../modules/es.array.splice');
|
||||
require('../../../modules/es.array.unscopables.flat');
|
||||
require('../../../modules/es.array.unscopables.flat-map');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.iterator');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').values;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.join');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').join;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.iterator');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').keys;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.last-index-of');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').lastIndexOf;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.map');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').map;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.reduce-right');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').reduceRight;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.reduce');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').reduce;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.reverse');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').reverse;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.slice');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').slice;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.some');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').some;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.sort');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').sort;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.splice');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').splice;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.array.iterator');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Array').values;
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../modules/es.data-view');
|
||||
require('../../modules/es.object.to-string');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.DataView;
|
||||
@@ -1,8 +0,0 @@
|
||||
require('../../modules/es.date.now');
|
||||
require('../../modules/es.date.to-json');
|
||||
require('../../modules/es.date.to-iso-string');
|
||||
require('../../modules/es.date.to-string');
|
||||
require('../../modules/es.date.to-primitive');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Date;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.date.now');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Date.now;
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../../modules/es.date.to-iso-string');
|
||||
require('../../modules/es.date.to-json');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Date', 'toISOString');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.date.to-json');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Date', 'toJSON');
|
||||
@@ -1,6 +0,0 @@
|
||||
require('../../modules/es.date.to-primitive');
|
||||
var toPrimitive = require('../../internals/date-to-primitive');
|
||||
|
||||
module.exports = function (it, hint) {
|
||||
return toPrimitive.call(it, hint);
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
require('../../modules/es.date.to-string');
|
||||
var dateToString = Date.prototype.toString;
|
||||
|
||||
module.exports = function toString(it) {
|
||||
return dateToString.call(it);
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.function.bind');
|
||||
var entryUnbind = require('../../internals/entry-unbind');
|
||||
|
||||
module.exports = entryUnbind('Function', 'bind');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../modules/es.function.has-instance');
|
||||
var wellKnownSymbol = require('../../internals/well-known-symbol');
|
||||
|
||||
module.exports = Function[wellKnownSymbol('hasInstance')];
|
||||
@@ -1,6 +0,0 @@
|
||||
require('../../modules/es.function.bind');
|
||||
require('../../modules/es.function.name');
|
||||
require('../../modules/es.function.has-instance');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.Function;
|
||||
@@ -1 +0,0 @@
|
||||
require('../../modules/es.function.name');
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.function.bind');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Function').bind;
|
||||
@@ -1,4 +0,0 @@
|
||||
require('../../../modules/es.function.bind');
|
||||
var entryVirtual = require('../../../internals/entry-virtual');
|
||||
|
||||
module.exports = entryVirtual('Function');
|
||||
@@ -1,3 +0,0 @@
|
||||
require('../modules/es.global-this');
|
||||
|
||||
module.exports = require('../internals/global');
|
||||
210
lisp/emacs-application-framework/app/js-video-player/node_modules/core-js/es/index.js
generated
vendored
210
lisp/emacs-application-framework/app/js-video-player/node_modules/core-js/es/index.js
generated
vendored
@@ -1,210 +0,0 @@
|
||||
require('../modules/es.symbol');
|
||||
require('../modules/es.symbol.async-iterator');
|
||||
require('../modules/es.symbol.description');
|
||||
require('../modules/es.symbol.has-instance');
|
||||
require('../modules/es.symbol.is-concat-spreadable');
|
||||
require('../modules/es.symbol.iterator');
|
||||
require('../modules/es.symbol.match');
|
||||
require('../modules/es.symbol.match-all');
|
||||
require('../modules/es.symbol.replace');
|
||||
require('../modules/es.symbol.search');
|
||||
require('../modules/es.symbol.species');
|
||||
require('../modules/es.symbol.split');
|
||||
require('../modules/es.symbol.to-primitive');
|
||||
require('../modules/es.symbol.to-string-tag');
|
||||
require('../modules/es.symbol.unscopables');
|
||||
require('../modules/es.object.assign');
|
||||
require('../modules/es.object.create');
|
||||
require('../modules/es.object.define-property');
|
||||
require('../modules/es.object.define-properties');
|
||||
require('../modules/es.object.entries');
|
||||
require('../modules/es.object.freeze');
|
||||
require('../modules/es.object.from-entries');
|
||||
require('../modules/es.object.get-own-property-descriptor');
|
||||
require('../modules/es.object.get-own-property-descriptors');
|
||||
require('../modules/es.object.get-own-property-names');
|
||||
require('../modules/es.object.get-prototype-of');
|
||||
require('../modules/es.object.is');
|
||||
require('../modules/es.object.is-extensible');
|
||||
require('../modules/es.object.is-frozen');
|
||||
require('../modules/es.object.is-sealed');
|
||||
require('../modules/es.object.keys');
|
||||
require('../modules/es.object.prevent-extensions');
|
||||
require('../modules/es.object.seal');
|
||||
require('../modules/es.object.set-prototype-of');
|
||||
require('../modules/es.object.values');
|
||||
require('../modules/es.object.to-string');
|
||||
require('../modules/es.object.define-getter');
|
||||
require('../modules/es.object.define-setter');
|
||||
require('../modules/es.object.lookup-getter');
|
||||
require('../modules/es.object.lookup-setter');
|
||||
require('../modules/es.function.bind');
|
||||
require('../modules/es.function.name');
|
||||
require('../modules/es.function.has-instance');
|
||||
require('../modules/es.global-this');
|
||||
require('../modules/es.array.from');
|
||||
require('../modules/es.array.is-array');
|
||||
require('../modules/es.array.of');
|
||||
require('../modules/es.array.concat');
|
||||
require('../modules/es.array.copy-within');
|
||||
require('../modules/es.array.every');
|
||||
require('../modules/es.array.fill');
|
||||
require('../modules/es.array.filter');
|
||||
require('../modules/es.array.find');
|
||||
require('../modules/es.array.find-index');
|
||||
require('../modules/es.array.flat');
|
||||
require('../modules/es.array.flat-map');
|
||||
require('../modules/es.array.for-each');
|
||||
require('../modules/es.array.includes');
|
||||
require('../modules/es.array.index-of');
|
||||
require('../modules/es.array.join');
|
||||
require('../modules/es.array.last-index-of');
|
||||
require('../modules/es.array.map');
|
||||
require('../modules/es.array.reduce');
|
||||
require('../modules/es.array.reduce-right');
|
||||
require('../modules/es.array.reverse');
|
||||
require('../modules/es.array.slice');
|
||||
require('../modules/es.array.some');
|
||||
require('../modules/es.array.sort');
|
||||
require('../modules/es.array.splice');
|
||||
require('../modules/es.array.species');
|
||||
require('../modules/es.array.unscopables.flat');
|
||||
require('../modules/es.array.unscopables.flat-map');
|
||||
require('../modules/es.array.iterator');
|
||||
require('../modules/es.string.from-code-point');
|
||||
require('../modules/es.string.raw');
|
||||
require('../modules/es.string.code-point-at');
|
||||
require('../modules/es.string.ends-with');
|
||||
require('../modules/es.string.includes');
|
||||
require('../modules/es.string.match');
|
||||
require('../modules/es.string.match-all');
|
||||
require('../modules/es.string.pad-end');
|
||||
require('../modules/es.string.pad-start');
|
||||
require('../modules/es.string.repeat');
|
||||
require('../modules/es.string.replace');
|
||||
require('../modules/es.string.search');
|
||||
require('../modules/es.string.split');
|
||||
require('../modules/es.string.starts-with');
|
||||
require('../modules/es.string.trim');
|
||||
require('../modules/es.string.trim-start');
|
||||
require('../modules/es.string.trim-end');
|
||||
require('../modules/es.string.iterator');
|
||||
require('../modules/es.string.anchor');
|
||||
require('../modules/es.string.big');
|
||||
require('../modules/es.string.blink');
|
||||
require('../modules/es.string.bold');
|
||||
require('../modules/es.string.fixed');
|
||||
require('../modules/es.string.fontcolor');
|
||||
require('../modules/es.string.fontsize');
|
||||
require('../modules/es.string.italics');
|
||||
require('../modules/es.string.link');
|
||||
require('../modules/es.string.small');
|
||||
require('../modules/es.string.strike');
|
||||
require('../modules/es.string.sub');
|
||||
require('../modules/es.string.sup');
|
||||
require('../modules/es.regexp.constructor');
|
||||
require('../modules/es.regexp.exec');
|
||||
require('../modules/es.regexp.flags');
|
||||
require('../modules/es.regexp.sticky');
|
||||
require('../modules/es.regexp.test');
|
||||
require('../modules/es.regexp.to-string');
|
||||
require('../modules/es.parse-int');
|
||||
require('../modules/es.parse-float');
|
||||
require('../modules/es.number.constructor');
|
||||
require('../modules/es.number.epsilon');
|
||||
require('../modules/es.number.is-finite');
|
||||
require('../modules/es.number.is-integer');
|
||||
require('../modules/es.number.is-nan');
|
||||
require('../modules/es.number.is-safe-integer');
|
||||
require('../modules/es.number.max-safe-integer');
|
||||
require('../modules/es.number.min-safe-integer');
|
||||
require('../modules/es.number.parse-float');
|
||||
require('../modules/es.number.parse-int');
|
||||
require('../modules/es.number.to-fixed');
|
||||
require('../modules/es.number.to-precision');
|
||||
require('../modules/es.math.acosh');
|
||||
require('../modules/es.math.asinh');
|
||||
require('../modules/es.math.atanh');
|
||||
require('../modules/es.math.cbrt');
|
||||
require('../modules/es.math.clz32');
|
||||
require('../modules/es.math.cosh');
|
||||
require('../modules/es.math.expm1');
|
||||
require('../modules/es.math.fround');
|
||||
require('../modules/es.math.hypot');
|
||||
require('../modules/es.math.imul');
|
||||
require('../modules/es.math.log10');
|
||||
require('../modules/es.math.log1p');
|
||||
require('../modules/es.math.log2');
|
||||
require('../modules/es.math.sign');
|
||||
require('../modules/es.math.sinh');
|
||||
require('../modules/es.math.tanh');
|
||||
require('../modules/es.math.to-string-tag');
|
||||
require('../modules/es.math.trunc');
|
||||
require('../modules/es.date.now');
|
||||
require('../modules/es.date.to-json');
|
||||
require('../modules/es.date.to-iso-string');
|
||||
require('../modules/es.date.to-string');
|
||||
require('../modules/es.date.to-primitive');
|
||||
require('../modules/es.json.stringify');
|
||||
require('../modules/es.json.to-string-tag');
|
||||
require('../modules/es.promise');
|
||||
require('../modules/es.promise.all-settled');
|
||||
require('../modules/es.promise.finally');
|
||||
require('../modules/es.map');
|
||||
require('../modules/es.set');
|
||||
require('../modules/es.weak-map');
|
||||
require('../modules/es.weak-set');
|
||||
require('../modules/es.array-buffer.constructor');
|
||||
require('../modules/es.array-buffer.is-view');
|
||||
require('../modules/es.array-buffer.slice');
|
||||
require('../modules/es.data-view');
|
||||
require('../modules/es.typed-array.int8-array');
|
||||
require('../modules/es.typed-array.uint8-array');
|
||||
require('../modules/es.typed-array.uint8-clamped-array');
|
||||
require('../modules/es.typed-array.int16-array');
|
||||
require('../modules/es.typed-array.uint16-array');
|
||||
require('../modules/es.typed-array.int32-array');
|
||||
require('../modules/es.typed-array.uint32-array');
|
||||
require('../modules/es.typed-array.float32-array');
|
||||
require('../modules/es.typed-array.float64-array');
|
||||
require('../modules/es.typed-array.from');
|
||||
require('../modules/es.typed-array.of');
|
||||
require('../modules/es.typed-array.copy-within');
|
||||
require('../modules/es.typed-array.every');
|
||||
require('../modules/es.typed-array.fill');
|
||||
require('../modules/es.typed-array.filter');
|
||||
require('../modules/es.typed-array.find');
|
||||
require('../modules/es.typed-array.find-index');
|
||||
require('../modules/es.typed-array.for-each');
|
||||
require('../modules/es.typed-array.includes');
|
||||
require('../modules/es.typed-array.index-of');
|
||||
require('../modules/es.typed-array.iterator');
|
||||
require('../modules/es.typed-array.join');
|
||||
require('../modules/es.typed-array.last-index-of');
|
||||
require('../modules/es.typed-array.map');
|
||||
require('../modules/es.typed-array.reduce');
|
||||
require('../modules/es.typed-array.reduce-right');
|
||||
require('../modules/es.typed-array.reverse');
|
||||
require('../modules/es.typed-array.set');
|
||||
require('../modules/es.typed-array.slice');
|
||||
require('../modules/es.typed-array.some');
|
||||
require('../modules/es.typed-array.sort');
|
||||
require('../modules/es.typed-array.subarray');
|
||||
require('../modules/es.typed-array.to-locale-string');
|
||||
require('../modules/es.typed-array.to-string');
|
||||
require('../modules/es.reflect.apply');
|
||||
require('../modules/es.reflect.construct');
|
||||
require('../modules/es.reflect.define-property');
|
||||
require('../modules/es.reflect.delete-property');
|
||||
require('../modules/es.reflect.get');
|
||||
require('../modules/es.reflect.get-own-property-descriptor');
|
||||
require('../modules/es.reflect.get-prototype-of');
|
||||
require('../modules/es.reflect.has');
|
||||
require('../modules/es.reflect.is-extensible');
|
||||
require('../modules/es.reflect.own-keys');
|
||||
require('../modules/es.reflect.prevent-extensions');
|
||||
require('../modules/es.reflect.set');
|
||||
require('../modules/es.reflect.set-prototype-of');
|
||||
var path = require('../internals/path');
|
||||
|
||||
module.exports = path;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user