Skip to content

Add mtlog-analyzer support for Emacs #58

@willibrandon

Description

@willibrandon

Description:
Implement mtlog-analyzer support as an Emacs package. This would be the 5th editor integration alongside VS Code, GoLand, Neovim, and Zed.

Background:
Emacs has two main LSP clients (lsp-mode and Eglot) that can integrate with language servers. Following the bundled approach used for Zed, Emacs will use mtlog-lsp which will include the analyzer functionality bundled within it.

Architecture

mtlog-analyzer.el (Emacs Package)

An Emacs package that configures both lsp-mode and Eglot to use mtlog-lsp:

  • Registers mtlog-lsp with both LSP clients
  • Detects mtlog usage in Go projects
  • Handles binary installation and detection
  • Passes analyzer configuration through LSP initialization options

Installation:

go install github.com/willibrandon/mtlog/cmd/mtlog-lsp@latest

Implementation

Package Structure

emacs-extension/mtlog-analyzer/
├── mtlog-analyzer.el      # Main package file
├── README.md              # Installation and usage documentation
├── Makefile               # Build and test automation
└── test/                  # ERT tests

Core Implementation

;;; mtlog-analyzer.el --- mtlog-analyzer support for Emacs -*- lexical-binding: t; -*-

;; Author: Brandon Williams
;; Version: 0.1.0
;; Package-Requires: ((emacs "27.1"))
;; Keywords: languages, go, tools
;; URL: https://github.com/willibrandon/mtlog

(require 'go-mode)

(defgroup mtlog-analyzer nil
  "mtlog-analyzer integration for Go development."
  :group 'go
  :prefix "mtlog-analyzer-")

(defcustom mtlog-analyzer-lsp-path nil
  "Path to mtlog-lsp executable.
If nil, will search in standard Go binary locations."
  :type '(choice (const :tag "Auto-detect" nil)
                 (file :tag "Path to executable"))
  :group 'mtlog-analyzer)

;; Analyzer configuration options
(defcustom mtlog-analyzer-strict nil
  "Enable strict format specifier validation."
  :type 'boolean
  :group 'mtlog-analyzer)

(defcustom mtlog-analyzer-common-keys '("user_id" "request_id")
  "Common context keys to suggest as constants."
  :type '(repeat string)
  :group 'mtlog-analyzer)

(defcustom mtlog-analyzer-disabled-checks '()
  "List of checks to disable."
  :type '(repeat string)
  :group 'mtlog-analyzer)

(defcustom mtlog-analyzer-suppressed-diagnostics '()
  "List of diagnostic IDs to suppress (e.g., MTLOG007)."
  :type '(repeat string)
  :group 'mtlog-analyzer)

;;;###autoload
(defun mtlog-analyzer-setup ()
  "Set up mtlog-analyzer for current Emacs session."
  (interactive)
  (when (mtlog-analyzer--find-lsp-binary)
    (mtlog-analyzer--setup-lsp-mode)
    (mtlog-analyzer--setup-eglot)))

Binary Detection

(defun mtlog-analyzer--find-lsp-binary ()
  "Find mtlog-lsp in standard locations."
  (or mtlog-analyzer-lsp-path
      (executable-find "mtlog-lsp")
      (mtlog-analyzer--find-in-go-path)))

(defun mtlog-analyzer--find-in-go-path ()
  "Search for mtlog-lsp in Go binary directories."
  (let ((paths (list
                (when-let ((gobin (getenv "GOBIN")))
                  (expand-file-name "mtlog-lsp" gobin))
                (when-let ((gopath (getenv "GOPATH")))
                  (expand-file-name "bin/mtlog-lsp" gopath))
                (expand-file-name "~/go/bin/mtlog-lsp"))))
    (cl-find-if #'file-executable-p paths)))

(defun mtlog-analyzer-install-lsp ()
  "Install mtlog-lsp binary."
  (interactive)
  (let ((default-directory (temporary-file-directory)))
    (message "Installing mtlog-lsp...")
    (if (zerop (shell-command "go install github.com/willibrandon/mtlog/cmd/mtlog-lsp@latest"))
        (message "mtlog-lsp installed successfully")
      (error "Failed to install mtlog-lsp"))))

LSP Configuration

lsp-mode setup:

(defun mtlog-analyzer--setup-lsp-mode ()
  "Configure lsp-mode to use mtlog-lsp."
  (when (featurep 'lsp-mode)
    (require 'lsp-mode)
    (lsp-register-client
     (make-lsp-client
      :new-connection (lsp-stdio-connection
                       (lambda () (mtlog-analyzer--find-lsp-binary)))
      :activation-fn (lsp-activate-on "go")
      :server-id 'mtlog-lsp
      :priority 10
      :add-on? t
      :initialization-options #'mtlog-analyzer--make-initialization-options))))

Eglot setup:

(defun mtlog-analyzer--setup-eglot ()
  "Configure Eglot to use mtlog-lsp."
  (when (featurep 'eglot)
    (require 'eglot)
    (add-to-list 'eglot-server-programs
                 `(go-mode . (,(mtlog-analyzer--find-lsp-binary))))
    (add-hook 'eglot-managed-mode-hook
              (lambda ()
                (when (derived-mode-p 'go-mode)
                  (setq-local eglot-workspace-configuration
                              (mtlog-analyzer--make-initialization-options)))))))

Features

  1. All MTLOG001-MTLOG013 diagnostics via LSP
  2. Quick fixes/Code Actions through lsp-execute-code-action or eglot-code-actions
  3. Automatic binary detection in standard Go paths
  4. Works with both lsp-mode and Eglot out of the box
  5. Configuration through LSP initialization options
  6. Auto-setup for mtlog projects via go.mod detection

Requirements

Only one component needs to be installed:

mtlog-lsp - The LSP server with bundled analyzer

go install github.com/willibrandon/mtlog/cmd/mtlog-lsp@latest

Publishing

Initial Publishing

  1. Submit package to MELPA
    • Fork MELPA repository
    • Add recipe file for mtlog-analyzer
    • Submit PR with package metadata
  2. Add to GNU ELPA (optional)
  3. Create Emacs Wiki page

Package Distribution

MELPA Recipe (recipes/mtlog-analyzer):

(mtlog-analyzer :repo "willibrandon/mtlog"
                :fetcher github
                :files ("emacs-extension/mtlog-analyzer/*.el"))

Package Header:

;; Package-Requires: ((emacs "27.1"))
;; Version: 0.1.0
;; URL: https://github.com/willibrandon/mtlog
;; Keywords: languages, go, tools

Testing Requirements

  • Verify diagnostics display in both lsp-mode and Eglot
  • Test quick fix application with both LSP clients
  • Validate binary detection on macOS/Linux/Windows
  • Check configuration options are properly passed
  • Test auto-setup with mtlog projects
  • Verify no conflicts with gopls
  • Performance testing with bundled analyzer

Implementation Notes

  • Uses bundled mtlog-lsp (analyzer included)
  • Supports both major Emacs LSP clients
  • No custom UI needed - uses built-in diagnostics
  • Configuration through LSP initialization options
  • Single binary simplifies installation
  • Auto-configuration based on project detection

Comparison with Other Editor Integrations

Editor Language LOC Notes
VS Code TypeScript ~3,700 Custom diagnostics provider, uses mtlog-analyzer directly
GoLand Kotlin ~7,200 IntelliJ platform integration, uses mtlog-analyzer directly
Neovim Lua ~14,200 Complete plugin with caching, uses mtlog-analyzer directly
Zed Rust ~200 Simple LSP wrapper, uses bundled mtlog-lsp
Emacs Elisp ~300 LSP client configuration, uses bundled mtlog-lsp

Emacs follows the same approach as Zed, using the bundled mtlog-lsp for simplified installation and configuration.

Metadata

Metadata

Assignees

Labels

emacsEmacs editor extension and integrationenhancementNew feature or requestmtlog-analyzerStatic analysis tool for detecting mtlog usage issuesmtlog-lspLanguage Server Protocol implementation for mtlog-analyzertoolingDevelopment tools, build systems, and analyzers

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions