Skip to content

Update Shell script syntax checking to use built-in Flymake backend for Emacs ≥ 29 #44

Description

@coderabbitai

Context

As identified in PR #43 (#43), the current shell script syntax checking logic needs to be updated to leverage Emacs built-in Flymake ShellCheck support available in Emacs ≥ 29.

Current Implementation

In pel_keys.el (lines 6224-6240), the current logic always installs the flymake-shellcheck package from MELPA:

;; [:todo 2026-02-19, by Pierre Rouleau: Update this logic to handle
;;                    Emacs > 29 where Emacs handle Flymake-Shellcheck
;;                    integration ]
(cond
 ;; using flymake
 ((memq pel-use-shellcheck '(flymake-manual
                             flymake-automatic))
  (pel-ensure-package flymake-shellcheck from: melpa)
  (when (eq pel-use-shellcheck 'flymake-automatic)
    (add-hook 'sh-mode-hook 'flymake-shellcheck-load)))
 ;; using flycheck
 ;; - flycheck support is already extended by default.
 ;; - start it automatically if it was requested by user-option
 ((eq pel-use-shellcheck 'flycheck-automatic)
  (add-hook 'sh-mode-hook 'flycheck-mode))))

Built-in Support in Emacs ≥ 29

Starting with Emacs 29, sh-script.el includes a built-in Flymake backend for ShellCheck (sh-shellcheck-flymake). This backend is automatically added to flymake-diagnostic-functions in sh-mode and bash-ts-mode.

Key differences:

  • No external package installation required
  • Just needs shellcheck executable on PATH
  • Backend is automatically registered when Flymake is enabled
  • Optional: Can configure via sh-shellcheck-arguments variable

References:

Proposed Implementation

Update the conditional logic to distinguish between Emacs versions:

;; Shell script syntax checking with ShellCheck
(cond
 ;; Using Flymake with ShellCheck
 ((memq pel-use-shellcheck '(flymake-manual flymake-automatic))
  (if (>= emacs-major-version 29)
      ;; Emacs ≥ 29: Use built-in sh-shellcheck-flymake backend
      (progn
        ;; Optional: Configure ShellCheck arguments (e.g., "-x" to follow sourced files)
        ;; (setq-default sh-shellcheck-arguments '("-x"))
        
        ;; Activate Flymake automatically if requested
        (when (eq pel-use-shellcheck 'flymake-automatic)
          (add-hook 'sh-mode-hook #'flymake-mode)
          ;; Also for bash-ts-mode if tree-sitter support is available
          (when (fboundp 'bash-ts-mode)
            (add-hook 'bash-ts-mode-hook #'flymake-mode))))
    
    ;; Emacs < 29: Use external flymake-shellcheck package from MELPA
    (pel-ensure-package flymake-shellcheck from: melpa)
    (when (eq pel-use-shellcheck 'flymake-automatic)
      (add-hook 'sh-mode-hook 'flymake-shellcheck-load))))
 
 ;; Using Flycheck with ShellCheck
 ;; (No change needed - no built-in support for Flycheck)
 ((eq pel-use-shellcheck 'flycheck-automatic)
  (add-hook 'sh-mode-hook 'flycheck-mode)))

Additional Considerations

  1. User Option pel-use-shellcheck: Consider adding documentation to clarify that for Emacs ≥ 29, the built-in backend is used when selecting Flymake options.

  2. ShellCheck Installation: Users still need to install the shellcheck executable separately. Consider adding a check or warning if shellcheck is not found on PATH.

  3. Configuration Variable: Consider exposing sh-shellcheck-arguments through a PEL user option for users who want to customize ShellCheck behavior (e.g., enabling sourced file checking with "-x").

  4. Backward Compatibility: The proposed implementation maintains full backward compatibility with older Emacs versions.

  5. Tree-sitter Support: The built-in backend also works with bash-ts-mode, so consider adding hooks for tree-sitter modes when available.

Tasks

  • Update the conditional logic in pel_keys.el
  • Update documentation for pel-use-shellcheck in pel--options.el
  • Consider adding a PEL user option for sh-shellcheck-arguments
  • Add note about shellcheck executable requirement
  • Test with Emacs 29+ and Emacs < 29

Requested by: @pierre-rouleau
Related PR: #43

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions