chenyanming/paw

Emacs Annotation and Language Learning tool.

Emacs Lisp

171

954 commits

updated Aug 10, 2026

See the code

README

#+title: paw (point-and-write)

[[file:images/logo.jpg]]

Study for a life in Emacs.

~paw.el~ was created in 2021 as an annotation tool, but I was not used it a lot at that time. Recently I picked it up and dramatically changed its usage. Now it is a complete solution of making annotations and language learning tools, right inside Emacs.

paw relies on sqlite. All annotations are saved inside a database, which means it can be easily backup and you can read and make annotation right inside Emacs (PC/mobile) using same database.

paw is not just a dictionary tool. paw was created in mind that:
1. Query word with single mouse click, even no need to click.
2. Save and trace all known/unknown words and wordlist support, online or offline.
3. Integrate with other great open source tools, libraries, and dictionaries.
4. Integrate with external dictionary tools.
5. Support many languages.
6. Multi-Platform Support, including Mobile/e-link devices.
7. Use AI as assistant.

#+begin_quote
The standout feature of Paw is the ability to scan an entire buffer, tokenize all words, batch-query them, and filter them out according to user-provided tags, ultimately applying overlays alongside meanings to all discovered words. In essence, Paw proactively queries the dictionary on your behalf, making the highlighted word's meaning immediately available.

This means that you can simply hover your mouse over a word to view its definition, without having to click on it.
#+end_quote

This package is mainly used along with:
1. nov-mode
2. org-mode
3. markdown-mode
4. eaf-mode
5. eww-mode
6. wallabag-entry-mode
7. pdf-view-mode
8. elfeed-show-entry-mode
9. telega-webpage-mode
10. [[https://github.com/chenyanming/paw_org_protocol][Browser Support]]
11. Derived text-mode
12. Derived prog-mode

* Get started
** M-x ~paw-annotation-mode~ 
Modes that supported in ~paw-annotation-mode-supported-modes~ can enable
~paw-annotation-mode~.

See the doc of ~M-x describe-function paw-annotation-mode~

** M-x ~paw-annotation-live-mode~
~paw-annotation-live-mode~ is similar as ~paw-annotation-mode~

But it can be used on any buffer, less limitation, and less keybindings,
with auto refresh annotation overlays feature.

See the doc of ~M-x describe-function paw-annotation-live-mode~

* What can paw do?
** Reading and annotation
1. Open an epub file using nov.el, open an org/txt/md file, browse web with eww/eaf, read rss with elfeed, you name it.
2. Enable ~paw-annotation-mode~ (buffer will be turned into read-only if
   ~paw-annotation-read-only-enable~ is t to avoid accidental alternation)
3. Use ~paw~ add word/highlight/bookmark/todo/, for example, ~paw-add-word~,
   ~paw-add-highlight~... Please check M-x ~paw-add-*~ related commands for all type
   of supported annotations.
4. Annotations will be highlighted via overlay. Under the annotation, you can do
   various of operations. For example, to edit the annotation, under the
   annotation, press ~i~, ~paw-find-note~. It will create an temporary org file
   dedicated for this annotation, ~C-c C-i~ to insert annotation link as reflink,
   finally save by ~C-c C-c~, changes will be saved in the database respectively.
5. Under the annotation, run ~paw-change-annotation-note-type~ (~c~) or
   ~paw-change-note_type~ (~C~) to change the face of the overlay.
6. The most useful case is adding highlight by ~paw-add-highlight~, then change
   the highlight overlay by ~paw-change-annotation-note-type~. The default
   highlight overlay is defined in ~paw-annotation-default-highlight-type~, and
   running ~paw-change-annotation-note-type~ will remember the last highlight
   overlay. paw predefines some most used highlight styles that often appeared
   in other annotation tools, like marker or underline (press ~c1~, ~c2~, ~c3~, etc),
   but it is not limited to that, you can change to any face you want (press ~cf~)
7. Use ~paw-add-comment~ (~C-c i~ or ~i~ [evil] under ~paw-annotation-mode~) to
   quickly add a comment to the current thing (~paw-add-comment-thing~), if no
   comment is added, the annotation will be deleted after quitting the note
   buffer. ~paw-add-comment~ is actually a convenient wrapper of ~paw-add-highlight~
   and ~paw-find-note~.
   1. Inside ~*paw-view-note*~ buffer, you can press ~i~ to edit the Saved Meanings or Notes. Check ~paw-view-note-transient~ for more operations.
8. Call ~paw~, ~paw-list-annotations~, ~paw-list-all-annotations~ or
   ~paw-list-all-links~ to manage or jump to annotation location (One useful case
   is that make highlight or create bookmark on ~eww~, and jump back to the exact
   same annotation location simply pressing Enter)
9. Under the annotation, M-x ~paw-view-notes~, all notes under the same path will
   be shown, giving you an overview on all notes you've made for the same file.
   Or M-x ~paw-find-notes~ to update/save all notes under the same path into an
   org file under ~paw-note-dir~, and jump to the annotation location inside the
   org file.
10. ~paw-add-bookmark~ works great on eww-mode/eaf-mode (browser or pdf-viewer)
11. ~M-x paw-toggle-inline-annotations~, to show all annotations inline.

[[file:images/annatation.png]]

** Editing/Programming while Annotating
*** Method 1: M-x ~paw-annotation-live-mode~
Any buffer can enable paw-annotation-live-mode. After enabling it, you can add annotations with M-x paw-add-*. After file saved, annotations will be auto refreshed (location will be updated if possible).

~M-x paw-toggle-inline-annotations~, to show all annotations inline.


*** Method 2: M-x paw-annotation-mode
By default, the major-mode includes in ~paw-annotation-mode-supported-modes~ will
turn into read-only if ~paw-annotation-read-only-enable~ is t.

However, two special modes text-mode/prog-mode are added in
~paw-annotation-mode-supported-modes~. If the current buffer's major-mode is not
one of modes in ~paw-annotation-mode-supported-modes~ but derived from ~text-mode~
or ~prog-mode~. Enabling ~paw-annotation-mode~ will not alternate the read-only
status, in the mean time, it shows annotations made on the current buffer while
disable other paw-annotation-mode features (like mouse click to query, show
unknown words, show wordlists' words etc, which makes sense when Reading but not
Editing). This makes sure that we can continue to edit the buffer and use the
buffer's cooresponding keymaps while also able to add/show/manage annotations.

~M-x paw-toggle-inline-annotations~, to show all annotations inline.

[[file:images/programming.png]]

** Language Learning
1. Copy a text you want to learn to an org file or browse a page with eww/eaf etc.
2. Enable ~paw-annotation-mode~
3. Click/Select word/sentence with ~paw-view-note~, it will show you an
   informative buffer of the word/sentence. It has dictionary, translation,
   notes and also able to search by external browser.
4. Use ~paw-add-offline-word~ or ~paw-add-online-word~ to add a new word. For Online
   words, please check 
        #+html: <a href="#anki-integration">Anki Integration</a>
        #+html: <a href="#eudic-integration">Eudic Integration</a>
   All offline/online words appeared on any buffers that were enabled
   ~paw-annoation-mode~ will be highlighted, useful for language learners using
   the important method: Repetition.
5. For offline words, please setup ~paw-offline-studylist~ before using it. By
   default we have two offline studylists: =English Studylist= and =Japanese
   Studylist=.
6. You can also use ~paw-add-word~. Unlike offline/online word, the word added by
   ~paw-add-word~ is linked with an unique id, it is only highlighted at the
   location where we added it.
7. Under any annotation, click or press ~v~ to invoke ~paw-view-note~, a buffer
   with saved meanings, dictionary, translation, notes is shown.
8. Under any annotation, click or press ~S~ to invoke
   ~paw-change-word-learning-level~, select from level 1~5. 1~4 are controlled by
   ~paw-level-1-word-face~ to ~paw-level-4-word-face~ for online words,
   ~paw-level-1-offline-word-face~ to ~paw-level-4-offline-word-face~ for offline
   words, while 5 is considered as Known word, skipping adding overlay face
   (just hiding). You can change the word to level 5 while keep it hiding, but
   if you don't need it anymore, simply run =paw-delete-annotation= to delete it.
9. Click/Select word/sentence with ~paw-view-note-current-thing~,
   ~paw-view-note-next-thing~, ~paw-view-note-prev-thing~, it will do segmentation
   using [[https://github.com/ikawaha/kagome][kagome]] (Japanese), and [[https://github.com/skywind3000/ECDICT][ECDICT]] (English).
10. Check https://www.lingq.com/en/, you know more ideas how to learn a foreign
    language with ~paw.el~.
11. Run ~paw-export-notes-to-csv~, check the csv file under ~paw-csv-file~, import it
    to [[https://apps.ankiweb.net/][Anki]] for further studying.
12. Both ~paw-add-word~ and ~paw-add-online-word~ will capture the context sentence
    and save it into Notes field.
- ~M-x paw-toggle-inline-annotations~, to show all annotations inline (think about it as a similar feature - [[https://www.amazon.com/gp/help/customer/display.html?nodeId=201645250][kindle word wise]])
14. Check ~paw-annotation-transient~ for more operations.
15. To review all words in the current buffer, under any unknown/known word (the
    overlay), C-u M-x ~paw-view-notes~, all unknown/known words appeared in the
    current buffer will be shown, giving you an overview on all words appeared
    in the current buffer. Or C-u M-x ~paw-find-notes~ to save all words appeared
    in the current buffer into an org file under ~paw-note-dir~, and jump to the
    annotation location inside the org file.
16. Please notice: if use M-x ~paw-view-notes~ without C-u, all notes under the
    path the moment it was captured will be shown instead.

Tip: Find some interesting contents on LingQ, and browse using eww, enable
~paw-annotation-mode~, enjoy language studying!

[[file:images/learning.png]]

** Search a word/sentence inside Emacs
1. Select/Under a word/sentence
2. Run ~paw-view-note~ (no segmentation, good for word) or
   ~paw-view-note-current-thing~ (segmentation, good for sentence)
3. Further search with ~paw-view-note-in-dictionary~ or search with browser.

** Search a word/sentence with external dictionary
1. Select/Under a word/sentence
2. Run ~paw-view-note-in-dictionary~, currently support eudic/goldendict/silverdict/yomitan (configured by ~paw-dictionary-function~)
3. You can also use:
   - ~paw-mac-dictionary-search-details~ (can configure mac dictionary or eudic, by ~paw-mac-dictionary-program~)
   - ~paw-goldendict-search-details~ (by ~paw-goldendict-program~)
   - ~paw-silverdict-search-details~ (by ~paw-silverdict-host~ and ~paw-silverdict-port~)
   - ~paw-yomitan-search-details-firefox~ (configure ~paw-yomitan-firefox-id~ and yomitan extension on browser before use)
   - ~paw-yomitan-search-details-chrome~ (configure yomitan extension on browser before use)
   - ~paw-android-search-details~ (android)
   - ~paw-eudic-search-details~ (mac/android/windows, ~paw-eudic-android-program~)
   - ~paw-chatgpt-search-details~ (mac/android, ~paw-chatgpt-android-program~)
   - ~paw-moji-search-details~ (android, ~paw-moji-android-program~)

** Manage annotations
#+begin_src emacs-lisp
M-x paw
#+end_src

It will launch a dashboard of annotations based on the current path of the buffer or project-root (text-mode/prog-mode).

Overview all notes using ~paw-view-notes~ on the same path.
Demo:
#+attr_org: :width 500px
[[file:images/overview.png]]


Export notes to an org file and print out as pdf (using latex), use ~paw-find-notes~.

Demo:
#+attr_org: :width 500px
[[file:images/latex.png]]

* Installation
You should install the following Dependencies if you want to make use all the power of paw:

- Command line tools
  - [[https://github.com/Dushistov/sdcv][sdcv]] (external command line dictionary)
  - mpv (or other command line mp3 player)
  - [[https://github.com/goldendict/goldendict][goldendict]] (external dictionary)
  - [[https://github.com/Crissium/SilverDict][silverdict]] (external web-based dictionary, works on Android)
  - [[https://github.com/rany2/edge-tts/][edge-tts]] (pronunciation)
  - [[https://github.com/ikawaha/kagome][kagome]] (For Japanese sentence segmentation)

- python dependencies (install paw command line by ~pip install emacs-paw~ or one by one manually):
  - Python itself (3.10+, for mac 3.11+)
  - nltk
  - flask
  - flask-cors
  - requests
  - mecab-python3
  - unidic-lite
  - waitress (optional, for enhanced server performance)

- Language detection python dependencies:
  - paw (emacs-paw cli), [[https://github.com/pemistahl/lingua-py][lingua-py]], pycld2, or gcld3

- Emacs packages (Not all are needed, some are optional, but paw just supports them. Some needed packages will be installed along with paw):
  - [[https://github.com/lorniu/go-translate][go-translate]] (Needed, for online transalation)
  - [[https://github.com/karthink/gptel][gptel]] (Needed, for ai translation)
  - emacsql (Needed)
  - transient (Needed)
  - [[https://github.com/larstvei/Focus][focus]]
  - svg-lib
  - anki-eidtor
  - all-the-icons
  - nerd-icons
  - immersive-translate
  - ivy
  - consult
  - posframe
  - [[https://github.com/kisaragi-hiu/emacs-jieba][jieba]]
  - eldoc-box
  - evil
  - esxml
  - [[https://github.com/chenyanming/shrface][shrface]]
  - [[https://github.com/chenyanming/wallabag.el][wallabag]]
  - [[https://github.com/emacs-eaf/emacs-application-framework][eaf]]
  - [[https://github.com/manateelazycat/popweb][popweb]]
  - pdf-tools
  - elfeed
  - telega

- Offline Dictionary:
  - [[https://sourceforge.net/projects/stardict-4/][stardict]] dictionaries (Used by sdcv, you can download mine from [[https://github.com/chenyanming/sdcv_dictionaries][sdcv_dictionaries]])
  - [[https://github.com/skywind3000/ECDICT][ECDICT]] (Please go into the [[https://github.com/skywind3000/ECDICT/releases][page]] and download the ~ecdict-stardict-28.zip~, unzip as ~startdict.db~)
  - [[https://github.com/chenyanming/yomichan-jlpt-vocab][yomichan-jlpt-vocab]] (Please go into the page, clone the repo, and build the japanese.db by yourself, or download mine in [[https://github.com/chenyanming/paw_dictionaries][paw_dictionaries]])
  - text/csv dictionaries (I uploaded my dictionaries to [[https://github.com/chenyanming/paw_dictionaries][paw_dictionaries]], you can also easily convert the any Anki Deck into csv format and use them. Also, this project also provides some functions to download, check ~paw-util.el~)

- Other Dictionaries
  - [[https://github.com/yomidevs/yomitan][yomitan]] (external dictionary)


Five steps:
- Install Offline Dictionaries (See above)
- Install Python
#+begin_src sh 
brew install python # You can use pyenv or other tools to install python
#+end_src
- Install [[https://pypi.org/project/emacs-paw/][emacs-paw]] command line by the following command, check usage at [[https://github.com/chenyanming/paw_server][paw_server]]
#+begin_src sh
pip install emacs-paw
#+end_src

*Note*: The Python CLI tool and server components have been migrated to [[https://github.com/chenyanming/paw_server][paw_server]] for better organization and standalone usage.

- Please be patient... run the following command lines, you may need to adjust them based on your system, take mac for example:
#+begin_src sh
brew install sdcv
brew install mpv
pip install edge-tts
python -m nltk.downloader stopwords
python -m nltk.downloader punkt
python -m nltk.downloader punkt_tab
#+end_src
- For android install:
#+begin_src sh
pkg install tur-repo # https://github.com/termux-user-repository/tur
pkg install python3.10 # install python 3.10 (newer versions may not work at the time of writing)
#+end_src

- Finally, Install paw.el
#+begin_src emacs-lisp
(package! paw :recipe (:host github :repo "chenyanming/paw" :files ("*")))
#+end_src

* Configuration
** Configure paw.el
After installing the above Dependencies, you can configure paw like [[file:config.el][config.el]] (which I may update frequently based on my need). You should better copy to your own configurations and tweak it based on your need.

Some csv dictionaries can be found in [[https://github.com/chenyanming/paw_dictionaries][paw_dictionaries]], you can download them and change the location. You can also convert from [[https://ankiweb.net/shared/decks][Anki Decks]] or Make your own, it is just text based dictionaries.

You can also check the language specific configurations below:
- [[file:ENGLISH.org][English Configuration]]
- [[file:JAPANESE.org][Japanese Configuration]]
- [[file:CHINESE.org][Chinese Configuration]]

** configure sdcv (stardict)
#+begin_src emacs-lisp
(setq paw-sdcv-program "/opt/homebrew/bin/sdcv" )
(setq paw-sdcv-dictionary-data-dir (expand-file-name "dict" doom-private-dir))
;; (setq paw-sdcv-env-lang (getenv "LANG")) ;; may need this on linux and android
(setq paw-sdcv-dictionary-list    ;setup dictionary list for simple search
      '("懒虫简明英汉词典"
        "Collins Cobuild English Dictionary"
        "小学馆-日中词典"
        "日汉双解词典"
        "EJ-EDict" "JE-EDICT_Kanji"
        "日汉词典" "jmdict-ja-en" "KANJIDIC2" "新明解国語辞典"
        "小学館中日辞典EB版" "広辞苑 第六版" "EJ-GENE95"
        "jmdict-en-ja"
        "JCEDict" "EDICT"
        "JEDict" "ENAMDICT" "EJDic" "DrEye日汉词典" "DrEye4in1词典"))
#+end_src
** Keybindings
paw supports Emacs native keybindings, evil, and transient menu (?).

** Enable ~paw-annotation-mode~ automatically
You can add ~paw-annotation-mode~ to the corresponding hook, so that it can enable automatically after the corresponding mode is loaded:

#+begin_src emacs-lisp
(add-hook 'wallabag-entry-mode-hook #'paw-annotation-mode)
(add-hook 'nov-mode-hook #'paw-annotation-mode)
(add-hook 'elfeed-show-mode-hook #'paw-annotation-mode)
(add-hook 'eaf-mode-hook 'paw-annotation-mode)
(add-hook 'telega-webpage-mode-hook #'paw-annotation-mode)
#+end_src

Some modes like ~nov-mode~, ~wallabag-entry-mode~ and ~eww-mode~, adding above hook is not enough, you also need to add the following highlight functions ~:after~ the render function using ~advice-add~:
#+begin_src emacs-lisp
(when (bound-and-true-p paw-annotation-mode)
      (paw-clear-annotation-overlay)
      (paw-show-all-annotations)
      (if paw-annotation-show-wordlists-words-p
          (paw-focus-find-words :wordlist t))
      (if paw-annotation-show-unknown-words-p
          (paw-focus-find-words)))
#+end_src

For more examples, please check: https://github.com/chenyanming/shrface/blob/master/config.el

** One-Click or One-Key to query
By default, if ~paw-annotation-mode~ is enabled, you can =One-Click= to query the word. If you want to disable it:
#+begin_src emacs-lisp
(setq paw-view-note-click-enable nil) ;; Disable Left-Click One-Click to query feature
#+end_src

Or 
M-x ~paw-view-note-click-enable-toggle~ to toggle the =One-Click= feature on the fly.

You can also use ~paw-view-note-under-mouse~ to query the word under mouse, it is bound to ~`~ by default. Move the mouse and hover on the word to be queried, and press ~`~. I called it as ~One-Key~ to query.

+You may also use ~paw-view-note-click-directly~, which is bound to ~mouse-3~ (Right Click). This is not controlled by ~paw-view-note-click-enable~, it is also One-Click to query but using Right Click.+ -> I don't use it anymore.

Now,

Mouse-1 bound to ~paw-view-note-click~ (Click the word)
Mouse-2 bound to ~paw-view-note~ (After Mouse-1 drag a text then Mouse-2 for query the selected area)
Mouse-3 bound to ~paw-view-note-quit~ (Quit the view window)

** Sound engines
Paw includes multiple sound engines that can be used to download audio files. The available sound engines include:
- ~paw-say-word-cambridge~
- ~paw-say-word-oxford~
- ~paw-say-word-jpod101-alternate~
- ~paw-edge-tts-say-word~
- ~paw-youdao-say-word~
- ~paw-say-word-forvo~
- and more
By default, the sequence in which these sound engines are used is defined by ~paw-say-word-functions~.

The following configs control wheather say the word when you view by M-x ~paw-view-note~

#+begin_src emacs-lisp
(defcustom paw-say-word-p t
  "paw say word automatically"
  :group 'paw
  :type 'boolean)

(defcustom paw-say-word-supported-note-types '(word)
  "The note types will be say automatically."
  :group 'paw
  :type '(repeat (choice symbol)))
#+end_src

In dashboard header, it is possible to toggle the ~paw-say-word-p~ (Voice) on the fly.

** Audio player and volume control
Paw supports various audio players for pronunciation playback. The player program is automatically detected based on your system:

- macOS: ~afplay~ (with native ~--volume~ support)
- Other systems: ~mpv~, ~mplayer~, or ~mpg123~

You can configure the audio player and volume:

#+begin_src emacs-lisp
;; Audio player program (auto-detected by default)
(setq paw-player-program "/usr/bin/afplay")  ; or your preferred player

;; Volume control (0-100 range)
(setq paw-player-volume 50)  ; 50% volume
#+end_src

Volume support by player:
- ~mpv~: Uses ~--volume=N~ parameter
- ~mplayer~: Uses ~-volume N~ parameter
- ~afplay~ (macOS): Uses ~--volume N.N~ parameter (0.0-1.0 range)
- ~mpg123~: Uses ~-g N~ parameter for gain control
- ~aplayer~: No volume support, falls back to normal playback

** Icons/Buttons
Paw support all major emacs icons packages, you can choose one of them. 
- svg-icon
- nerd-icons (recommended if you use nerd fonts)
- all-the-icons
- pbm (image icons, recommended on android)
- text (if all options are nil, fallback to pure text as icons)

The current checking sequence is svg -> pbm -> all-the-icons -> nerd-icons -> text. The first ~t~ option will be used first.

To enable pbm on android while use nerd-icon on non-android, we can configure like so:
#+begin_src emacs-lisp
;; svg icons
(setq paw-svg-enable nil)
;; Use pbm icons/buttons on android
(setq paw-pbm-enable (if (eq system-type 'android) t))
;; all the icons icon
(setq paw-all-the-icons-icon-enable nil)
;; all the icons button 
(setq paw-all-the-icons-button-enable nil)
;; nerd icon/buttons
(setq paw-nerd-icons-icon-enable t)
#+end_src

** Configure Language Detection
Set ~paw-detect-language-p~ to t, paw will use emacs-paw python cli (to use others
tools check ~paw-detect-language-program~) to detect the language for more
accurate tts pronunciation and translation.

If you don't want to use language detection program, paw use simple ascii rate:
~paw-ascii-rate~ to detect the language, if the rate is greater than
~paw-ascii-rate~, then it is considered as English, otherwise use
~paw-detect-language-program~ to detect the language of the TEXT, if
~paw-detect-language-p~ is t, or return as ~paw-non-ascii-language~ if
~paw-detect-language-p~ is nil.

Setup ~paw-python-program~ if necessary, if the pip module is installed with
different python version, for android, set it to =python3.10=

Supported edge-tts voice:
- ~paw-tts-english-voice~
- ~paw-tts-zh-cn-voice~
- ~paw-tts-zh-tw-voice~
- ~paw-tts-japanese-voice~
- ~paw-tts-korean-voice~
- Other languages: ~paw-tts-multilingual-voice~
Welcome PRs to add more languages :)

** =*paw-view-note*= window configurations
If ~paw-view-note-window-auto-adjust~ is t (default), the window of
=*paw-view-note*= will be automatically adjusted. If the height of the window is
larger than the width, show it on the ~paw-view-note-vertical-position~, otherwise
show it on the ~paw-view-note-horizontal-position~. Also, the windows width/height
could be configured by ~paw-view-note-window-width~ and
~paw-view-note-window-height~.
** =*paw-view-note*= sections configurations
You can adjust the section order or remove the unwanted sections by configuring ~paw-view-note-sections~

The order of the sections is the order of the list.
Supported values are:
- "Dictionaries": The online dictionaries buttons
- "Search": The online search engine buttons
- "Context": The context around the word/annotation
- "Translation": The translation of the word/annotation
- "Saved Meanings": The Saved Meanings of the word/annotation
- "Meaning": The SDCV result of the word/annotation
- "Notes": The notes of the word/annotation
- "Anki": Special section for Anki

** Back to original buffer
Normally, when you run ~paw-view-note~, paw will switch to =*paw-view-note*= buffer. But there are some cases we want to stay at the original buffer, in this case:
- Set ~paw-view-note-back-to-original-buffer~ as t (Default)
- And add or remove the targeted major-mode into ~paw-view-note-back-to-original-buffer-supported-modes~.

** Configure Anki Integration
1. PC: Install Anki.
2. PC: Install AnkiConnect, add-on code: 2055492159.
3. Android: Install AnkiDroid from F-Driod (We need it has full media access
   right, so that Emacs can copy audio files to it. Instead of using AnkiConect
   to download the audio, paw will download and cache the audio in
   ~paw-tts-cache-dir~ after the voice is pronounced.).
4. Android: Install [[https://github.com/KamWithK/AnkiconnectAndroid][AnkiconnectAndroid]] 
5. Install [[https://github.com/anki-editor/anki-editor][Anki Editor]] if not installed.
6. If you just want to try or use the default settings. Please download the
   default template [[https://github.com/Eltaurus-Lt/Anki-Card-Templates][Memrise Templates (Lτ) v3.32.apkg]] and import it into anki
   then you are all done.

If you want to use different template,
1. Run ~paw-anki-configure-card-format~ to choose from default templates ~paw-anki-templates~, or configure deck, note type, filed-name, and filed-values one by one temporarily.
    Currently Supported field-value:
   - =word=: the word to learn
   - =exp=: the explanation of the word
   - =sound=: the sound file of the word
   - =note=: the note of the word
   - ~cloze_note~: the note of the word, word is clozed
   - ~cloze_note_exp_hint~: the note of the word, word is clozed, use exp as hint
   - =choices=: the choices of the word
   - =nil=: empty field
   - Other values: the value of the field, it must be a string
2. If you want to make it permanent, set ~paw-anki-deck~, ~paw-anki-note-type~,
   ~paw-anki-field-names~ and ~paw-anki-field-values~ manually in your config,
3. Configure ~paw-online-word-servers~, =(setq paw-online-word-servers '(anki))= to enable anki server, or =(setq paw-online-word-servers '(eudic anki))= to enable both eudic and anki servers.

PS:
All types of annotations (not all are tested) could be added into Anki. Either using ~paw-add-online-word~ (anywhere), or ~paw-anki-editor-push-note(s)~ (dashboard) ~paw-anki-editor-delete-note(s)~ (dashboard).


~paw-anki-editor-delete-note~: Delete note at point to Anki.

~paw-anki-editor-push-note~: Push note at point to Anki.

~paw-anki-editor-push-notes~: Push notes of marked-entries in dashboard to anki,
or push all anki notes in the same origin path (same file or same buffer). Same
file name under ~paw-annotation-search-paths~ is also considerred same origin
path.

~paw-anki-editor-delete-notes~: Delete anki notes of marked-entries in dashboard,
or delete all anki notes in the same origin path (same file or same buffer),
Same file name under ~paw-annotation-search-paths~ is also considerred same
origin path.

Other templates:
- [[https://forums.ankiweb.net/t/memrise-card-template-support-thread/34233/18][MemCloze.apkg]]
- Anime Mining: https://github.com/donkuri/lapis

The audio file is automatically downloaded and added to the anki note, if ~paw-anki-download-sound~ is t (default). The sound file download sequence are defined by ~paw-anki-download-sound-functions~.

** Configure Eudic Integration
1. Apply Authorization key on https://my.eudic.net/OpenAPI/Authorization, and fill it into ~paw-authorization-keys~ before adding online words.
2. Configure ~paw-online-word-servers~, =(setq paw-online-word-servers '(eudic))= to enable Eudic server, or =(setq paw-online-word-servers '(eudic anki))= to enable both eudic and anki servers.

PS:
Only online words can be added into Eudic. Mainly via command ~paw-add-online-word~

** Configure EAF Integration
Use my forks which add paw support.
- https://github.com/chenyanming/eaf-browser: Able to highlight all words in the database in the page, click to search word and show in paw-view-note buffer.
- https://github.com/chenyanming/eaf-pdf-viewer: Able to search the word under cursor by pressing one key (no need to select the word) and translate the sourrounded sentence, show in paw-view-note buffer.

Add the following bindings to your configuration:
#+begin_src emacs-lisp
(eaf-bind-key insert_or_paw_view_note_in_eaf "`" eaf-browser-keybinding)
(eaf-bind-key paw_view_note_in_eaf "`" eaf-pdf-viewer-keybinding)
#+end_src

[[file:images/eaf.gif]]

** Configure SilverDict Integration
SilverDict is a web-based dictionary server that works on multiple platforms including Android (via Termux). Unlike GoldenDict, SilverDict provides dictionary lookup through a web interface.

1. Install and run SilverDict server on your device (see [[https://github.com/Crissium/SilverDict][SilverDict documentation]])
2. Configure paw to use SilverDict:
   #+begin_src emacs-lisp
   ;; Set SilverDict as the external dictionary function
   (setq paw-external-dictionary-function 'paw-silverdict-search-details)
   
   ;; Configure host and port (defaults shown below)
   (setq paw-silverdict-host "localhost")  ; or your server IP
   (setq paw-silverdict-port "2628")       ; default SilverDict port
   
   ;; Configure the query path for your dictionary group (optional)
   ;; Default is "/api/query/Default%20Group/"
   ;; Change this to match your SilverDict dictionary group
   (setq paw-silverdict-query-path "/api/query/Default%20Group/")
   ;; Examples:
   ;; (setq paw-silverdict-query-path "/api/query/Chinese/")
   ;; (setq paw-silverdict-query-path "/api/query/YourGroup/")
   #+end_src

3. For Android (Termux) setup, you may need to use ~127.0.0.1~ or ~localhost~ if running locally, or your device's IP address if running on another device on the same network.

** Browser support
*** Browser Extension
1. Firefox & Firefox Android https://addons.mozilla.org/en-US/firefox/addon/emacs-paw
2. Chrome: https://chromewebstore.google.com/detail/paw/ofhodjclfalelhgjbfmdddekoghamlge
3. Brave: Same as Chrome, but need to add ~@@||localhost^~ into ~Create custom filters section~ of ~brave://settings/shields/filters~ if you need paw-server features.
4. This browser extension enhances word interaction by underlining words on mouseover and capturing context when words are clicked. The captured information is sent to Emacs via org-protocol and displayed in the *paw-view-note* buffer.
5. Update the server config inside the config page of the extension, and make sure the port number (~paw-server-port~) matches, for example, http://localhost:5001
6. M-x ~paw-server~. Run the paw-server, so that all words can be highlighted on browser.
7. paw-server is optional, you don't need to run it, and still able to use the org-protocol feature. If you installed paw command line, you can run paw-server in several ways (see also [[https://github.com/chenyanming/paw_server][paw_server]] for standalone usage):

**Method 1: Emacs Integration (Original), same as M-x paw-server**
#+begin_src sh
paw run_server --database /home/damonchan/org/paw.sqlite --save-dir /tmp/ --port 5001 --wallabag-host https://example.com --wallabag-username username --wallabag-password password --wallabag-clientid clientid --wallabag-secret secret
#+end_src

**Method 2: Standalone Mode (Enhanced, Recommended for Production, run on command line directly)**
#+begin_src sh
# Using environment variables (recommended)
export PAW_DATABASE_PATH="/home/damonchan/org/paw.sqlite"
export PAW_SAVE_DIR="/tmp/"
export PAW_PORT="5001"
export PAW_SERVER_TYPE="production"  # or "flask"
export WALLABAG_HOST="https://example.com"
export WALLABAG_USERNAME="username"
export WALLABAG_PASSWORD="password"
export WALLABAG_CLIENTID="clientid"
export WALLABAG_SECRET="secret"

paw server
#+end_src

**Method 3: Python Server (Moved)**

The Python server functionality has been moved to a separate repository: [[https://github.com/chenyanming/paw_server][paw_server]]. Please refer to that repository for server installation and usage instructions.

The standalone mode offers enhanced stability, better error handling, environment variable support, and waitress support for better performance.

#+attr_org: :width 1000px
[[file:images/_20250112_161934screenshot.png]]


#+attr_org: :width 300px
[[file:images/_20250112_162205screenshot.png]]


#+attr_org: :width 100px
[[file:images/_20250112_162133screenshot.png]]

Check more on: https://github.com/chenyanming/paw_org_protocol


*** org-protocol
If you don't want to use extension or sometimes can not use, add the following bookmarklet in browser, paste the following code as URL:
#+begin_src js
javascript:(function(){
    var selection = window.getSelection().toString();
    if (selection.length > 0) {
        var url = encodeURIComponent(window.location.href);
        var title = encodeURIComponent(document.title || "[untitled page]");
        var body = encodeURIComponent(selection);
        var parent = window.getSelection().getRangeAt(0).commonAncestorContainer.parentNode;
        while (parent.nodeType !== Node.ELEMENT_NODE) {
            parent = parent.parentNode;
        }
        var p_tag_parent = parent;
        while (p_tag_parent.tagName !== undefined && p_tag_parent.tagName !== 'P') {
            p_tag_parent = p_tag_parent.parentNode;
        }
        if (p_tag_parent !== document) {
            parent = p_tag_parent;
        }
        var note = encodeURIComponent(parent.textContent || "");
        location.href = 'org-protocol://paw?template=w&url=' + url + '&title=' + title + '&note=' + note + '&body=' + body;
    }
}());
#+end_src
Select the word, and click the bookmark, the word will be shown in paw-view-note buffer.

Check more examples on js files in the root folder.

** Coding
You can show anything on ~*paw-view-note*~ buffer!

For example, the following snippet shows the gptel result to ~*paw-view-note*~ buffer by using ~paw-view-note~ and ~paw-new-entry~ functions, use edge-tts to say the response out, use go-translate to transalte the response, also user can further interact (add to database etc) with the result in ~*paw-view-note*~ buffer.
#+begin_src emacs-lisp
(defun gptel-quick (&optional query)
  "ASK AI with predefined prompts."
  (interactive)
  (require 'gptel)
  (let* ((selected-text (when (use-region-p)
                          (buffer-substring-no-properties (region-beginning) (region-end))))
         ;; (current-buffer-text (buffer-substring-no-properties (point-min) (point-max)))
         (additional-text (or selected-text ""))
         (prompt (completing-read "Ask AI: "
                                  '("Draft an outline"
                                    "Draft anything"
                                    "Draft an email"
                                    "Draft a journal entry"
                                    "Draft a meeting agenda"
                                    "Explain in 12 words or less"
                                    "Explain in 48 words or less"
                                    "Explain in 100 words or less"
                                    "Explain in 200 words or less"
                                    "Write anything"
                                    "Brainstorm ideas"
                                    "Translate it to Chinese"))))
    (when (string= prompt "") (user-error "A prompt is required."))
    (deactivate-mark)
    (setq gptel-last-prompt (format "%s. %s" prompt additional-text))
    (gptel-request (or query gptel-last-prompt)
      :system "You are an AI assistant that lives inside Emacs"
      :callback
      (lambda (response info)
        (if (not response)
            (message "gptel-quick failed with message: %s" (plist-get info :status))
          (with-current-buffer (get-buffer-create "*gptel-quick*")
            (let ((paw-say-word-p t) ;; say the response out
                  (lang (paw-check-language response)))
              (paw-view-note (paw-new-entry response
                                            :origin_type "gptel"
                                            :serverp 3
                                            :lang lang
                                            :context (format "Question: %s\nAnswer: %s" gptel-last-prompt response))
                             :buffer-name paw-view-note-buffer-name
                             :display-func 'switch-to-buffer))))))))
#+end_src

* Database Synchronization
I personally use [[https://syncthing.net/][Syncting]] to share the database between PC and Android. The
drawback is that, if the database is in used in any party, the synchronization
will stop. You can run ~paw-db-sync~ to close the connection with the database, or
run =paw= then =paw-quit=, or close Emacs directly before Synchronization.

* Some Demos (maybe old)

https://emacs-china.org/uploads/default/original/3X/2/b/2bc2d9fd996827097b13f751c327ad7141376f88.gif

https://emacs-china.org/uploads/default/original/3X/3/5/3544a2bf376d1f3b8f1fc86063af2975e4da42b4.gif

https://emacs-china.org/uploads/default/optimized/3X/b/8/b8d7ae2d68baae4fe7dcb6477998cb761e28165f_2_1234x1000.png

https://emacs-china.org/uploads/default/optimized/3X/b/b/bb28af2a398f8d33861002facc62a6f7782be3b7_2_1232x1000.png

https://emacs-china.org/uploads/default/original/3X/5/5/55c6991c0521c6a70dbbce844ce1fb650119dc1e.png

https://emacs-china.org/uploads/default/original/3X/9/7/971b92c62a837e0a2e053e0e01f02916b8ae465d.png

* User Discussions
https://emacs-china.org/t/paw-el-emacs-lingq/27331

https://t.me/emacs_paw

* References
1. LingQ: Learning a language by reading
2. Kindle Vocabulary Builder
3. org noter
4. Chatgpt
5. SDCV
6. go-translate
7. Eudic
8. 蒙哥阅读器
9. Anki
10. [[https://github.com/themoeway/yomitan][Yomitan]]
11. [[https://github.com/killergerbah/asbplayer/tree/main?tab=readme-ov-file][asbplayer]]
12. [[https://github.com/kha-white/mokuro][mokuro]]
13. [[https://github.com/ninja33/ODH][ODH]]
14. [[https://chromewebstore.google.com/detail/lulu-translate/djbfechcnkppbknmlhfcaoifgnicolin][LuLu Translate]]
15. [[https://chromewebstore.google.com/detail/immersive-translate-trans/bpoadfkcbjbfhfodiogcnhhhpibjhbnh][Immersive Translate]]
16. Denote
17. Notion

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

Contributors

chenyanming

920 commits

jiewawa

32 commits

Copilot

2 commits

chenyanming/paw

Emacs Annotation and Language Learning tool.

Emacs Lisp

171

954 commits

updated Aug 10, 2026

See the code

README

#+title: paw (point-and-write)

[[file:images/logo.jpg]]

Study for a life in Emacs.

~paw.el~ was created in 2021 as an annotation tool, but I was not used it a lot at that time. Recently I picked it up and dramatically changed its usage. Now it is a complete solution of making annotations and language learning tools, right inside Emacs.

paw relies on sqlite. All annotations are saved inside a database, which means it can be easily backup and you can read and make annotation right inside Emacs (PC/mobile) using same database.

paw is not just a dictionary tool. paw was created in mind that:
1. Query word with single mouse click, even no need to click.
2. Save and trace all known/unknown words and wordlist support, online or offline.
3. Integrate with other great open source tools, libraries, and dictionaries.
4. Integrate with external dictionary tools.
5. Support many languages.
6. Multi-Platform Support, including Mobile/e-link devices.
7. Use AI as assistant.

#+begin_quote
The standout feature of Paw is the ability to scan an entire buffer, tokenize all words, batch-query them, and filter them out according to user-provided tags, ultimately applying overlays alongside meanings to all discovered words. In essence, Paw proactively queries the dictionary on your behalf, making the highlighted word's meaning immediately available.

This means that you can simply hover your mouse over a word to view its definition, without having to click on it.
#+end_quote

This package is mainly used along with:
1. nov-mode
2. org-mode
3. markdown-mode
4. eaf-mode
5. eww-mode
6. wallabag-entry-mode
7. pdf-view-mode
8. elfeed-show-entry-mode
9. telega-webpage-mode
10. [[https://github.com/chenyanming/paw_org_protocol][Browser Support]]
11. Derived text-mode
12. Derived prog-mode

* Get started
** M-x ~paw-annotation-mode~ 
Modes that supported in ~paw-annotation-mode-supported-modes~ can enable
~paw-annotation-mode~.

See the doc of ~M-x describe-function paw-annotation-mode~

** M-x ~paw-annotation-live-mode~
~paw-annotation-live-mode~ is similar as ~paw-annotation-mode~

But it can be used on any buffer, less limitation, and less keybindings,
with auto refresh annotation overlays feature.

See the doc of ~M-x describe-function paw-annotation-live-mode~

* What can paw do?
** Reading and annotation
1. Open an epub file using nov.el, open an org/txt/md file, browse web with eww/eaf, read rss with elfeed, you name it.
2. Enable ~paw-annotation-mode~ (buffer will be turned into read-only if
   ~paw-annotation-read-only-enable~ is t to avoid accidental alternation)
3. Use ~paw~ add word/highlight/bookmark/todo/, for example, ~paw-add-word~,
   ~paw-add-highlight~... Please check M-x ~paw-add-*~ related commands for all type
   of supported annotations.
4. Annotations will be highlighted via overlay. Under the annotation, you can do
   various of operations. For example, to edit the annotation, under the
   annotation, press ~i~, ~paw-find-note~. It will create an temporary org file
   dedicated for this annotation, ~C-c C-i~ to insert annotation link as reflink,
   finally save by ~C-c C-c~, changes will be saved in the database respectively.
5. Under the annotation, run ~paw-change-annotation-note-type~ (~c~) or
   ~paw-change-note_type~ (~C~) to change the face of the overlay.
6. The most useful case is adding highlight by ~paw-add-highlight~, then change
   the highlight overlay by ~paw-change-annotation-note-type~. The default
   highlight overlay is defined in ~paw-annotation-default-highlight-type~, and
   running ~paw-change-annotation-note-type~ will remember the last highlight
   overlay. paw predefines some most used highlight styles that often appeared
   in other annotation tools, like marker or underline (press ~c1~, ~c2~, ~c3~, etc),
   but it is not limited to that, you can change to any face you want (press ~cf~)
7. Use ~paw-add-comment~ (~C-c i~ or ~i~ [evil] under ~paw-annotation-mode~) to
   quickly add a comment to the current thing (~paw-add-comment-thing~), if no
   comment is added, the annotation will be deleted after quitting the note
   buffer. ~paw-add-comment~ is actually a convenient wrapper of ~paw-add-highlight~
   and ~paw-find-note~.
   1. Inside ~*paw-view-note*~ buffer, you can press ~i~ to edit the Saved Meanings or Notes. Check ~paw-view-note-transient~ for more operations.
8. Call ~paw~, ~paw-list-annotations~, ~paw-list-all-annotations~ or
   ~paw-list-all-links~ to manage or jump to annotation location (One useful case
   is that make highlight or create bookmark on ~eww~, and jump back to the exact
   same annotation location simply pressing Enter)
9. Under the annotation, M-x ~paw-view-notes~, all notes under the same path will
   be shown, giving you an overview on all notes you've made for the same file.
   Or M-x ~paw-find-notes~ to update/save all notes under the same path into an
   org file under ~paw-note-dir~, and jump to the annotation location inside the
   org file.
10. ~paw-add-bookmark~ works great on eww-mode/eaf-mode (browser or pdf-viewer)
11. ~M-x paw-toggle-inline-annotations~, to show all annotations inline.

[[file:images/annatation.png]]

** Editing/Programming while Annotating
*** Method 1: M-x ~paw-annotation-live-mode~
Any buffer can enable paw-annotation-live-mode. After enabling it, you can add annotations with M-x paw-add-*. After file saved, annotations will be auto refreshed (location will be updated if possible).

~M-x paw-toggle-inline-annotations~, to show all annotations inline.


*** Method 2: M-x paw-annotation-mode
By default, the major-mode includes in ~paw-annotation-mode-supported-modes~ will
turn into read-only if ~paw-annotation-read-only-enable~ is t.

However, two special modes text-mode/prog-mode are added in
~paw-annotation-mode-supported-modes~. If the current buffer's major-mode is not
one of modes in ~paw-annotation-mode-supported-modes~ but derived from ~text-mode~
or ~prog-mode~. Enabling ~paw-annotation-mode~ will not alternate the read-only
status, in the mean time, it shows annotations made on the current buffer while
disable other paw-annotation-mode features (like mouse click to query, show
unknown words, show wordlists' words etc, which makes sense when Reading but not
Editing). This makes sure that we can continue to edit the buffer and use the
buffer's cooresponding keymaps while also able to add/show/manage annotations.

~M-x paw-toggle-inline-annotations~, to show all annotations inline.

[[file:images/programming.png]]

** Language Learning
1. Copy a text you want to learn to an org file or browse a page with eww/eaf etc.
2. Enable ~paw-annotation-mode~
3. Click/Select word/sentence with ~paw-view-note~, it will show you an
   informative buffer of the word/sentence. It has dictionary, translation,
   notes and also able to search by external browser.
4. Use ~paw-add-offline-word~ or ~paw-add-online-word~ to add a new word. For Online
   words, please check 
        #+html: <a href="#anki-integration">Anki Integration</a>
        #+html: <a href="#eudic-integration">Eudic Integration</a>
   All offline/online words appeared on any buffers that were enabled
   ~paw-annoation-mode~ will be highlighted, useful for language learners using
   the important method: Repetition.
5. For offline words, please setup ~paw-offline-studylist~ before using it. By
   default we have two offline studylists: =English Studylist= and =Japanese
   Studylist=.
6. You can also use ~paw-add-word~. Unlike offline/online word, the word added by
   ~paw-add-word~ is linked with an unique id, it is only highlighted at the
   location where we added it.
7. Under any annotation, click or press ~v~ to invoke ~paw-view-note~, a buffer
   with saved meanings, dictionary, translation, notes is shown.
8. Under any annotation, click or press ~S~ to invoke
   ~paw-change-word-learning-level~, select from level 1~5. 1~4 are controlled by
   ~paw-level-1-word-face~ to ~paw-level-4-word-face~ for online words,
   ~paw-level-1-offline-word-face~ to ~paw-level-4-offline-word-face~ for offline
   words, while 5 is considered as Known word, skipping adding overlay face
   (just hiding). You can change the word to level 5 while keep it hiding, but
   if you don't need it anymore, simply run =paw-delete-annotation= to delete it.
9. Click/Select word/sentence with ~paw-view-note-current-thing~,
   ~paw-view-note-next-thing~, ~paw-view-note-prev-thing~, it will do segmentation
   using [[https://github.com/ikawaha/kagome][kagome]] (Japanese), and [[https://github.com/skywind3000/ECDICT][ECDICT]] (English).
10. Check https://www.lingq.com/en/, you know more ideas how to learn a foreign
    language with ~paw.el~.
11. Run ~paw-export-notes-to-csv~, check the csv file under ~paw-csv-file~, import it
    to [[https://apps.ankiweb.net/][Anki]] for further studying.
12. Both ~paw-add-word~ and ~paw-add-online-word~ will capture the context sentence
    and save it into Notes field.
- ~M-x paw-toggle-inline-annotations~, to show all annotations inline (think about it as a similar feature - [[https://www.amazon.com/gp/help/customer/display.html?nodeId=201645250][kindle word wise]])
14. Check ~paw-annotation-transient~ for more operations.
15. To review all words in the current buffer, under any unknown/known word (the
    overlay), C-u M-x ~paw-view-notes~, all unknown/known words appeared in the
    current buffer will be shown, giving you an overview on all words appeared
    in the current buffer. Or C-u M-x ~paw-find-notes~ to save all words appeared
    in the current buffer into an org file under ~paw-note-dir~, and jump to the
    annotation location inside the org file.
16. Please notice: if use M-x ~paw-view-notes~ without C-u, all notes under the
    path the moment it was captured will be shown instead.

Tip: Find some interesting contents on LingQ, and browse using eww, enable
~paw-annotation-mode~, enjoy language studying!

[[file:images/learning.png]]

** Search a word/sentence inside Emacs
1. Select/Under a word/sentence
2. Run ~paw-view-note~ (no segmentation, good for word) or
   ~paw-view-note-current-thing~ (segmentation, good for sentence)
3. Further search with ~paw-view-note-in-dictionary~ or search with browser.

** Search a word/sentence with external dictionary
1. Select/Under a word/sentence
2. Run ~paw-view-note-in-dictionary~, currently support eudic/goldendict/silverdict/yomitan (configured by ~paw-dictionary-function~)
3. You can also use:
   - ~paw-mac-dictionary-search-details~ (can configure mac dictionary or eudic, by ~paw-mac-dictionary-program~)
   - ~paw-goldendict-search-details~ (by ~paw-goldendict-program~)
   - ~paw-silverdict-search-details~ (by ~paw-silverdict-host~ and ~paw-silverdict-port~)
   - ~paw-yomitan-search-details-firefox~ (configure ~paw-yomitan-firefox-id~ and yomitan extension on browser before use)
   - ~paw-yomitan-search-details-chrome~ (configure yomitan extension on browser before use)
   - ~paw-android-search-details~ (android)
   - ~paw-eudic-search-details~ (mac/android/windows, ~paw-eudic-android-program~)
   - ~paw-chatgpt-search-details~ (mac/android, ~paw-chatgpt-android-program~)
   - ~paw-moji-search-details~ (android, ~paw-moji-android-program~)

** Manage annotations
#+begin_src emacs-lisp
M-x paw
#+end_src

It will launch a dashboard of annotations based on the current path of the buffer or project-root (text-mode/prog-mode).

Overview all notes using ~paw-view-notes~ on the same path.
Demo:
#+attr_org: :width 500px
[[file:images/overview.png]]


Export notes to an org file and print out as pdf (using latex), use ~paw-find-notes~.

Demo:
#+attr_org: :width 500px
[[file:images/latex.png]]

* Installation
You should install the following Dependencies if you want to make use all the power of paw:

- Command line tools
  - [[https://github.com/Dushistov/sdcv][sdcv]] (external command line dictionary)
  - mpv (or other command line mp3 player)
  - [[https://github.com/goldendict/goldendict][goldendict]] (external dictionary)
  - [[https://github.com/Crissium/SilverDict][silverdict]] (external web-based dictionary, works on Android)
  - [[https://github.com/rany2/edge-tts/][edge-tts]] (pronunciation)
  - [[https://github.com/ikawaha/kagome][kagome]] (For Japanese sentence segmentation)

- python dependencies (install paw command line by ~pip install emacs-paw~ or one by one manually):
  - Python itself (3.10+, for mac 3.11+)
  - nltk
  - flask
  - flask-cors
  - requests
  - mecab-python3
  - unidic-lite
  - waitress (optional, for enhanced server performance)

- Language detection python dependencies:
  - paw (emacs-paw cli), [[https://github.com/pemistahl/lingua-py][lingua-py]], pycld2, or gcld3

- Emacs packages (Not all are needed, some are optional, but paw just supports them. Some needed packages will be installed along with paw):
  - [[https://github.com/lorniu/go-translate][go-translate]] (Needed, for online transalation)
  - [[https://github.com/karthink/gptel][gptel]] (Needed, for ai translation)
  - emacsql (Needed)
  - transient (Needed)
  - [[https://github.com/larstvei/Focus][focus]]
  - svg-lib
  - anki-eidtor
  - all-the-icons
  - nerd-icons
  - immersive-translate
  - ivy
  - consult
  - posframe
  - [[https://github.com/kisaragi-hiu/emacs-jieba][jieba]]
  - eldoc-box
  - evil
  - esxml
  - [[https://github.com/chenyanming/shrface][shrface]]
  - [[https://github.com/chenyanming/wallabag.el][wallabag]]
  - [[https://github.com/emacs-eaf/emacs-application-framework][eaf]]
  - [[https://github.com/manateelazycat/popweb][popweb]]
  - pdf-tools
  - elfeed
  - telega

- Offline Dictionary:
  - [[https://sourceforge.net/projects/stardict-4/][stardict]] dictionaries (Used by sdcv, you can download mine from [[https://github.com/chenyanming/sdcv_dictionaries][sdcv_dictionaries]])
  - [[https://github.com/skywind3000/ECDICT][ECDICT]] (Please go into the [[https://github.com/skywind3000/ECDICT/releases][page]] and download the ~ecdict-stardict-28.zip~, unzip as ~startdict.db~)
  - [[https://github.com/chenyanming/yomichan-jlpt-vocab][yomichan-jlpt-vocab]] (Please go into the page, clone the repo, and build the japanese.db by yourself, or download mine in [[https://github.com/chenyanming/paw_dictionaries][paw_dictionaries]])
  - text/csv dictionaries (I uploaded my dictionaries to [[https://github.com/chenyanming/paw_dictionaries][paw_dictionaries]], you can also easily convert the any Anki Deck into csv format and use them. Also, this project also provides some functions to download, check ~paw-util.el~)

- Other Dictionaries
  - [[https://github.com/yomidevs/yomitan][yomitan]] (external dictionary)


Five steps:
- Install Offline Dictionaries (See above)
- Install Python
#+begin_src sh 
brew install python # You can use pyenv or other tools to install python
#+end_src
- Install [[https://pypi.org/project/emacs-paw/][emacs-paw]] command line by the following command, check usage at [[https://github.com/chenyanming/paw_server][paw_server]]
#+begin_src sh
pip install emacs-paw
#+end_src

*Note*: The Python CLI tool and server components have been migrated to [[https://github.com/chenyanming/paw_server][paw_server]] for better organization and standalone usage.

- Please be patient... run the following command lines, you may need to adjust them based on your system, take mac for example:
#+begin_src sh
brew install sdcv
brew install mpv
pip install edge-tts
python -m nltk.downloader stopwords
python -m nltk.downloader punkt
python -m nltk.downloader punkt_tab
#+end_src
- For android install:
#+begin_src sh
pkg install tur-repo # https://github.com/termux-user-repository/tur
pkg install python3.10 # install python 3.10 (newer versions may not work at the time of writing)
#+end_src

- Finally, Install paw.el
#+begin_src emacs-lisp
(package! paw :recipe (:host github :repo "chenyanming/paw" :files ("*")))
#+end_src

* Configuration
** Configure paw.el
After installing the above Dependencies, you can configure paw like [[file:config.el][config.el]] (which I may update frequently based on my need). You should better copy to your own configurations and tweak it based on your need.

Some csv dictionaries can be found in [[https://github.com/chenyanming/paw_dictionaries][paw_dictionaries]], you can download them and change the location. You can also convert from [[https://ankiweb.net/shared/decks][Anki Decks]] or Make your own, it is just text based dictionaries.

You can also check the language specific configurations below:
- [[file:ENGLISH.org][English Configuration]]
- [[file:JAPANESE.org][Japanese Configuration]]
- [[file:CHINESE.org][Chinese Configuration]]

** configure sdcv (stardict)
#+begin_src emacs-lisp
(setq paw-sdcv-program "/opt/homebrew/bin/sdcv" )
(setq paw-sdcv-dictionary-data-dir (expand-file-name "dict" doom-private-dir))
;; (setq paw-sdcv-env-lang (getenv "LANG")) ;; may need this on linux and android
(setq paw-sdcv-dictionary-list    ;setup dictionary list for simple search
      '("懒虫简明英汉词典"
        "Collins Cobuild English Dictionary"
        "小学馆-日中词典"
        "日汉双解词典"
        "EJ-EDict" "JE-EDICT_Kanji"
        "日汉词典" "jmdict-ja-en" "KANJIDIC2" "新明解国語辞典"
        "小学館中日辞典EB版" "広辞苑 第六版" "EJ-GENE95"
        "jmdict-en-ja"
        "JCEDict" "EDICT"
        "JEDict" "ENAMDICT" "EJDic" "DrEye日汉词典" "DrEye4in1词典"))
#+end_src
** Keybindings
paw supports Emacs native keybindings, evil, and transient menu (?).

** Enable ~paw-annotation-mode~ automatically
You can add ~paw-annotation-mode~ to the corresponding hook, so that it can enable automatically after the corresponding mode is loaded:

#+begin_src emacs-lisp
(add-hook 'wallabag-entry-mode-hook #'paw-annotation-mode)
(add-hook 'nov-mode-hook #'paw-annotation-mode)
(add-hook 'elfeed-show-mode-hook #'paw-annotation-mode)
(add-hook 'eaf-mode-hook 'paw-annotation-mode)
(add-hook 'telega-webpage-mode-hook #'paw-annotation-mode)
#+end_src

Some modes like ~nov-mode~, ~wallabag-entry-mode~ and ~eww-mode~, adding above hook is not enough, you also need to add the following highlight functions ~:after~ the render function using ~advice-add~:
#+begin_src emacs-lisp
(when (bound-and-true-p paw-annotation-mode)
      (paw-clear-annotation-overlay)
      (paw-show-all-annotations)
      (if paw-annotation-show-wordlists-words-p
          (paw-focus-find-words :wordlist t))
      (if paw-annotation-show-unknown-words-p
          (paw-focus-find-words)))
#+end_src

For more examples, please check: https://github.com/chenyanming/shrface/blob/master/config.el

** One-Click or One-Key to query
By default, if ~paw-annotation-mode~ is enabled, you can =One-Click= to query the word. If you want to disable it:
#+begin_src emacs-lisp
(setq paw-view-note-click-enable nil) ;; Disable Left-Click One-Click to query feature
#+end_src

Or 
M-x ~paw-view-note-click-enable-toggle~ to toggle the =One-Click= feature on the fly.

You can also use ~paw-view-note-under-mouse~ to query the word under mouse, it is bound to ~`~ by default. Move the mouse and hover on the word to be queried, and press ~`~. I called it as ~One-Key~ to query.

+You may also use ~paw-view-note-click-directly~, which is bound to ~mouse-3~ (Right Click). This is not controlled by ~paw-view-note-click-enable~, it is also One-Click to query but using Right Click.+ -> I don't use it anymore.

Now,

Mouse-1 bound to ~paw-view-note-click~ (Click the word)
Mouse-2 bound to ~paw-view-note~ (After Mouse-1 drag a text then Mouse-2 for query the selected area)
Mouse-3 bound to ~paw-view-note-quit~ (Quit the view window)

** Sound engines
Paw includes multiple sound engines that can be used to download audio files. The available sound engines include:
- ~paw-say-word-cambridge~
- ~paw-say-word-oxford~
- ~paw-say-word-jpod101-alternate~
- ~paw-edge-tts-say-word~
- ~paw-youdao-say-word~
- ~paw-say-word-forvo~
- and more
By default, the sequence in which these sound engines are used is defined by ~paw-say-word-functions~.

The following configs control wheather say the word when you view by M-x ~paw-view-note~

#+begin_src emacs-lisp
(defcustom paw-say-word-p t
  "paw say word automatically"
  :group 'paw
  :type 'boolean)

(defcustom paw-say-word-supported-note-types '(word)
  "The note types will be say automatically."
  :group 'paw
  :type '(repeat (choice symbol)))
#+end_src

In dashboard header, it is possible to toggle the ~paw-say-word-p~ (Voice) on the fly.

** Audio player and volume control
Paw supports various audio players for pronunciation playback. The player program is automatically detected based on your system:

- macOS: ~afplay~ (with native ~--volume~ support)
- Other systems: ~mpv~, ~mplayer~, or ~mpg123~

You can configure the audio player and volume:

#+begin_src emacs-lisp
;; Audio player program (auto-detected by default)
(setq paw-player-program "/usr/bin/afplay")  ; or your preferred player

;; Volume control (0-100 range)
(setq paw-player-volume 50)  ; 50% volume
#+end_src

Volume support by player:
- ~mpv~: Uses ~--volume=N~ parameter
- ~mplayer~: Uses ~-volume N~ parameter
- ~afplay~ (macOS): Uses ~--volume N.N~ parameter (0.0-1.0 range)
- ~mpg123~: Uses ~-g N~ parameter for gain control
- ~aplayer~: No volume support, falls back to normal playback

** Icons/Buttons
Paw support all major emacs icons packages, you can choose one of them. 
- svg-icon
- nerd-icons (recommended if you use nerd fonts)
- all-the-icons
- pbm (image icons, recommended on android)
- text (if all options are nil, fallback to pure text as icons)

The current checking sequence is svg -> pbm -> all-the-icons -> nerd-icons -> text. The first ~t~ option will be used first.

To enable pbm on android while use nerd-icon on non-android, we can configure like so:
#+begin_src emacs-lisp
;; svg icons
(setq paw-svg-enable nil)
;; Use pbm icons/buttons on android
(setq paw-pbm-enable (if (eq system-type 'android) t))
;; all the icons icon
(setq paw-all-the-icons-icon-enable nil)
;; all the icons button 
(setq paw-all-the-icons-button-enable nil)
;; nerd icon/buttons
(setq paw-nerd-icons-icon-enable t)
#+end_src

** Configure Language Detection
Set ~paw-detect-language-p~ to t, paw will use emacs-paw python cli (to use others
tools check ~paw-detect-language-program~) to detect the language for more
accurate tts pronunciation and translation.

If you don't want to use language detection program, paw use simple ascii rate:
~paw-ascii-rate~ to detect the language, if the rate is greater than
~paw-ascii-rate~, then it is considered as English, otherwise use
~paw-detect-language-program~ to detect the language of the TEXT, if
~paw-detect-language-p~ is t, or return as ~paw-non-ascii-language~ if
~paw-detect-language-p~ is nil.

Setup ~paw-python-program~ if necessary, if the pip module is installed with
different python version, for android, set it to =python3.10=

Supported edge-tts voice:
- ~paw-tts-english-voice~
- ~paw-tts-zh-cn-voice~
- ~paw-tts-zh-tw-voice~
- ~paw-tts-japanese-voice~
- ~paw-tts-korean-voice~
- Other languages: ~paw-tts-multilingual-voice~
Welcome PRs to add more languages :)

** =*paw-view-note*= window configurations
If ~paw-view-note-window-auto-adjust~ is t (default), the window of
=*paw-view-note*= will be automatically adjusted. If the height of the window is
larger than the width, show it on the ~paw-view-note-vertical-position~, otherwise
show it on the ~paw-view-note-horizontal-position~. Also, the windows width/height
could be configured by ~paw-view-note-window-width~ and
~paw-view-note-window-height~.
** =*paw-view-note*= sections configurations
You can adjust the section order or remove the unwanted sections by configuring ~paw-view-note-sections~

The order of the sections is the order of the list.
Supported values are:
- "Dictionaries": The online dictionaries buttons
- "Search": The online search engine buttons
- "Context": The context around the word/annotation
- "Translation": The translation of the word/annotation
- "Saved Meanings": The Saved Meanings of the word/annotation
- "Meaning": The SDCV result of the word/annotation
- "Notes": The notes of the word/annotation
- "Anki": Special section for Anki

** Back to original buffer
Normally, when you run ~paw-view-note~, paw will switch to =*paw-view-note*= buffer. But there are some cases we want to stay at the original buffer, in this case:
- Set ~paw-view-note-back-to-original-buffer~ as t (Default)
- And add or remove the targeted major-mode into ~paw-view-note-back-to-original-buffer-supported-modes~.

** Configure Anki Integration
1. PC: Install Anki.
2. PC: Install AnkiConnect, add-on code: 2055492159.
3. Android: Install AnkiDroid from F-Driod (We need it has full media access
   right, so that Emacs can copy audio files to it. Instead of using AnkiConect
   to download the audio, paw will download and cache the audio in
   ~paw-tts-cache-dir~ after the voice is pronounced.).
4. Android: Install [[https://github.com/KamWithK/AnkiconnectAndroid][AnkiconnectAndroid]] 
5. Install [[https://github.com/anki-editor/anki-editor][Anki Editor]] if not installed.
6. If you just want to try or use the default settings. Please download the
   default template [[https://github.com/Eltaurus-Lt/Anki-Card-Templates][Memrise Templates (Lτ) v3.32.apkg]] and import it into anki
   then you are all done.

If you want to use different template,
1. Run ~paw-anki-configure-card-format~ to choose from default templates ~paw-anki-templates~, or configure deck, note type, filed-name, and filed-values one by one temporarily.
    Currently Supported field-value:
   - =word=: the word to learn
   - =exp=: the explanation of the word
   - =sound=: the sound file of the word
   - =note=: the note of the word
   - ~cloze_note~: the note of the word, word is clozed
   - ~cloze_note_exp_hint~: the note of the word, word is clozed, use exp as hint
   - =choices=: the choices of the word
   - =nil=: empty field
   - Other values: the value of the field, it must be a string
2. If you want to make it permanent, set ~paw-anki-deck~, ~paw-anki-note-type~,
   ~paw-anki-field-names~ and ~paw-anki-field-values~ manually in your config,
3. Configure ~paw-online-word-servers~, =(setq paw-online-word-servers '(anki))= to enable anki server, or =(setq paw-online-word-servers '(eudic anki))= to enable both eudic and anki servers.

PS:
All types of annotations (not all are tested) could be added into Anki. Either using ~paw-add-online-word~ (anywhere), or ~paw-anki-editor-push-note(s)~ (dashboard) ~paw-anki-editor-delete-note(s)~ (dashboard).


~paw-anki-editor-delete-note~: Delete note at point to Anki.

~paw-anki-editor-push-note~: Push note at point to Anki.

~paw-anki-editor-push-notes~: Push notes of marked-entries in dashboard to anki,
or push all anki notes in the same origin path (same file or same buffer). Same
file name under ~paw-annotation-search-paths~ is also considerred same origin
path.

~paw-anki-editor-delete-notes~: Delete anki notes of marked-entries in dashboard,
or delete all anki notes in the same origin path (same file or same buffer),
Same file name under ~paw-annotation-search-paths~ is also considerred same
origin path.

Other templates:
- [[https://forums.ankiweb.net/t/memrise-card-template-support-thread/34233/18][MemCloze.apkg]]
- Anime Mining: https://github.com/donkuri/lapis

The audio file is automatically downloaded and added to the anki note, if ~paw-anki-download-sound~ is t (default). The sound file download sequence are defined by ~paw-anki-download-sound-functions~.

** Configure Eudic Integration
1. Apply Authorization key on https://my.eudic.net/OpenAPI/Authorization, and fill it into ~paw-authorization-keys~ before adding online words.
2. Configure ~paw-online-word-servers~, =(setq paw-online-word-servers '(eudic))= to enable Eudic server, or =(setq paw-online-word-servers '(eudic anki))= to enable both eudic and anki servers.

PS:
Only online words can be added into Eudic. Mainly via command ~paw-add-online-word~

** Configure EAF Integration
Use my forks which add paw support.
- https://github.com/chenyanming/eaf-browser: Able to highlight all words in the database in the page, click to search word and show in paw-view-note buffer.
- https://github.com/chenyanming/eaf-pdf-viewer: Able to search the word under cursor by pressing one key (no need to select the word) and translate the sourrounded sentence, show in paw-view-note buffer.

Add the following bindings to your configuration:
#+begin_src emacs-lisp
(eaf-bind-key insert_or_paw_view_note_in_eaf "`" eaf-browser-keybinding)
(eaf-bind-key paw_view_note_in_eaf "`" eaf-pdf-viewer-keybinding)
#+end_src

[[file:images/eaf.gif]]

** Configure SilverDict Integration
SilverDict is a web-based dictionary server that works on multiple platforms including Android (via Termux). Unlike GoldenDict, SilverDict provides dictionary lookup through a web interface.

1. Install and run SilverDict server on your device (see [[https://github.com/Crissium/SilverDict][SilverDict documentation]])
2. Configure paw to use SilverDict:
   #+begin_src emacs-lisp
   ;; Set SilverDict as the external dictionary function
   (setq paw-external-dictionary-function 'paw-silverdict-search-details)
   
   ;; Configure host and port (defaults shown below)
   (setq paw-silverdict-host "localhost")  ; or your server IP
   (setq paw-silverdict-port "2628")       ; default SilverDict port
   
   ;; Configure the query path for your dictionary group (optional)
   ;; Default is "/api/query/Default%20Group/"
   ;; Change this to match your SilverDict dictionary group
   (setq paw-silverdict-query-path "/api/query/Default%20Group/")
   ;; Examples:
   ;; (setq paw-silverdict-query-path "/api/query/Chinese/")
   ;; (setq paw-silverdict-query-path "/api/query/YourGroup/")
   #+end_src

3. For Android (Termux) setup, you may need to use ~127.0.0.1~ or ~localhost~ if running locally, or your device's IP address if running on another device on the same network.

** Browser support
*** Browser Extension
1. Firefox & Firefox Android https://addons.mozilla.org/en-US/firefox/addon/emacs-paw
2. Chrome: https://chromewebstore.google.com/detail/paw/ofhodjclfalelhgjbfmdddekoghamlge
3. Brave: Same as Chrome, but need to add ~@@||localhost^~ into ~Create custom filters section~ of ~brave://settings/shields/filters~ if you need paw-server features.
4. This browser extension enhances word interaction by underlining words on mouseover and capturing context when words are clicked. The captured information is sent to Emacs via org-protocol and displayed in the *paw-view-note* buffer.
5. Update the server config inside the config page of the extension, and make sure the port number (~paw-server-port~) matches, for example, http://localhost:5001
6. M-x ~paw-server~. Run the paw-server, so that all words can be highlighted on browser.
7. paw-server is optional, you don't need to run it, and still able to use the org-protocol feature. If you installed paw command line, you can run paw-server in several ways (see also [[https://github.com/chenyanming/paw_server][paw_server]] for standalone usage):

**Method 1: Emacs Integration (Original), same as M-x paw-server**
#+begin_src sh
paw run_server --database /home/damonchan/org/paw.sqlite --save-dir /tmp/ --port 5001 --wallabag-host https://example.com --wallabag-username username --wallabag-password password --wallabag-clientid clientid --wallabag-secret secret
#+end_src

**Method 2: Standalone Mode (Enhanced, Recommended for Production, run on command line directly)**
#+begin_src sh
# Using environment variables (recommended)
export PAW_DATABASE_PATH="/home/damonchan/org/paw.sqlite"
export PAW_SAVE_DIR="/tmp/"
export PAW_PORT="5001"
export PAW_SERVER_TYPE="production"  # or "flask"
export WALLABAG_HOST="https://example.com"
export WALLABAG_USERNAME="username"
export WALLABAG_PASSWORD="password"
export WALLABAG_CLIENTID="clientid"
export WALLABAG_SECRET="secret"

paw server
#+end_src

**Method 3: Python Server (Moved)**

The Python server functionality has been moved to a separate repository: [[https://github.com/chenyanming/paw_server][paw_server]]. Please refer to that repository for server installation and usage instructions.

The standalone mode offers enhanced stability, better error handling, environment variable support, and waitress support for better performance.

#+attr_org: :width 1000px
[[file:images/_20250112_161934screenshot.png]]


#+attr_org: :width 300px
[[file:images/_20250112_162205screenshot.png]]


#+attr_org: :width 100px
[[file:images/_20250112_162133screenshot.png]]

Check more on: https://github.com/chenyanming/paw_org_protocol


*** org-protocol
If you don't want to use extension or sometimes can not use, add the following bookmarklet in browser, paste the following code as URL:
#+begin_src js
javascript:(function(){
    var selection = window.getSelection().toString();
    if (selection.length > 0) {
        var url = encodeURIComponent(window.location.href);
        var title = encodeURIComponent(document.title || "[untitled page]");
        var body = encodeURIComponent(selection);
        var parent = window.getSelection().getRangeAt(0).commonAncestorContainer.parentNode;
        while (parent.nodeType !== Node.ELEMENT_NODE) {
            parent = parent.parentNode;
        }
        var p_tag_parent = parent;
        while (p_tag_parent.tagName !== undefined && p_tag_parent.tagName !== 'P') {
            p_tag_parent = p_tag_parent.parentNode;
        }
        if (p_tag_parent !== document) {
            parent = p_tag_parent;
        }
        var note = encodeURIComponent(parent.textContent || "");
        location.href = 'org-protocol://paw?template=w&url=' + url + '&title=' + title + '&note=' + note + '&body=' + body;
    }
}());
#+end_src
Select the word, and click the bookmark, the word will be shown in paw-view-note buffer.

Check more examples on js files in the root folder.

** Coding
You can show anything on ~*paw-view-note*~ buffer!

For example, the following snippet shows the gptel result to ~*paw-view-note*~ buffer by using ~paw-view-note~ and ~paw-new-entry~ functions, use edge-tts to say the response out, use go-translate to transalte the response, also user can further interact (add to database etc) with the result in ~*paw-view-note*~ buffer.
#+begin_src emacs-lisp
(defun gptel-quick (&optional query)
  "ASK AI with predefined prompts."
  (interactive)
  (require 'gptel)
  (let* ((selected-text (when (use-region-p)
                          (buffer-substring-no-properties (region-beginning) (region-end))))
         ;; (current-buffer-text (buffer-substring-no-properties (point-min) (point-max)))
         (additional-text (or selected-text ""))
         (prompt (completing-read "Ask AI: "
                                  '("Draft an outline"
                                    "Draft anything"
                                    "Draft an email"
                                    "Draft a journal entry"
                                    "Draft a meeting agenda"
                                    "Explain in 12 words or less"
                                    "Explain in 48 words or less"
                                    "Explain in 100 words or less"
                                    "Explain in 200 words or less"
                                    "Write anything"
                                    "Brainstorm ideas"
                                    "Translate it to Chinese"))))
    (when (string= prompt "") (user-error "A prompt is required."))
    (deactivate-mark)
    (setq gptel-last-prompt (format "%s. %s" prompt additional-text))
    (gptel-request (or query gptel-last-prompt)
      :system "You are an AI assistant that lives inside Emacs"
      :callback
      (lambda (response info)
        (if (not response)
            (message "gptel-quick failed with message: %s" (plist-get info :status))
          (with-current-buffer (get-buffer-create "*gptel-quick*")
            (let ((paw-say-word-p t) ;; say the response out
                  (lang (paw-check-language response)))
              (paw-view-note (paw-new-entry response
                                            :origin_type "gptel"
                                            :serverp 3
                                            :lang lang
                                            :context (format "Question: %s\nAnswer: %s" gptel-last-prompt response))
                             :buffer-name paw-view-note-buffer-name
                             :display-func 'switch-to-buffer))))))))
#+end_src

* Database Synchronization
I personally use [[https://syncthing.net/][Syncting]] to share the database between PC and Android. The
drawback is that, if the database is in used in any party, the synchronization
will stop. You can run ~paw-db-sync~ to close the connection with the database, or
run =paw= then =paw-quit=, or close Emacs directly before Synchronization.

* Some Demos (maybe old)

https://emacs-china.org/uploads/default/original/3X/2/b/2bc2d9fd996827097b13f751c327ad7141376f88.gif

https://emacs-china.org/uploads/default/original/3X/3/5/3544a2bf376d1f3b8f1fc86063af2975e4da42b4.gif

https://emacs-china.org/uploads/default/optimized/3X/b/8/b8d7ae2d68baae4fe7dcb6477998cb761e28165f_2_1234x1000.png

https://emacs-china.org/uploads/default/optimized/3X/b/b/bb28af2a398f8d33861002facc62a6f7782be3b7_2_1232x1000.png

https://emacs-china.org/uploads/default/original/3X/5/5/55c6991c0521c6a70dbbce844ce1fb650119dc1e.png

https://emacs-china.org/uploads/default/original/3X/9/7/971b92c62a837e0a2e053e0e01f02916b8ae465d.png

* User Discussions
https://emacs-china.org/t/paw-el-emacs-lingq/27331

https://t.me/emacs_paw

* References
1. LingQ: Learning a language by reading
2. Kindle Vocabulary Builder
3. org noter
4. Chatgpt
5. SDCV
6. go-translate
7. Eudic
8. 蒙哥阅读器
9. Anki
10. [[https://github.com/themoeway/yomitan][Yomitan]]
11. [[https://github.com/killergerbah/asbplayer/tree/main?tab=readme-ov-file][asbplayer]]
12. [[https://github.com/kha-white/mokuro][mokuro]]
13. [[https://github.com/ninja33/ODH][ODH]]
14. [[https://chromewebstore.google.com/detail/lulu-translate/djbfechcnkppbknmlhfcaoifgnicolin][LuLu Translate]]
15. [[https://chromewebstore.google.com/detail/immersive-translate-trans/bpoadfkcbjbfhfodiogcnhhhpibjhbnh][Immersive Translate]]
16. Denote
17. Notion

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

Contributors

chenyanming

920 commits

jiewawa

32 commits

Copilot

2 commits

Languages

Emacs Lisp

94.8%

JavaScript

1.7%

Python

1.7%

AppleScript

1.2%