Closed hongyi-zhao closed 3 years ago
Hi, have you installed and activated company-mode? company-wordfreq
is actually just a backend for company-mode
.
Also you need to download word list as described in the documentation:
M-x company-wordfreq-download-list
Hi, have you installed and activated company-mode?
Really, the following commands do the trick:
M-x company-mode RET
M-x fk/company-wordfreq-mode RET
See the drop-down menu on the screenshot below, which is triggered by TAB
when the number of the input characters greater than or equal to 3:
M-x company-wordfreq-download-list
I've downloaded the dictionary file:
$ ls -l ~/.emacs.d/wordfreq-dicts/
total 392
-rw-rw-r-- 1 werner werner 400440 Jun 19 12:12 english.txt
But I want to know how to let the customized function, i.e., fk/company-wordfreq-mode
, automatically activate company-mode
on the corresponding buffer for me.
You can edit the minor mode directly:
(define-minor-mode fk/company-wordfreq-mode
"Suggest words by frequency."
:global nil
(if fk/company-wordfreq-mode
(progn
(company-mode) ;; <---- ACTIVATE COMPANY MODE
(setq-local company-backends-backup company-backends)
(setq-local company-transformers-backup company-transformers)
(setq-local company-backends '(company-wordfreq))
(setq-local company-transformers nil))
(setq-local company-backends company-backends-backup)
(setq-local company-transformers company-transformers-backup)))
or add a hook if you want to make it from outside:
(add-hook 'fk/company-wordfreq-mode-hook 'company-mode)
Also, I recommend these settings for company to see dropdown immediately after first character:
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 1)
I closed it by mistake.
Got it. Wonderful solution. Thank you very much.
You're welcome :+1:
I previously only know the following way to activate the company mode, which is invalid for this case due to the customized function works with a minor-mode:
(use-package company)
(add-hook 'after-init-hook 'global-company-mode)
Here, you've shown me the tip of the iceberg of Elisp's sophistication and power.
Other relevant questions/comments:
Can I trigger a similar dropdown menu for yasnippet with company for the snippet insertion, as describe by the issue I filed here?
For fine and modular complicated control, it seems that the global-*
options for many packages are not good/graceful, and even error methods.
Thank you again.
Actually I use global-company-mode
too and it works fine I don't know why it didn't work for you.
How do you want to see snippets exactly? Mixed with company-wordfreq? Mixed with code completion? or just show it manually?
If you want to see dropdown manually, just type some letters and run M-x company-yasnippet
.
Or you can see all the snippets related to your current buffer with M-x yas-describe-tables
.
How do you want to see snippets exactly? Mixed with company-wordfreq? Mixed with code completion? or just show it manually?
What about let code completion
, human language texts completion
, and snippet completion
work similarly?
If you want to see dropdown manually, just type some letters and run M-x company-yasnippet.
Which letters will trigger which snippets?
Can you try copy pasting these:
(defun fk/company-backend-with-yas (backend)
"Add ':with company-yasnippet' to the given company backend."
(if (and (listp backend) (member 'company-yasnippet backend))
backend
(append (if (consp backend)
backend
(list backend))
'(:with company-yasnippet))))
(defun fk/company-smart-snippets (fn command &optional arg &rest _)
"Do not show yasnippet candidates after dot."
;;Source:
;;https://www.reddit.com/r/emacs/comments/7dnbxl/how_to_temporally_filter_companymode_candidates/
(unless (when (and (equal command 'prefix) (> (point) 0))
(let* ((prefix (company-grab-symbol))
(point-before-prefix (if (> (- (point) (length prefix) 1) 0)
(- (point) (length prefix) 1)
1))
(char (buffer-substring-no-properties point-before-prefix (1+ point-before-prefix))))
(string= char ".")))
(funcall fn command arg)))
;; TODO: maybe show snippets at first?
(defun fk/company-enable-snippets ()
"Enable snippet suggestions in company by adding ':with
company-yasnippet' to all company backends."
(interactive)
(setq company-backends (mapcar 'fk/company-backend-with-yas company-backends))
(advice-add 'company-yasnippet :around 'fk/company-smart-snippets))
(fk/company-enable-snippets) ;; <------- ACTIVATE SNIPPET COMPLETION
Based on your comments above, I tried to test with the following code snippet:
(use-package company)
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 1)
(use-package company-wordfreq
:straight (:host github :repo "johannes-mueller/company-wordfreq.el")
:commands my/company-wordfreq-mode
:custom
(ispell-local-dictionary "english")
:config
(define-minor-mode my/company-wordfreq-mode
"Suggest words by frequency."
:global nil
(if my/company-wordfreq-mode
(progn
;https://github.com/KaratasFurkan/.emacs.d/issues/1#issuecomment-864426970
(company-mode) ;; <---- ACTIVATE COMPANY MODE
(setq-local company-backends-backup company-backends)
(setq-local company-transformers-backup company-transformers)
(setq-local company-backends '(company-wordfreq))
(setq-local company-transformers nil))
(setq-local company-backends company-backends-backup)
(setq-local company-transformers company-transformers-backup))))
(add-hook 'latex-mode-hook 'my/company-wordfreq-mode)
(use-package yasnippet)
(defun my/company-backend-with-yas (backend)
"Add ':with company-yasnippet' to the given company backend."
(if (and (listp backend) (member 'company-yasnippet backend))
backend
(append (if (consp backend)
backend
(list backend))
'(:with company-yasnippet))))
(defun my/company-smart-snippets (fn command &optional arg &rest _)
"Do not show yasnippet candidates after dot."
;;Source:
;;https://www.reddit.com/r/emacs/comments/7dnbxl/how_to_temporally_filter_companymode_candidates/
(unless (when (and (equal command 'prefix) (> (point) 0))
(let* ((prefix (company-grab-symbol))
(point-before-prefix (if (> (- (point) (length prefix) 1) 0)
(- (point) (length prefix) 1)
1))
(char (buffer-substring-no-properties point-before-prefix (1+ point-before-prefix))))
(string= char ".")))
(funcall fn command arg)))
;; TODO: maybe show snippets at first?
(defun my/company-enable-snippets ()
"Enable snippet suggestions in company by adding ':with
company-yasnippet' to all company backends."
(interactive)
(setq company-backends (mapcar 'my/company-backend-with-yas company-backends))
(advice-add 'company-yasnippet :around 'my/company-smart-snippets))
(my/company-enable-snippets) ;; <------- ACTIVATE SNIPPET COMPLETION
I noticed the following problems:
my/company-wordfreq-mode
will be activated, but I still must first run the following command in order to activate the snippets completion:
M-x my/company-enable-snippets RET
my/company-enable-snippets
depends on my/company-wordfreq-mode
, i.e., the second command must be activated first, otherwise, the first won't work at all.my/company-wordfreq-mode
activated, the completion results for you
will be as follows:Subsequently, I run M-x my/company-enable-snippets RET
, now, the completion results for you
will be as follows:
I don't know if these are the expected results.
auctex
, eglot
, texlab
, and company
with the following configuration, which I've described here and here:;;; Using AUCTEX from the local Git Repo without installation through straight.
(straight-use-package
`(auctex :type git :host nil :repo "https://git.savannah.gnu.org/git/auctex.git"
:pre-build ,(pcase system-type
(`berkeley-unix '("gmake"))
(_ '(
`("bash" "-c" "cd" ,(straight--repos-dir "auctex"))
("./autogen.sh")
("./configure" "--without-texmf-dir" "--with-lispdir=.")
("make")
)))))
(setq TeX-data-directory (straight--repos-dir "auctex")
TeX-lisp-directory TeX-data-directory)
; Or set the following variable via custom-set-variables in the opened buffer by the following command.
; M-x describe-variable RET preview-TeX-style-dir RET
;`(preview-TeX-style-dir ,(concat ".:" (straight--repos-dir "auctex") "latex:"))
(setq preview-TeX-style-dir (concat ".:" (straight--repos-dir "auctex") "latex:"))
(load "auctex.el" nil t t)
(load "preview-latex.el" nil t t)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
;;; eglot, company, and texlab
(use-package company)
(add-hook 'after-init-hook 'global-company-mode)
(use-package eglot)
;https://tam5917.hatenablog.com/entry/2021/04/01/014719
;; hook into AUCTeX
(add-hook 'TeX-mode-hook 'eglot-ensure)
;; ensure we don't use digestif server, which is far less than texlab on features and characteristics.
(delete (assoc '(tex-mode context-mode texinfo-mode bibtex-mode)
eglot-server-programs) eglot-server-programs)
;; ensure texlab is set as the server.
(add-to-list 'eglot-server-programs
'((latex-mode tex-mode context-mode texinfo-mode bibtex-mode) . (
"texlab"
)))
TAB
to select the first entry on the top.SPC
to pick up different candidates.wordfreq
writing helper for normal typesetting, and yasnippet
for the major mode specific snippets' insertion automatically. I mean, once I open a (La)TeX document, all the above-mentioned features will work OOTB, rather than requiring me to run the corresponding custom command/function to activate them manually.I don't know if these are the expected results.
Yes they are. my/company-enable-snippets
patches current company-backends
, since my/company-wordfreq-mode
changes company-backends
, you need to run my/company-enable-snippets
again. This may help:
(add-hook 'my/company-wordfreq-mode-hook 'my/company-enable-snippets)
For the keybindings, you can check the :bind
section of my company-mode settings: https://github.com/KaratasFurkan/.emacs.d#company
This may help:
Thank you for letting me know the hook chain based method. It does the trick by replacing the following command:
(my/company-enable-snippets)
with:
(add-hook 'my/company-wordfreq-mode-hook 'my/company-enable-snippets)
For the keybindings, you can check the :bind section of my company-mode settings: https://github.com/KaratasFurkan/.emacs.d#company
I noticed the following keyboard binding custom Settings:
("RET" . nil)
([return] . nil)
("C-w" . nil)
("TAB" . company-complete-selection)
("<tab>" . company-complete-selection)
("C-s" . company-complete-selection) ; Mostly to use during yasnippet expansion
("C-n" . company-select-next)
("C-p" . company-select-previous))
Why do you set the first three to nil
?
Because I don't want to select candidate with RET
(which is default, so I disabled the default binding). C-w
was conflicting with one of my other keybinding so I disabled it too.
Thank you for your explanation.
Based on the method described here, considering that the elements in the list are executed in the reverse order by add-hook
, I combined the two hooks into one as shown below:
(dolist (fn '(my/company-enable-snippets
my/company-wordfreq-mode))
(add-hook 'latex-mode-hook fn))
But I still can't figure out how to let the above configurations to work with latex command completion at the same time, as shown below for the configuration and the completion effect screenshot:
(straight-use-package
`(auctex :type git :host nil :repo "https://git.savannah.gnu.org/git/auctex.git"
:pre-build ,(pcase system-type
(`berkeley-unix '("gmake"))
(_ '(
`("bash" "-c" "cd" ,(straight--repos-dir "auctex"))
("./autogen.sh")
("./configure" "--without-texmf-dir" "--with-lispdir=.")
("make")
)))))
(setq TeX-data-directory (straight--repos-dir "auctex")
TeX-lisp-directory TeX-data-directory)
; Or set the following variable via custom-set-variables in the opened buffer by the following command.
; M-x describe-variable RET preview-TeX-style-dir RET
;`(preview-TeX-style-dir ,(concat ".:" (straight--repos-dir "auctex") "latex:"))
(setq preview-TeX-style-dir (concat ".:" (straight--repos-dir "auctex") "latex:"))
(load "auctex.el" nil t t)
(load "preview-latex.el" nil t t)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
(use-package eglot
:hook
(
(TeX-mode . eglot-ensure)
)
:config
(add-to-list 'eglot-server-programs
'((latex-mode tex-mode context-mode texinfo-mode bibtex-mode) . (
"texlab"
))))
When I put all the settings discussed above together as follows:
(straight-use-package
`(auctex :type git :host nil :repo "https://git.savannah.gnu.org/git/auctex.git"
:pre-build ,(pcase system-type
(`berkeley-unix '("gmake"))
(_ '(
`("bash" "-c" "cd" ,(straight--repos-dir "auctex"))
("./autogen.sh")
("./configure" "--without-texmf-dir" "--with-lispdir=.")
("make")
)))))
(setq TeX-data-directory (straight--repos-dir "auctex")
TeX-lisp-directory TeX-data-directory)
; Or set the following variable via custom-set-variables in the opened buffer by the following command.
; M-x describe-variable RET preview-TeX-style-dir RET
;`(preview-TeX-style-dir ,(concat ".:" (straight--repos-dir "auctex") "latex:"))
(setq preview-TeX-style-dir (concat ".:" (straight--repos-dir "auctex") "latex:"))
(load "auctex.el" nil t t)
(load "preview-latex.el" nil t t)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
(use-package eglot
:hook
(
(TeX-mode . eglot-ensure)
)
:config
(add-to-list 'eglot-server-programs
'((latex-mode tex-mode context-mode texinfo-mode bibtex-mode) . (
"texlab"
))))
(use-package company
:custom
(company-idle-delay 0)
(company-minimum-prefix-length 1)
(company-tooltip-align-annotations t)
(company-dabbrev-downcase nil)
(company-dabbrev-other-buffers t) ; search buffers with the same major mode
:bind
( :map company-active-map
("RET" . nil)
([return] . nil)
("C-w" . nil)
("TAB" . company-complete-selection)
("<tab>" . company-complete-selection)
("C-s" . company-complete-selection) ; Mostly to use during yasnippet expansion
("C-n" . company-select-next)
("C-p" . company-select-previous))
:hook
;(dashboard-after-initialize . global-company-mode)
; https://emacs.stackexchange.com/questions/39256/how-to-avail-of-hook-using-use-package
(after-init . global-company-mode)
:config
(add-to-list 'company-begin-commands 'backward-delete-char-untabify))
(use-package company-wordfreq
:straight (:host github :repo "johannes-mueller/company-wordfreq.el")
:commands my/company-wordfreq-mode
:custom
; This correspoding to the dictionary file:
;~/.emacs.d/wordfreq-dicts/english.txt
;$ curl -x socks5://127.0.0.1:18888 -O https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2018/en/en_full.txt
;$ awk '{print $1}' en_full.txt > my-en_full.txt
;$ diff my-en_full.txt english.txt
(ispell-local-dictionary "english")
;(ispell-local-dictionary "my-en_full")
:config
(define-minor-mode my/company-wordfreq-mode
"Suggest words by frequency."
:global nil
(if my/company-wordfreq-mode
(progn
(company-mode) ;; <---- ACTIVATE COMPANY MODE
(setq-local company-backends-backup company-backends)
(setq-local company-transformers-backup company-transformers)
(setq-local company-backends '(company-wordfreq))
(setq-local company-transformers nil))
(setq-local company-backends company-backends-backup)
(setq-local company-transformers company-transformers-backup))))
;; Show YASnippet snippets in company
(use-package yasnippet)
(defun my/company-backend-with-yas (backend)
"Add ':with company-yasnippet' to the given company backend."
(if (and (listp backend) (member 'company-yasnippet backend))
backend
(append (if (consp backend)
backend
(list backend))
'(:with company-yasnippet))))
(defun my/company-smart-snippets (fn command &optional arg &rest _)
"Do not show yasnippet candidates after dot."
;;Source:
;;https://www.reddit.com/r/emacs/comments/7dnbxl/how_to_temporally_filter_companymode_candidates/
(unless (when (and (equal command 'prefix) (> (point) 0))
(let* ((prefix (company-grab-symbol))
(point-before-prefix (if (> (- (point) (length prefix) 1) 0)
(- (point) (length prefix) 1)
1))
(char (buffer-substring-no-properties point-before-prefix (1+ point-before-prefix))))
(string= char ".")))
(funcall fn command arg)))
;; TODO: maybe show snippets at first?
(defun my/company-enable-snippets ()
"Enable snippet suggestions in company by adding ':with
company-yasnippet' to all company backends."
(interactive)
(setq company-backends (mapcar 'my/company-backend-with-yas company-backends))
(advice-add 'company-yasnippet :around 'my/company-smart-snippets))
;(my/company-enable-snippets) ;; <------- ACTIVATE SNIPPET COMPLETION
;(add-hook 'my/company-wordfreq-mode-hook 'my/company-enable-snippets)
;https://stackoverflow.com/questions/25778644/add-several-functions-as-hooks-in-emacs
;https://github.com/KaratasFurkan/.emacs.d/issues/1#issuecomment-864574670
(dolist (fn '(my/company-enable-snippets
my/company-wordfreq-mode))
(add-hook 'latex-mode-hook fn))
When I open some tex document, only the latex command completion are activated. If I run M-x my/company-wordfreq-mode
, then company-wordfreq
will be activated, but latex command completion will be disabled, as shown below:
Obviously, when I type latex commands, I don't want to have the normal human writing suggestions supplied by company-wordfreq
, and vice versa.
How to solve this problem?
Regards, HY
Another thing I want to know is whether company
supplies fuzzy match based completion for all above methods.
On Ubuntu 20.04, based on your wonderful code snippets here, I tried with the following
company-wordfreq
configuration:I test the above setting in
Emacs
with the following workflow:Then input some English words, but there is no drop-down menu which suggests me possible words as I type, as shown below:
Any hints for this problem will be highly appreciated.
Regards, HY