diff --git a/init.example.el b/init.example.el index 22a707033..2fe2b108b 100644 --- a/init.example.el +++ b/init.example.el @@ -134,6 +134,7 @@ ;;fstar ; (dependent) types and (monadic) effects and Z3 ;;gdscript ; the language you waited for ;;(go +lsp) ; the hipster dialect + ;;(graphql +lsp) ; Give queries a REST ;;(haskell +lsp) ; a language that's lazier than I am ;;hy ; readability of scheme w/ speed of python ;;idris ; a language you can depend on diff --git a/modules/lang/graphql/README.org b/modules/lang/graphql/README.org new file mode 100644 index 000000000..b960e28cb --- /dev/null +++ b/modules/lang/graphql/README.org @@ -0,0 +1,115 @@ +#+TITLE: lang/graphql +#+DATE: March 31, 2022 +#+SINCE: v2.0 +#+STARTUP: inlineimages nofold + +* Table of Contents :TOC_3:noexport: +- [[#description][Description]] + - [[#maintainers][Maintainers]] + - [[#module-flags][Module Flags]] + - [[#plugins][Plugins]] + - [[#hacks][Hacks]] +- [[#prerequisites][Prerequisites]] +- [[#features][Features]] + - [[#sending-queries][Sending queries]] + - [[#viewing-docs][Viewing docs]] +- [[#configuration][Configuration]] +- [[#troubleshooting][Troubleshooting]] + +* Description +This module adds [[https://www.graphql.org][GraphQL]] support to Doom Emacs. + ++ Code completion ++ LSP support (=+lsp=) + + Diagnostics (GraphQL syntax linting/validations) (spec-compliant) + + Autocomplete suggestions (spec-compliant) + + Hyperlink to fragment definitions and named types (type, input, enum) definitions (spec-compliant) + + Outline view support for queries and SDL + + Symbols support across the workspace ++ Local schema viewer ++ Org-babel exporter (requires =:lang org=) + +** Maintainers ++ [[https://github.com/elken][@elken]] (Author) + +** Module Flags ++ =+lsp= Enable LSP support through [[https://github.com/graphql/graphiql/tree/main/packages/graphql-language-service-cli#readme][graphql-language-service-cli]] (also requires =:tools lsp=) + +** Plugins ++ [[https://github.com/davazp/graphql-mode][graphql-mode]] ++ [[https://github.com/ifitzpatrick/graphql-doc.el][graphql-doc]] ++ [[https://github.com/timoweave/company-graphql][company-graphql]] (when =+lsp= is disabled) + +** Hacks +Added a convenience function =+graphql-doc-open-config= to open schema docs from a +[[https://github.com/jimkyndemeyer/graphql-config-examples][=.graphqlconfig=]] file. + +* Prerequisites +There are no prerequisites for using this module. LSP server should be +downloaded upon opening a graphql buffer. + +* Features +** Sending queries +When visiting a graphql buffer, you have access to the ability to send the +current query with =C-c C-c= which will prompt you for an optional variables file, +then execute the query and return a buffer of the results. + +It's also possible to send queries using org-babel using a block such as the +ones below (executing correctly will require =:lang org=) + +#+NAME: my-variables +#+begin_src json +{ + "continentCode": "AF" +} +#+end_src + +#+BEGIN_SRC graphql :url https://countries.trevorblades.com/ :variables my-variables +query GetContinents($continentCode: String!) { + continent(code: $continentCode) { + name + code + } +} +#+END_SRC + +#+RESULTS: +: { +: "data": { +: "continent": { +: "name": "Africa", +: "code": "AF" +: } +: } +: } + +** Viewing docs +With this module, there are 3 ways to view schemas: ++ =+graphql-doc-open-config= which uses a local [[https://github.com/jimkyndemeyer/graphql-config-examples][=.graphqlconfig=]] file to seed endpoints to query ++ =graphql-doc= which prompts you to select an endpoint based on ones added manually by =graphql-doc-add-api= ++ =graphql-doc-open-url= which prompts to to manually enter an endpoint url + +When using the doc viewer, there are a few bindings for navigating around. + +| Key | Command | Description | +|-------------+---------------------+-----------------------------------| +| =C-j= | =forward-button= | Follow a forward button | +| =C-k= | =backward-button= | Follow a backward button | +| == | =graphql-doc-go-back= | Go back to a previous page | +| =mouse-1= | - | Follow the next label under =point= | +| =RET= | - | Follow the next label under =point= | + +* Configuration +Most of the "magic" in the module relies on a properly configured +[[https://github.com/jimkyndemeyer/graphql-config-examples][=.graphqlconfig=]] file, so follow the examples linked to create an appropriate +setup. + +LSP configuration is handled through [[https://github.com/graphql/graphiql/tree/main/packages/graphql-language-service-cli#graphql-configuration-file-graphqlrcyml][GraphQL Config]] to handle custom directives/documents/validation etc. + +These files will also be useful to other editors, so it would be worth trying to +get them into version control. + +* Troubleshooting +- [[https://github.com/ifitzpatrick/graphql-doc.el/issues][Issues with the doc viewer]] +- [[https://github.com/davazp/graphql-mode/issues][Issues with graphql-mode]] +- [[https://github.com/emacs-lsp/lsp-mode/issues][Issues with LSP]] ([[https://github.com/graphql/graphiql/issues][Upstream LSP issues]]) diff --git a/modules/lang/graphql/autoload.el b/modules/lang/graphql/autoload.el new file mode 100644 index 000000000..953025e5e --- /dev/null +++ b/modules/lang/graphql/autoload.el @@ -0,0 +1,14 @@ +;;; lang/graphql/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun +graphql-doc-open-config () + "Locate a .graphqlconfig file in the current tree and use that to point to a + schema." + (interactive) + (let ((config (json-read-file (graphql-locate-config ".")))) + (let-alist config + (if-let ((endpoints .extensions.endpoints) + (endpoint (cdr (assq (intern (graphql--completing-read-endpoint endpoints)) endpoints)))) + (let-alist endpoint + (graphql-doc--start .url `(:url ,.url :headers ,.headers))) + (error "No endpoint configurations in .graphqlconfig"))))) diff --git a/modules/lang/graphql/config.el b/modules/lang/graphql/config.el new file mode 100644 index 000000000..e63865064 --- /dev/null +++ b/modules/lang/graphql/config.el @@ -0,0 +1,39 @@ +;;; lang/graphql/config.el -*- lexical-binding: t; -*- + +(after! graphql-mode + (defface all-the-icons-rhodamine + '((t (:foreground "#E10098"))) + "Face for GraphQL icon." + :group 'all-the-icons-faces) + + ;; Define a doom-modeline compatiable major-mode icon + (after! all-the-icons + (setf (alist-get "graphql" all-the-icons-extension-icon-alist) + '(all-the-icons-fileicon "graphql" :v-adjust -0.05 :face 'all-the-icons-rhodamine)) + (setf (alist-get "gql" all-the-icons-extension-icon-alist) + '(all-the-icons-fileicon "graphql" :v-adjust -0.05 :face 'all-the-icons-rhodamine)) + (setf (alist-get 'graphql-mode all-the-icons-mode-icon-alist) + '(all-the-icons-fileicon "graphql" :v-adjust -0.05 :face 'all-the-icons-rhodamine))) + (if (featurep! +lsp) + (add-hook 'graphql-mode-local-vars-hook #'lsp! 'append) + (set-company-backend! 'graphql-mode 'company-graphql)) + + (add-hook 'graphql-mode-hook #'rainbow-delimiters-mode) + (set-docsets! 'graphql-mode :add "GraphQL Specification") + + (set-electric! 'graphql-mode + :chars '(?\} ?\)) + :words '("or" "and")) + + (set-ligatures! 'graphql-mode + :null "null" + :true "true" :false "false" + :int "Int" :str "String" + :float "Float" + :bool "Bool" + + :not "not" + :and "and" :or "or")) + +(use-package! graphql-doc + :after graphql-mode) diff --git a/modules/lang/graphql/packages.el b/modules/lang/graphql/packages.el new file mode 100644 index 000000000..ba8a84a4b --- /dev/null +++ b/modules/lang/graphql/packages.el @@ -0,0 +1,7 @@ +;; -*- no-byte-compile: t; -*- +;;; lang/graphql/packages.el + +(package! graphql-mode :pin "9740e4027bd9313697d5cac5caaa5b15626ab1da") +(package! graphql-doc :pin "6ba7961fc9c5c9818bd60abce6ba9dfef2dad452") +(when (not (featurep! +lsp)) + (package! company-graphql :pin "757dfa45ad0cef9b9c362c8993d6474a2426c01c")) diff --git a/modules/lang/org/packages.el b/modules/lang/org/packages.el index c77979df5..a608645fa 100644 --- a/modules/lang/org/packages.el +++ b/modules/lang/org/packages.el @@ -103,6 +103,8 @@ (package! ob-elixir :pin "8990a8178b2f7bd93504a9ab136622aab6e82e32")) (when (featurep! :lang go) (package! ob-go :pin "2067ed55f4c1d33a43cb3f6948609d240a8915f5")) +(when (featurep! :lang graphql) + (package! ob-graphql :pin "7c35419f9eec5dc44967cbcfa13c7135b9a96bfc")) (when (featurep! :lang hy) (package! ob-hy :pin "a42ecaf440adc03e279afe43ee5ef6093ddd542a")) (when (featurep! :lang nim)