dotfiles/emacs/.emacs.d/config/init-terraform.el

68 lines
3.0 KiB
EmacsLisp

;; -*- lexical-binding: t; -*-
;; Configuration as code!
(use-package terraform-mode
:mode "\\.tf\\'"
:config
(defun devdocs-terraform-resource-string (resource type)
"Returns the devdocs for Terraform resource RESOURCE of type TYPE (\"data\" or \"resource\")as a string."
(devdocs-as-string resource "terraform" type))
(add-to-list 'devdocs-entry-aliases '("aws_alb" . "aws_lb"))
(defun terraform-resource-name-and-type-at-pos (pos)
(let* ((parser (treesit-parser-create 'hcl))
(current-node (treesit-node-at pos parser))
(block (treesit-node-top-level current-node "block"))
(capture (when block
(treesit-query-capture block
'((block (identifier) @id (:match "^\\(data\\|resource\\)$" @id)
(string_lit (_) (template_literal) @name (_)))))))
(name-node (alist-get 'name capture))
(id-node (alist-get 'id capture))
(name (when name-node (treesit-node-text name-node t)))
(id (when id-node (treesit-node-text id-node t))))
(cons name id)))
(defun terraform-resource-name-and-type-at-point ()
(terraform-resource-name-and-type-at-pos (point)))
(defun terraform-devdocs-eldoc-function (cb)
(when-let* ((resource-name-and-type (terraform-resource-name-and-type-at-point))
(resource-name (car resource-name-and-type))
(resource-type (cdr resource-name-and-type))
(doc (devdocs-terraform-resource-string resource-name resource-type))
(summary (with-temp-buffer
(insert doc)
(goto-char (point-min))
(forward-line)
(while (and (looking-at (rx space) t) (not (eobp)))
(forward-line))
(buffer-substring-no-properties (line-beginning-position) (line-end-position)))))
(funcall cb doc :echo summary)))
(defun terraform-setup-eldoc ()
(add-hook 'eldoc-documentation-functions #'terraform-devdocs-eldoc-function nil t))
(add-hook 'terraform-mode-hook #'terraform-setup-eldoc)
(defun find-terraform-root ()
"Returns the highest-level parent directory containing a .tf file."
(let ((current-dir default-directory)
(root nil))
(while (and (not (string-match locate-dominating-stop-dir-regexp current-dir))
(f-glob "*.tf" current-dir))
(setq root current-dir)
(setq current-dir (f-parent current-dir)))
(when root (file-name-as-directory root))))
;; Use root terraform module to resolve providers
(defun terraform-provider-ns-advice (oldfn &rest args)
(let ((dir (or (find-terraform-root) default-directory)))
(let ((default-directory dir))
(apply oldfn args))))
(advice-add 'terraform--get-resource-provider-namespace :around #'terraform-provider-ns-advice))
(provide 'init-terraform)