diff --git a/.github/workflows/activate.yml b/.github/workflows/activate.yml
new file mode 100644
index 0000000..8b2c4b2
--- /dev/null
+++ b/.github/workflows/activate.yml
@@ -0,0 +1,40 @@
+name: Activate
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ test:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ emacs-version:
+ - 28.1
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: jcs090218/setup-emacs@master
+ with:
+ version: ${{ matrix.emacs-version }}
+
+ - uses: actions/setup-node@v2
+ with:
+ node-version: '16'
+
+ - uses: emacs-eask/setup-eask@master
+ with:
+ version: 'snapshot'
+
+ - name: Run tests
+ run:
+ make activate
diff --git a/Eask b/Eask
index 541d73d..a05134b 100644
--- a/Eask
+++ b/Eask
@@ -1,6 +1,6 @@
(package "lsp-grammarly"
- "0.2.2"
- "LSP Clients for Grammarly ")
+ "0.3.0"
+ "LSP Clients for Grammarly")
(package-file "lsp-grammarly.el")
@@ -14,4 +14,7 @@
(depends-on "s")
(depends-on "ht")
+(development
+ (depends-on "markdown-mode"))
+
(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432
diff --git a/Makefile b/Makefile
index c9b20af..5e6bc22 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,9 @@ SHELL := /usr/bin/env bash
EMACS ?= emacs
EASK ?= eask
-TEST-FILES := $(shell ls test/lsp-grammarly-*.el)
-
.PHONY: clean checkdoc lint package install compile test
-ci: clean package install compile
+ci: clean package install compile checkdoc lint
package:
@echo "Packaging..."
@@ -23,7 +21,19 @@ compile:
test:
@echo "Testing..."
- $(EASK) exec ert-runner -L . $(LOAD-TEST-FILES) -t '!no-win' -t '!org'
+ $(EASK) ert ./test/*.el
+
+checkdoc:
+ @echo "Run checkdoc..."
+ $(EASK) checkdoc
+
+lint:
+ @echo "Run package-lint..."
+ $(EASK) lint
clean:
rm -rf .eask *.elc
+
+activate:
+ $(EASK) install --dev
+ $(EASK) load ./test/activate.el
diff --git a/README.md b/README.md
index 94f215a..08c7dfc 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,9 @@
# lsp-grammarly
[![CI](https://github.com/emacs-grammarly/lsp-grammarly/actions/workflows/test.yml/badge.svg)](https://github.com/emacs-grammarly/lsp-grammarly/actions/workflows/test.yml)
+[![Activate](https://github.com/emacs-grammarly/lsp-grammarly/actions/workflows/activate.yml/badge.svg)](https://github.com/emacs-grammarly/lsp-grammarly/actions/workflows/activate.yml)
-`lsp-mode` client leveraging [unofficial-grammarly-language-server](https://github.com/emacs-grammarly/unofficial-grammarly-language-server).
+`lsp-mode` client leveraging [grammarly-language-server](https://github.com/emacs-grammarly/grammarly-language-server).
@@ -18,10 +19,6 @@
- [📇 Commands](#📇-commands)
- [🔧 Configuration](#🔧-configuration)
- [📝 Roadmap](#📝-roadmap)
- - [💸 Using a Paid Grammarly Account](#💸-using-a-paid-grammarly-account)
- - [🔍 Method 1: Login with VSCode (easier)](#🔍-method-1-login-with-vscode-easier)
- - [🔍 Method 2: Login with Emacs (a bit complicated)](#🔍-method-2-login-with-emacs-a-bit-complicated)
- - [Authentication from Grammarly website](#authentication-from-grammarly-website)
- [Contribute](#contribute)
@@ -38,6 +35,9 @@
## 📇 Commands
+> ⚠️ We are moving to the newer grammarly-language-server that uses the official
+> API. Some features are disabled for now, but we will later add them back.
+
List of commands interact with `language server` and `Grammarly.com`.
| Commands | Description |
@@ -51,16 +51,42 @@ List of commands interact with `language server` and `Grammarly.com`.
## 🔧 Configuration
`lsp-grammarly` supports following configuration. Each configuration is described in
-detail in [Grammarly Settings](https://github.com/emacs-grammarly/unofficial-grammarly-language-server#extension-settings).
-
-* `grammarly.autoActivate` via `lsp-grammarly-auto-activate`
-* `grammarly.audience` via `lsp-grammarly-audience`
-* `grammarly.dialect` via `lsp-grammarly-dialect`
-* `grammarly.domain` via `lsp-grammarly-domain`
-* `grammarly.emotions` via `lsp-grammarly-emotions`
-* `grammarly.goals` via `lsp-grammarly-goals`
-* `grammarly.userWords` via `lsp-grammarly-user-words`
-* `grammarly.overrides` via `lsp-grammarly-override`
+detail in [Grammarly Extension Settings](https://github.com/emacs-grammarly/grammarly-language-server/blob/main/extension/package.json).
+
+* `grammarly.patterns` via `lsp-grammarly-patterns`
+* `grammarly.selectors` via `lsp-grammarly-selectors`
+* `grammarly.config.documentDialect` via `lsp-grammarly-dialect`
+* `grammarly.config.documentDomain` via `lsp-grammarly-domain`
+* `grammarly.config.suggestions.ConjunctionAtStartOfSentence` via `lsp-grammarly-suggestions-conjunction-at-start-of-sentence`
+* `grammarly.config.suggestions.Fluency` via `lsp-grammarly-suggestions-fluency`
+* `grammarly.config.suggestions.InformalPronounsAcademic` via `lsp-grammarly-suggestions-informal-pronouns-academic`
+* `grammarly.config.suggestions.MissingSpaces` via `lsp-grammarly-suggestions-missing-spaces`
+* `grammarly.config.suggestions.NounStrings` via `lsp-grammarly-suggestions-noun-strings`
+* `grammarly.config.suggestions.NumbersBeginningSentences` via `lsp-grammarly-suggestions-numbers-beginning-sentences`
+* `grammarly.config.suggestions.NumbersZeroThroughTen` via `lsp-grammarly-suggestions-numbers-zero-through-ten`
+* `grammarly.config.suggestions.OxfordComma` via `lsp-grammarly-suggestions-oxford-comma`
+* `grammarly.config.suggestions.PassiveVoice` via `lsp-grammarly-suggestions-passive-voice`
+* `grammarly.config.suggestions.PersonFirstLanguage` via `lsp-grammarly-suggestions-person-first-language`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageAgeRelated` via `lsp-grammarly-suggestions-possibly-biased-language-age-related`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageDisabilityRelated` via `lsp-grammarly-suggestions-possibly-biased-language-disability-related`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageFamilyRelated` via `lsp-grammarly-suggestions-possibly-biased-language-family-related`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageGenderRelated` via `lsp-grammarly-suggestions-possibly-biased-language-gender-related`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageHumanRights` via `lsp-grammarly-suggestions-possibly-biased-language-human-rights`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageHumanRightsRelated` via `lsp-grammarly-suggestions-possibly-biased-language-human-rights-related`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageLgbtqiaRelated` via `lsp-grammarly-suggestions-possibly-biased-language-lgbtqia-related`
+* `grammarly.config.suggestions.PossiblyBiasedLanguageRaceEthnicityRelated` via `lsp-grammarly-suggestions-possibly-biased-language-race-ethnicity-related`
+* `grammarly.config.suggestions.PossiblyPoliticallyIncorrectLanguage` via `lsp-grammarly-suggestions-possibly-politically-incorrect-language`
+* `grammarly.config.suggestions.PrepositionAtTheEndOfSentence` via `lsp-grammarly-suggestions-preposition-at-the-end-of-sentence`
+* `grammarly.config.suggestions.PunctuationWithQuotation` via `lsp-grammarly-suggestions-punctuation-with-quotation`
+* `grammarly.config.suggestions.ReadabilityFillerwords` via `lsp-grammarly-suggestions-readability-fillerwords`
+* `grammarly.config.suggestions.ReadabilityTransforms` via `lsp-grammarly-suggestions-readability-transforms`
+* `grammarly.config.suggestions.SentenceVariety` via `lsp-grammarly-suggestions-sentence-variety`
+* `grammarly.config.suggestions.SpacesSurroundingSlash` via `lsp-grammarly-suggestions-spaces-surrounding-slash`
+* `grammarly.config.suggestions.SplitInfinitive` via `lsp-grammarly-suggestions-split-infinitive`
+* `grammarly.config.suggestions.StylisticFragments` via `lsp-grammarly-suggestions-stylistic-fragments`
+* `grammarly.config.suggestions.UnnecessaryEllipses` via `lsp-grammarly-suggestions-unnecessary-ellipses`
+* `grammarly.config.suggestions.Variety` via `lsp-grammarly-suggestions-variety`
+* `grammarly.config.suggestions.Vocabulary` via `lsp-grammarly-suggestions-vocabulary`
## 📝 Roadmap
@@ -68,66 +94,6 @@ List of todos, but I have not got time to implement these features.
- [ ] Create another package that displays information from [Grammarly.com](https://www.grammarly.com/)
(To display useful information, `score`, `readability`, `word counts`, etc).
-- [ ] Implement command `Ignore Grammarly Issue`.
-- [ ] Implement `diagnostics` and `severity` for configuration.
-
-## 💸 Using a Paid Grammarly Account
-
-> ***NOTE:** To login, make sure you have package [keytar](https://github.com/emacs-grammarly/keytar)
-set up properly. See [keytar#installation](https://github.com/emacs-grammarly/keytar#installation)
-for setup instruction.*
-
-You can either login with [vscode-grammarly](https://marketplace.visualstudio.com/items?itemName=znck.grammarly)
-using VSCode or hit `M-x lsp-grammarly-login`. They both share the same credentials
-so you can login with either side.
-
-### 🔍 Method 1: Login with VSCode (easier)
-
-Install VSCode and install extension [vscode-grammarly](https://marketplace.visualstudio.com/items?itemName=znck.grammarly)
-from the extension panel.
-
-
-
-Then call command palette (default to Ctrl+Shift+p)
-and type to search `grammarly login` command.
-
-
-
-You should see [Grammarly Website](#authentication-from-grammarly-website) and
-login with your Grammarly account.
-
-
-
-🎉 Make sure you click on the button `Open Visual Studio Code`. Done! You
-can now close VSCode and go back to Emacs!
-
-### 🔍 Method 2: Login with Emacs (a bit complicated)
-
-Hit `M-x lsp-grammarly-login` and you should see the Grammarly's website pop out
-from your favorite browser. See below [screenshot](#authentication-from-grammarly-website),
-
-After login, click the button `Open URL:vscode`, If you have VSCode installed, then
-this button would be `Open Visual Studio Code` instead yet it doesn't matter.
-
-
-
-Then click F12 to open the DevTool window. You should able to see
-an URI like the following
-
-
-
-Copy and paste the URI back to Emacs and hit return.
-
-
-
-🎉 Done! Now you should be loggin!
-
-### Authentication from Grammarly website
-
-Login with your Grammarly account (This step does not require VSCode to be
-installed)!
-
-
## Contribute
diff --git a/lsp-grammarly.el b/lsp-grammarly.el
index a38e717..ab5ab17 100644
--- a/lsp-grammarly.el
+++ b/lsp-grammarly.el
@@ -6,7 +6,7 @@
;; Author: Shen, Jen-Chieh
;; Description: LSP Clients for Grammarly.
;; Keyword: lsp grammarly checker
-;; Version: 0.2.2
+;; Version: 0.3.0
;; Package-Requires: ((emacs "27.1") (lsp-mode "6.1") (grammarly "0.3.0") (request "0.3.0") (s "1.12.0") (ht "2.3"))
;; URL: https://github.com/emacs-grammarly/lsp-grammarly
@@ -41,9 +41,6 @@
(require 'ht)
(require 'json)
-(unless (require 'keytar nil t)
- (warn "`keytar' is required for login into Grammarly account"))
-
(defgroup lsp-grammarly nil
"Settings for the Grammarly Language Server.
@@ -67,9 +64,17 @@ This is only for development use."
:type 'list
:group 'lsp-grammarly)
-(defcustom lsp-grammarly-auto-activate t
- "Enable Grammarly service when a supported document is opened."
- :type 'boolean
+(defcustom lsp-grammarly-patterns
+ ["**/**.md"
+ "**/*.txt"]
+ "A glob pattern, like `*.{md,txt}` for file scheme."
+ :type 'vector
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-selectors
+ []
+ "Filter documents to be checked with Grammarly."
+ :type 'vector
:group 'lsp-grammarly)
(defcustom lsp-grammarly-audience "knowledgeable"
@@ -84,7 +89,8 @@ This is only for development use."
:type '(choice (const "american")
(const "australian")
(const "british")
- (const "canadian"))
+ (const "canadian")
+ (const "auto-text"))
:group 'lsp-grammarly)
(defcustom lsp-grammarly-domain "general"
@@ -92,42 +98,237 @@ This is only for development use."
:type '(choice (const "academic")
(const "business")
(const "general")
- (const "technical")
+ (const "mail")
(const "casual")
(const "creative"))
:group 'lsp-grammarly)
+(defcustom lsp-grammarly-suggestions-conjunction-at-start-of-sentence
+ nil
+ "Flags use of conjunctions such as 'but' and 'and' at the beginning of
+sentences."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-fluency
+ t
+ "Suggests ways to sound more natural and fluent."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-informal-pronouns-academic
+ nil
+ "Flags use of personal pronouns such as 'I' and 'you' in academic writing."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-missing-spaces
+ t
+ "Suggests adding missing spacing after a numeral when writing times."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-noun-strings
+ t
+ "Flags a series of nouns that modify a final noun."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-numbers-beginning-sentences
+ t
+ "Suggests spelling out numbers at the beginning of sentences."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-numbers-zero-through-ten
+ t
+ "Suggests spelling out numbers zero through ten."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-oxford-comma
+ nil
+ "Suggests adding the Oxford comma after the second-to-last item in a list of
+things."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-passive-voice
+ nil
+ "Flags use of passive voice."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-person-first-language
+ t
+ "Suggests using person-first language to refer respectfully to an individual
+with a disability."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-age-related
+ t
+ "Suggests alternatives to potentially biased language related to older adults."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-disability-related
+ t
+ "Suggests alternatives to potentially ableist language."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-family-related
+ t
+ "Suggests alternatives to potentially biased language related to parenting and
+family systems."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-gender-related
+ t
+ "Suggests alternatives to potentially gender-biased and non-inclusive phrasing."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-human-rights
+ t
+ "Suggests alternatives to language related to human slavery."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-human-rights-related
+ t
+ "Suggests alternatives to terms with origins in the institution of slavery."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-lgbtqia-related
+ t
+ "Flags LGBTQIA+-related terms that may be seen as biased, outdated, or
+disrespectful in some contexts."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-biased-language-race-ethnicity-related
+ t
+ "Suggests alternatives to potentially biased language related to race and
+ethnicity."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-possibly-politically-incorrect-language
+ t
+ "Suggests alternatives to language that may be considered politically
+incorrect."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-preposition-at-the-end-of-sentence
+ nil
+ "Flags use of prepositions such as 'with' and 'in' at the end of sentences."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-punctuation-with-quotation
+ t
+ "Suggests placing punctuation before closing quotation marks."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-readability-fillerwords
+ t
+ "Flags long, complicated sentences that could potentially confuse your reader."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-readability-transforms
+ t
+ "Suggests splitting long, complicated sentences that could potentially confuse
+your reader."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-sentence-variety
+ t
+ "Flags series of sentences that follow the same pattern."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-spaces-surrounding-slash
+ t
+ "Suggests removing extra spaces surrounding a slash."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-split-infinitive
+ t
+ "Suggests rewriting split infinitives so that an adverb doesn't come between
+'to' and the verb."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-stylistic-fragments
+ nil
+ "Suggests completing all incomplete sentences, including stylistic sentence
+fragments that may be intentional."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-unnecessary-ellipses
+ nil
+ "Flags unnecessary use of ellipses (...)."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-variety
+ t
+ "Suggests alternatives to words that occur frequently in the same paragraph."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defcustom lsp-grammarly-suggestions-vocabulary
+ t
+ "Suggests alternatives to bland and overused words such as 'good' and 'nice'."
+ :type 'boolean
+ :group 'lsp-grammarly)
+
+(defvar lsp-grammarly--show-debug-message nil
+ "Flag to see if we show debug messages.")
+
+;;
+;; (@* "Obsolete" )
+;;
+
+(defcustom lsp-grammarly-auto-activate t
+ "Enable Grammarly service when a supported document is opened."
+ :type 'boolean
+ :group 'lsp-grammarly)
+(make-obsolete-variable 'lsp-grammarly-auto-activate nil "0.2.2")
+
(defcustom lsp-grammarly-emotions '()
"Experimental: How do you want to sound."
:type 'list
:group 'lsp-grammarly)
+(make-obsolete-variable 'lsp-grammarly-emotions nil "0.3.0")
(defcustom lsp-grammarly-goals '()
"Experimental: What are you trying to do."
:type 'list
:group 'lsp-grammarly)
+(make-obsolete-variable 'lsp-grammarly-goal nil "0.3.0")
(defcustom lsp-grammarly-user-words '()
"A list of words as a local dictionary."
:type 'list
:group 'lsp-grammarly)
+(make-obsolete-variable 'lsp-grammarly-user-words nil "0.3.0")
(defcustom lsp-grammarly-override '()
"Per document override for audience, dialect, domain, emotions and goals."
:type 'list
:group 'lsp-grammarly)
-
-(defvar lsp-grammarly--show-debug-message nil
- "Flag to see if we show debug messages.")
-
-;;
-;; (@* "External" )
-;;
-
-(declare-function keytar--check "ext:keytar.el")
-(declare-function keytar-set-password "ext:keytar.el")
-(declare-function keytar-get-password "ext:keytar.el")
-(declare-function keytar-delete-password "ext:keytar.el")
+(make-obsolete-variable 'lsp-grammarly-override nil "0.3.0")
;;
;; (@* "Util" )
@@ -149,10 +350,6 @@ This is only for development use."
(dotimes (_ n) (insert (elt charset (random baseCount))))
(buffer-string))))
-(defun lsp-grammarly--json-encode (obj)
- "Wrap function `json-encode' to convert OBJ for keytar password."
- (s-replace "\"" "\\\"" (json-encode obj)))
-
(defun lsp-grammarly--json-read (string)
"Ensure read JSON STRING avoid bad string format."
(let ((output (or (ignore-errors (json-read-from-string string))
@@ -166,15 +363,6 @@ This is only for development use."
;; (@* "Login" )
;;
-(defconst lsp-grammarly--cookie-key "vscode-grammarly-cookie"
- "Key to store credentials.")
-
-(defconst lsp-grammarly--account "default"
- "Key that Grammarly LSP default to.")
-
-(defvar lsp-grammarly--password-string nil
- "Encrypted password in string.")
-
(defvar lsp-grammarly--password nil
"Encrypted password in alist.")
@@ -202,20 +390,12 @@ For argument CALLBACK, see object `lsp--client' description."
(defun lsp-grammarly--store-token (_workspace _uri _callback &rest _)
"Save the token once."
- (keytar-set-password
- lsp-grammarly--cookie-key lsp-grammarly--account lsp-grammarly--password-string))
+ )
(defun lsp-grammarly--init (&rest _)
"Get Grammarly API ready."
- (unless (lsp-grammarly-login-p)
- (let ((pass (ignore-errors
- (keytar-get-password lsp-grammarly--cookie-key lsp-grammarly--account))))
- (when pass
- (setq lsp-grammarly--password-string pass
- lsp-grammarly--password (lsp-grammarly--json-read pass))))
- (if (lsp-grammarly-login-p)
- (message "[INFO] Logged in as, %s" (lsp-grammarly--username))
- (message "[INFO] Visited as, anonymous"))))
+ ;; TODO: wait for the server side implementation
+ )
(defun lsp-grammarly--show-error (_workspace _uri callback &rest _)
"Show error from language server.
@@ -244,19 +424,45 @@ For argument CALLBACK, see object `lsp--client' description."
(list (lsp-package-path 'grammarly-ls) "--stdio")))
(lsp-register-custom-settings
- '(("grammarly.autoActivate" lsp-grammarly-auto-activate t)
- ("grammarly.audience" lsp-grammarly-audience)
- ("grammarly.dialect" lsp-grammarly-dialect)
- ("grammarly.domain" lsp-grammarly-domain)
- ("grammarly.emotions" lsp-grammarly-emotions)
- ("grammarly.goals" lsp-grammarly-goals)
- ("grammarly.userWords" lsp-grammarly-user-words)
- ("grammarly.overrides" lsp-grammarly-override)))
+ '(("grammarly.patterns" lsp-grammarly-patterns)
+ ("grammarly.selectors" lsp-grammarly-selectors)
+ ("grammarly.config.documentDialect" lsp-grammarly-dialect)
+ ("grammarly.config.documentDomain" lsp-grammarly-domain)
+ ("grammarly.config.suggestions.ConjunctionAtStartOfSentence" lsp-grammarly-suggestions-conjunction-at-start-of-sentence)
+ ("grammarly.config.suggestions.Fluency" lsp-grammarly-suggestions-fluency)
+ ("grammarly.config.suggestions.InformalPronounsAcademic" lsp-grammarly-suggestions-informal-pronouns-academic)
+ ("grammarly.config.suggestions.MissingSpaces" lsp-grammarly-suggestions-missing-spaces)
+ ("grammarly.config.suggestions.NounStrings" lsp-grammarly-suggestions-noun-strings)
+ ("grammarly.config.suggestions.NumbersBeginningSentences" lsp-grammarly-suggestions-numbers-beginning-sentences)
+ ("grammarly.config.suggestions.NumbersZeroThroughTen" lsp-grammarly-suggestions-numbers-zero-through-ten)
+ ("grammarly.config.suggestions.OxfordComma" lsp-grammarly-suggestions-oxford-comma)
+ ("grammarly.config.suggestions.PassiveVoice" lsp-grammarly-suggestions-passive-voice)
+ ("grammarly.config.suggestions.PersonFirstLanguage" lsp-grammarly-suggestions-person-first-language)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageAgeRelated" lsp-grammarly-suggestions-possibly-biased-language-age-related)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageDisabilityRelated" lsp-grammarly-suggestions-possibly-biased-language-disability-related)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageFamilyRelated" lsp-grammarly-suggestions-possibly-biased-language-family-related)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageGenderRelated" lsp-grammarly-suggestions-possibly-biased-language-gender-related)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageHumanRights" lsp-grammarly-suggestions-possibly-biased-language-human-rights)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageHumanRightsRelated" lsp-grammarly-suggestions-possibly-biased-language-human-rights-related)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageLgbtqiaRelated" lsp-grammarly-suggestions-possibly-biased-language-lgbtqia-related)
+ ("grammarly.config.suggestions.PossiblyBiasedLanguageRaceEthnicityRelated" lsp-grammarly-suggestions-possibly-biased-language-race-ethnicity-related)
+ ("grammarly.config.suggestions.PossiblyPoliticallyIncorrectLanguage" lsp-grammarly-suggestions-possibly-politically-incorrect-language)
+ ("grammarly.config.suggestions.PrepositionAtTheEndOfSentence" lsp-grammarly-suggestions-preposition-at-the-end-of-sentence)
+ ("grammarly.config.suggestions.PunctuationWithQuotation" lsp-grammarly-suggestions-punctuation-with-quotation)
+ ("grammarly.config.suggestions.ReadabilityFillerwords" lsp-grammarly-suggestions-readability-fillerwords)
+ ("grammarly.config.suggestions.ReadabilityTransforms" lsp-grammarly-suggestions-readability-transforms)
+ ("grammarly.config.suggestions.SentenceVariety" lsp-grammarly-suggestions-sentence-variety)
+ ("grammarly.config.suggestions.SpacesSurroundingSlash" lsp-grammarly-suggestions-spaces-surrounding-slash)
+ ("grammarly.config.suggestions.SplitInfinitive" lsp-grammarly-suggestions-split-infinitive)
+ ("grammarly.config.suggestions.StylisticFragments" lsp-grammarly-suggestions-stylistic-fragments)
+ ("grammarly.config.suggestions.UnnecessaryEllipses" lsp-grammarly-suggestions-unnecessary-ellipses)
+ ("grammarly.config.suggestions.Variety" lsp-grammarly-suggestions-variety)
+ ("grammarly.config.suggestions.Vocabulary" lsp-grammarly-suggestions-vocabulary)))
(lsp-dependency 'grammarly-ls
'(:system "grammarly-ls")
- '(:npm :package "@emacs-grammarly/unofficial-grammarly-language-server"
- :path "unofficial-grammarly-language-server"))
+ '(:npm :package "@emacs-grammarly/grammarly-languageserver"
+ :path "grammarly-languageserver"))
(lsp-register-client
(make-lsp-client
@@ -282,178 +488,31 @@ For argument CALLBACK, see object `lsp--client' description."
(defun lsp-grammarly-check-grammar ()
"Start the Grammarly checker."
(interactive)
- (lsp-request-async
- "$/checkGrammar" `(:uri ,(lsp--buffer-uri))
- (lambda (_) (message "Start Grammarly checker..."))))
+ (user-error "[INFO] This command is currently disabled, and it will be added back in the later version"))
(defun lsp-grammarly-stop ()
"Stop the Grammarly checker."
(interactive)
- (lsp-request-async
- "$/stop" `(:uri ,(lsp--buffer-uri))
- (lambda (_) (message "Stop Grammarly checker..."))))
+ (user-error "[INFO] This command is currently disabled, and it will be added back in the later version"))
(defun lsp-grammarly-stats ()
"Return document state."
(interactive)
- (lsp-request-async
- "$/getDocumentState" `(:uri ,(lsp--buffer-uri))
- (lambda (state)
- (message
- (concat
- (let* ((user (ht-get state "user"))
- (is-premium (ht-get user "isPremium"))
- (_is-anonymous (ht-get user "isAnonymous"))
- (username (ht-get user "username")))
- (format "[User] %s (%s)" username (if is-premium "Premium" "Free")))
- (when-let ((score (ht-get state "score")))
- (format "\n[Text Score] %s out of 100" score))
- (when-let* ((text-info (ht-get state "textInfo"))
- (chars-count (ht-get text-info "charsCount"))
- (words-count (ht-get text-info "wordsCount"))
- (readability-score (ht-get text-info "readabilityScore")))
- (format "\n[Text-Info] Readability: %s, C: %s, W: %s"
- readability-score chars-count words-count))
- (when-let* ((scores (ht-get state "scores"))
- (clarity (ht-get scores "Clarity"))
- (tone (ht-get scores "Tone"))
- (correctness (ht-get scores "Correctness"))
- (general-score (ht-get scores "GeneralScore"))
- (engagement (ht-get scores "Engagement")))
- (format "\nClarity: %s, Tone: %s, Correctness: %s, GeneralScore: %s, Engagement: %s"
- (lsp-grammarly--scale-100 clarity)
- (lsp-grammarly--scale-100 tone)
- (lsp-grammarly--scale-100 correctness)
- (lsp-grammarly--scale-100 general-score)
- (lsp-grammarly--scale-100 engagement))))))))
+ (user-error "[INFO] This command is currently disabled, and it will be added back in the later version"))
;;
;; (@* "Login" )
;;
-(defvar lsp-grammarly--code-verifier nil "Login information, code verifier.")
-(defvar lsp-grammarly--challenge nil "Login information, challenge.")
-
-(defconst lsp-grammarly-client-id "extensionVSCode"
- "Key for URI scheme.")
-
-(defun lsp-grammarly--resolve-uri (uri)
- "Handle URI for authentication."
- (let ((prefix "vscode://znck.grammarly/auth/callback?") query)
- (if (not (string-prefix-p prefix uri))
- (user-error "[WARNING] An URL should start with prefix: %s" prefix)
- (setq uri (s-replace prefix "" uri)
- query (url-parse-query-string uri))
- (nth 1 (assoc "code" query)))))
-
-(defun lsp-grammarly--update-cookie ()
- "Refresh the Grammarly.com cookie once."
- (grammarly--form-cookie)
- `((csrf-token . ,(grammarly--get-cookie-by-name "csrf-token"))
- (grauth . ,(grammarly--get-cookie-by-name "grauth"))
- (gnar-containerId . ,(grammarly--get-cookie-by-name "gnar_containerId"))
- (tdi . ,(grammarly--get-cookie-by-name "tdi"))))
-
-(defun lsp-grammarly--uri-callback ()
- "Callback after resolving URI.
-
-Argument CODE is the query string from URI."
- (let* ((uri (read-string "[Grammarly Authentication] code: "))
- (code (lsp-grammarly--resolve-uri uri))
- cookie csrf-token grauth gnar-containerId tdi)
- (request
- (format "https://auth.grammarly.com/v3/user/oranonymous?app=%s" lsp-grammarly-client-id)
- :type "GET"
- :headers
- `(("x-client-type". ,lsp-grammarly-client-id)
- ("x-client-version" . "0.0.0"))
- :success
- (cl-function
- (lambda (&key _response _data &allow-other-keys)
- (setq cookie (lsp-grammarly--update-cookie)
- csrf-token (cdr (assoc 'csrf-token cookie))
- grauth (cdr (assoc 'grauth cookie))
- gnar-containerId (cdr (assoc 'gnar-containerId cookie)))
- (request
- "https://auth.grammarly.com/v3/api/unified-login/code/exchange"
- :type "POST"
- :headers
- `(("Accept" . "application/json")
- ("Content-Type" . "application/json")
- ("x-client-type" . ,lsp-grammarly-client-id)
- ("x-client-version" . "0.0.0")
- ("x-csrf-token" . ,csrf-token)
- ("x-container-id" . ,gnar-containerId)
- ("cookie" . ,(format "grauth=%s; csrf-token=%s" grauth csrf-token)))
- :data
- (json-encode
- `(("client_id" . ,lsp-grammarly-client-id)
- ("code" . ,code)
- ("code_verifier" . ,lsp-grammarly--code-verifier)))
- :success
- (cl-function
- (lambda (&key _response data &allow-other-keys)
- (setq cookie (lsp-grammarly--update-cookie)
- csrf-token (cdr (assoc 'csrf-token cookie))
- grauth (cdr (assoc 'grauth cookie))
- gnar-containerId (cdr (assoc 'gnar-containerId cookie))
- tdi (cdr (assoc 'tdi cookie)))
- (let* ((all-data (lsp-grammarly--json-read data))
- (user (nth 0 all-data))
- (premium (string= "Premium" (cdr (assoc 'type user))))
- (name (cdr (assoc 'name user)))
- (email (cdr (assoc 'email user)))
- (token (format "grauth=%s;csrf-token=%s;tdi=%s;" grauth csrf-token tdi))
- (auth-info `(("isAnonymous" . :json-false)
- ("isPremium" . ,premium)
- ("token" . ,token)
- ("username" . ,email))))
- (keytar-set-password
- lsp-grammarly--cookie-key lsp-grammarly--account
- (lsp-grammarly--json-encode auth-info))
- ;; TODO: This is slow, need to improve the performance for better
- ;; user experience.
- (ignore-errors (lsp-workspace-restart nil))
- (message "[INFO] Logged in as `%s`" name))))
- :error
- (cl-function
- (lambda (&rest args &key _error-thrown &allow-other-keys)
- (lsp-grammarly--message "[ERROR] Error while authenticating login: %s" args))))))
- :error
- (cl-function
- (lambda (&rest args &key _error-thrown &allow-other-keys)
- (lsp-grammarly--message "[ERROR] Error while getting cookie: %s" args))))))
-
(defun lsp-grammarly-login ()
"Login to Grammarly.com."
(interactive)
- (keytar--check)
- (if (lsp-grammarly-login-p)
- (message "[INFO] You are already logged in with `%s`" (lsp-grammarly--username))
- (setq lsp-grammarly--code-verifier
- (base64url-encode-string (lsp-grammarly--random-bytes 96) t)
- lsp-grammarly--challenge
- (base64url-encode-string (secure-hash 'sha256 lsp-grammarly--code-verifier nil nil t) t))
- (browse-url (format
- "https://grammarly.com/signin/app?client_id=%s&code_challenge=%s"
- lsp-grammarly-client-id lsp-grammarly--challenge))
- (lsp-grammarly--uri-callback)))
+ (user-error "[INFO] This command is currently disabled, and it will be added back in the later version"))
(defun lsp-grammarly-logout ()
"Logout from Grammarly.com."
(interactive)
- (keytar--check)
- (if (not (lsp-grammarly-login-p))
- (message "[INFO] You are already logout from Grammarly.com")
- (if (keytar-delete-password lsp-grammarly--cookie-key lsp-grammarly--account)
- (progn
- (setq lsp-grammarly--password nil
- lsp-grammarly--password-string nil)
- ;; TODO: This is slow, need to improve the performance for better
- ;; user experience.
- (ignore-errors (lsp-workspace-restart nil))
- (message "[INFO] Logged out of Grammarly.com"))
- (message "[ERROR] Failed to logout from Grammarly.com"))))
+ (user-error "[INFO] This command is currently disabled, and it will be added back in the later version"))
(provide 'lsp-grammarly)
;;; lsp-grammarly.el ends here
diff --git a/test/activate.el b/test/activate.el
new file mode 100644
index 0000000..2efee57
--- /dev/null
+++ b/test/activate.el
@@ -0,0 +1,65 @@
+;;; activate.el --- Test activation -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Shen, Jen-Chieh
+;; Created date 2022-05-08 12:50:37
+
+;; This file is NOT part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see .
+
+;;; Commentary:
+;;
+;; Test activation
+;;
+
+;;; Code:
+
+(eask-pkg-init)
+
+(require 'lsp-mode)
+
+(lsp-install-server t 'grammarly-ls) ; Start installation
+
+(defconst timeout 180
+ "Timeout in seconds.")
+
+(defvar timer 0)
+
+(defun get-lsp-install-buffer ()
+ "Get lsp-insall buffer."
+ (nth 0
+ (cl-remove-if-not (lambda (buf)
+ (string-prefix-p "*lsp-install:" (buffer-name buf)))
+ (buffer-list))))
+
+(with-current-buffer (get-lsp-install-buffer)
+ (while (not (string-match-p "^Comint" (thing-at-point 'line)))
+ (goto-char (point-max))
+ (forward-line -1)
+ (sit-for 5)
+ (cl-incf timer 5)
+ (message "Waited %s..." timer)))
+
+(defconst server-install-path (lsp-package-path 'grammarly-ls)
+ "The server install location.")
+
+(unless (file-exists-p server-install-path)
+ (error "Failed to install server: %s" server-install-path)
+ (kill-emacs 1))
+
+(message "Testing with a file...")
+
+(find-file "README.md") ; start lsp
+
+;;; activate.el ends here