From 4c886c1a0475bf800464717b234d32465db231ac Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 16:47:53 -0800 Subject: [PATCH 01/14] Add lint exit-code tests and test case files --- test/jest/lint.test.js | 216 ++++++++++++++++++++++++++++++++ test/jest/lint/Eask | 7 ++ test/jest/lint/checkdoc-fail.el | 29 +++++ test/jest/lint/declare-fail.el | 24 ++++ test/jest/lint/declare-ok.el | 26 ++++ test/jest/lint/elisp-lint-ok.el | 21 ++++ test/jest/lint/elsa-warn.el | 29 +++++ test/jest/lint/indent-warn.el | 31 +++++ test/jest/lint/regexp-warn.el | 28 +++++ 9 files changed, 411 insertions(+) create mode 100644 test/jest/lint.test.js create mode 100644 test/jest/lint/Eask create mode 100644 test/jest/lint/checkdoc-fail.el create mode 100644 test/jest/lint/declare-fail.el create mode 100644 test/jest/lint/declare-ok.el create mode 100644 test/jest/lint/elisp-lint-ok.el create mode 100644 test/jest/lint/elsa-warn.el create mode 100644 test/jest/lint/indent-warn.el create mode 100644 test/jest/lint/regexp-warn.el diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js new file mode 100644 index 00000000..1fede4e9 --- /dev/null +++ b/test/jest/lint.test.js @@ -0,0 +1,216 @@ +const { TestContext } = require("./helpers"); + +describe("lint", () => { + const ctx = new TestContext("./test/jest/lint"); + + beforeEach(async () => { + await ctx.runEask("clean elc"); + }); + + afterAll(() => { + ctx.cleanUp(); + }); + + describe("partial input", () => { + it("eask lint should error", async () => { + await expect(ctx.runEask("eask lint")).rejects.toMatchObject({ code: 1 }); + }); + }); + + describe("checkdoc", () => { + it("should work on declare-ok.el", async () => { + await expect( + ctx.runEask("lint checkdoc declare-ok.el"), + ).resolves.toMatchObject({ + stderr: expect.stringContaining("No issues found"), + }); + }); + + it("should error given --strict", async () => { + await expect( + ctx.runEask("lint checkdoc --strict checkdoc-fail.el"), + ).rejects.toMatchObject({ + code: 1, + }); + }); + + it("should error given --strict and --allow-error", async () => { + await expect( + ctx.runEask("lint checkdoc --strict checkdoc-fail.el declare-ok.el"), + ).rejects.toMatchObject({ + code: 1, + // expect that declare-ok was checked too + stderr: expect.stringContaining("`declare-ok.el` with checkdoc"), + }); + }); + }); + + describe("declare", () => { + it("should work on declare-ok.el", async () => { + await expect( + ctx.runEask("lint declare declare-ok.el"), + ).resolves.toMatchObject({ + stderr: expect.stringContaining("No issues found"), + }); + }); + + it("should work on declare-fail.el (warnings ignored)", async () => { + await ctx.runEask("lint declare declare-fail.el"); + }); + + it("should error given --strict", async () => { + await expect( + ctx.runEask("lint declare --strict declare-fail.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + + it("should error given --strict --allow-error", async () => { + await expect( + ctx.runEask("lint declare --strict --allow-error ./*.el"), + ).rejects.toMatchObject({ + code: 1, + // expect that declare-ok was checked too + stderr: expect.stringContaining("`declare-ok.el` with check-declare"), + }); + }); + }); + + describe("elint", () => { + it("should work on declare-ok.el", async () => { + await ctx.runEask("lint elint declare-ok.el"); + }); + + // TODO --strict has no effect on elint + it.failing("should error given --strict", async () => { + await expect( + ctx.runEask("lint elint --strict checkdoc-fail.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + }); + + describe("elisp-lint", () => { + it("should work on elisp-lint-ok.el", async () => { + await ctx.runEask("lint elisp-lint --strict elisp-lint-ok.el"); + }); + + it("should work on declare-ok.el (warnings)", async () => { + await ctx.runEask("lint elisp-lint declare-ok.el"); + }); + + it("should error given --strict", async () => { + await expect( + ctx.runEask("lint elisp-lint --strict declare-ok.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + + it("should work with --strict --allow-error", async () => { + await expect( + ctx.runEask( + "lint elisp-lint --strict --allow-error checkdoc-fail.el elisp-lint-ok.el", + ), + ).rejects.toMatchObject({ + stderr: expect.stringContaining("2 files linted"), + }); + }); + }); + + describe("elsa", () => { + // TODO prints a lot of garbage + it("should work on elisp-lint-ok.el", async () => { + await ctx.runEask("lint elsa elisp-lint-ok.el"); + }); + + it("should work on elsa-warn.el (warnings)", async () => { + await ctx.runEask("lint elsa elsa-warn.el"); + }); + + // TODO prints out "error" but no exit code + it("should error on declare-ok.el", async () => { + await expect( + ctx.runEask("lint elsa declare-ok.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + + // TODO strict has no effect + it.failing("should error given --strict", async () => { + await expect( + ctx.runEask("lint elsa --strict elsa-warn.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + }); + + describe("indent", () => { + // TODO exits with 1 + // TODO prints "Don't call me!" + it.failing("should work on indent-warn.el", async () => { + await ctx.runEask("lint indent indent-warn.el"); + }); + + it("should error given --strict", async () => { + await expect( + ctx.runEask("lint indent --strict indent-warn.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + + it("should work with --strict --allow-error", async () => { + await expect( + ctx.runEask( + "lint indent --strict --allow-error indent-warn.el declare-ok.el", + ), + ).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("2 files linted"), + }); + }); + }); + + describe("keywords", () => { + // TODO seems like keywords in actual file are ignored + // only those in Eask file are checked + // but those interfere with --strict handling in other commands + + it.failing("should work", async () => { + await ctx.runEask("lint keywords"); + }); + + it.failing("should error given --strict", async () => { + await expect(ctx.runEask("lint keywords --strict")).rejects.toMatchObject( + { code: 1 }, + ); + }); + }); + + describe("package", () => { + it("should work on declare-ok.el", async () => { + await ctx.runEask("lint package declare-ok.el"); + }); + + // note that all files are checked anyway so --allow-error has no effect + it.failing("should error given --strict", async () => { + await expect( + ctx.runEask("lint package --strict declare-ok.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + }); + + describe("regexps", () => { + it("should work on declare-ok.el", async () => { + await ctx.runEask("lint regexps declare-ok.el"); + }); + + // TODO this prints a stack trace + it("should error on regexp-warn.el", async () => { + await expect( + ctx.runEask("lint regexps regexp-warn.el"), + ).rejects.toThrow(); + }); + + it.failing("should work with --allow-error", async () => { + await expect( + ctx.runEask("lint regexps --allow-error regexp-warn.el declare-ok.el"), + ).rejects.toMatchObject({ + stderr: expect.stringContaining("2 files linted"), + }); + }); + }); +}); diff --git a/test/jest/lint/Eask b/test/jest/lint/Eask new file mode 100644 index 00000000..4fed337f --- /dev/null +++ b/test/jest/lint/Eask @@ -0,0 +1,7 @@ +(package "lint" + "0.0.1" + "Test project for lint") +(package-file "lint-pkg.el") + +(source 'gnu) +(source 'melpa) diff --git a/test/jest/lint/checkdoc-fail.el b/test/jest/lint/checkdoc-fail.el new file mode 100644 index 00000000..ecbc4aad --- /dev/null +++ b/test/jest/lint/checkdoc-fail.el @@ -0,0 +1,29 @@ +;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;; 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: + +;; Tests for the command ert + +;;; Code: + +(defun my-foo (arg) + ".make a lot of checkdoc errors + +in this " ignore) + +;;; declare-ok.el ends here diff --git a/test/jest/lint/declare-fail.el b/test/jest/lint/declare-fail.el new file mode 100644 index 00000000..fa2739e3 --- /dev/null +++ b/test/jest/lint/declare-fail.el @@ -0,0 +1,24 @@ +;;; declare-fail.el --- Test lint declare -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;; 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: + +;;; Code: + +(declare-function not-a-function "subr.el" (x y z)) + +;;; declare-fail.el ends here diff --git a/test/jest/lint/declare-ok.el b/test/jest/lint/declare-ok.el new file mode 100644 index 00000000..0ff0ff03 --- /dev/null +++ b/test/jest/lint/declare-ok.el @@ -0,0 +1,26 @@ +;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;; 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: + +;; Tests for the command ert + +;;; Code: + +(declare-function ignore "subr.el" (&rest args)) + +;;; declare-ok.el ends here diff --git a/test/jest/lint/elisp-lint-ok.el b/test/jest/lint/elisp-lint-ok.el new file mode 100644 index 00000000..4b25a403 --- /dev/null +++ b/test/jest/lint/elisp-lint-ok.el @@ -0,0 +1,21 @@ +;;; elisp-lint-ok.el --- Test the linting -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;;; Version: 0.0.1 +;;; URL: https://foo.com +;;; Package-Requires: ((emacs "28.1")) + +;;; Commentary: + +;; Tests linting with elisp-lint +;; Also clean for packge lint + +;;; Code: + +(defun elisp-lint-ok-foo () + "Nothing here." + (message "ok")) + +(provide 'elisp-lint-ok) +;;; elisp-lint-ok.el ends here diff --git a/test/jest/lint/elsa-warn.el b/test/jest/lint/elsa-warn.el new file mode 100644 index 00000000..a91f18c9 --- /dev/null +++ b/test/jest/lint/elsa-warn.el @@ -0,0 +1,29 @@ +;;; elsa-warn.el --- Test elsa linting -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;; 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 elsa. +;; Should only cause warnings + +;;; Code: + +(defun elsa-warn-foo () + (some-foo) ;; not declared warning + (message "Ok")) + +;;; elsa-warn.el ends here diff --git a/test/jest/lint/indent-warn.el b/test/jest/lint/indent-warn.el new file mode 100644 index 00000000..7e009664 --- /dev/null +++ b/test/jest/lint/indent-warn.el @@ -0,0 +1,31 @@ +;;; indent-warn.el --- Test indent linting -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;; 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 indent. +;; Should only cause warnings + +;;; Code: + +(defun indent-warn-foo () + (if 't + (message "Ok") + (message + "no"))) + +;;; indent-warn.el ends here diff --git a/test/jest/lint/regexp-warn.el b/test/jest/lint/regexp-warn.el new file mode 100644 index 00000000..5025297b --- /dev/null +++ b/test/jest/lint/regexp-warn.el @@ -0,0 +1,28 @@ +;;; regexp-warn.el --- Test regexp linting -*- lexical-binding: t; -*- + +;; Copyright (C) 2022-2024 the Eask authors. + +;; 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 regexp. +;; Should only cause warnings + +;;; Code: + +(defun regexp-warn-foo () + (re-search-backward "^[.:wrod:]$")) + +;;; regexp-warn.el ends here From 553fa0cc440582bac0b63135bdbb561290a070fc Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 17:17:31 -0800 Subject: [PATCH 02/14] elint should exit with code 1 when --strict --- lisp/lint/elint.el | 12 +++++++++++- test/jest/lint.test.js | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lisp/lint/elint.el b/lisp/lint/elint.el index cc4edac3..9a66bb73 100644 --- a/lisp/lint/elint.el +++ b/lisp/lint/elint.el @@ -32,6 +32,9 @@ ;; ;;; Core +(defvar eask-lint-elint--warnings-p nil + "Non-nil if any warnings were reported in the run.") + (defun eask-lint-elint--file (filename) "Run elint on FILENAME." (let* ((filename (expand-file-name filename)) @@ -41,6 +44,10 @@ (eask-msg "`%s` with elint" (ansi-green file)) (eask-with-verbosity 'debug (elint-file filename)) (eask-print-log-buffer (elint-get-log-buffer)) + (with-current-buffer (elint-get-log-buffer) + (goto-char (point-min)) + (when (re-search-forward ":Warning:" nil t) + (setq eask-lint-elint--warnings-p t))) (kill-buffer (elint-get-log-buffer)))) (eask-start @@ -56,7 +63,10 @@ (eask-msg "") (eask-info "(Total of %s file%s %s checked)" (length files) (eask--sinr files "" "s") - (eask--sinr files "has" "have"))) + (eask--sinr files "has" "have")) + (when (and eask-lint-elint--warnings-p + (eask-strict-p)) + (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns (eask-info "(No files match wildcard: %s)" diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index 1fede4e9..28efee91 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -80,12 +80,22 @@ describe("lint", () => { await ctx.runEask("lint elint declare-ok.el"); }); - // TODO --strict has no effect on elint - it.failing("should error given --strict", async () => { + it("should error given --strict", async () => { await expect( ctx.runEask("lint elint --strict checkdoc-fail.el"), ).rejects.toMatchObject({ code: 1 }); }); + + it("should check both files given --strict --allow-error", async () => { + await expect( + ctx.runEask( + "lint elint --strict --allow-error checkdoc-fail.el declare-ok.el", + ), + ).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("`declare-ok.el` with elint"), + }); + }); }); describe("elisp-lint", () => { From 38fbcb9e00d245a484e7c045b221bf1561a34ae5 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 17:41:23 -0800 Subject: [PATCH 03/14] Skip unnecessary file load and package install in indent linter --- lisp/lint/indent.el | 3 --- test/jest/lint.test.js | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lisp/lint/indent.el b/lisp/lint/indent.el index dc9e5467..5f85e60a 100644 --- a/lisp/lint/indent.el +++ b/lisp/lint/indent.el @@ -68,9 +68,6 @@ (let* ((patterns (eask-args)) (files (if patterns (eask-expand-file-specs (eask-args)) (eask-package-el-files)))) - (eask-install-dependencies) - (eask-with-verbosity 'debug - (ignore-errors (mapc #'load (eask-package-el-files)))) (cond ;; Files found, do the action! (files diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index 28efee91..cd97c3a2 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -150,9 +150,7 @@ describe("lint", () => { }); describe("indent", () => { - // TODO exits with 1 - // TODO prints "Don't call me!" - it.failing("should work on indent-warn.el", async () => { + it("should work on indent-warn.el", async () => { await ctx.runEask("lint indent indent-warn.el"); }); From aa7b461ba4748f71cb50e8ad67f2833a23e14694 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 19:03:03 -0800 Subject: [PATCH 04/14] Better examples for lint keywords tests --- test/jest/lint.test.js | 26 ++++++++++------ test/jest/lint/keywords-bad/Eask | 15 +++++++++ test/jest/lint/keywords-bad/keywords-ok.el | 36 ++++++++++++++++++++++ test/jest/lint/keywords-ok/Eask | 15 +++++++++ test/jest/lint/keywords-ok/keywords-ok.el | 36 ++++++++++++++++++++++ 5 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 test/jest/lint/keywords-bad/Eask create mode 100644 test/jest/lint/keywords-bad/keywords-ok.el create mode 100644 test/jest/lint/keywords-ok/Eask create mode 100644 test/jest/lint/keywords-ok/keywords-ok.el diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index cd97c3a2..23db1426 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -173,18 +173,26 @@ describe("lint", () => { }); describe("keywords", () => { - // TODO seems like keywords in actual file are ignored - // only those in Eask file are checked - // but those interfere with --strict handling in other commands + // always errors so --strict doesn't matter + // checks only Eask and x-pkg.el, so --allow-error doesn't matter - it.failing("should work", async () => { - await ctx.runEask("lint keywords"); + it("should error in an empty project", async () => { + const ctxEmpty = new TestContext("./test/jest/lint"); + await expect(ctxEmpty.runEask("lint keywords")).rejects.toThrow(); }); - it.failing("should error given --strict", async () => { - await expect(ctx.runEask("lint keywords --strict")).rejects.toMatchObject( - { code: 1 }, - ); + it("should work in keywords-ok", async () => { + const ctxOk = new TestContext("./test/jest/lint/keywords-ok"); + await expect(ctxOk.runEask("lint keywords")).resolves.toMatchObject({ + stderr: expect.stringContaining("No issues found"), + }); + }); + + it("should error in keywords-bad", async () => { + const ctxBad = new TestContext("./test/jest/lint/keywords-bad"); + await expect(ctxBad.runEask("lint keywords")).rejects.toMatchObject({ + stderr: expect.stringContaining("Missing a standard keyword"), + }); }); }); diff --git a/test/jest/lint/keywords-bad/Eask b/test/jest/lint/keywords-bad/Eask new file mode 100644 index 00000000..9089c7f2 --- /dev/null +++ b/test/jest/lint/keywords-bad/Eask @@ -0,0 +1,15 @@ +;; -*- mode: eask; lexical-binding: t -*- + +(package "keywords-ok" + "1.0.0" + "") + +(keywords "bag" "frog") + +(package-file "keywords-ok.el") + +(script "test" "echo \"Error: no test specified\" && exit 1") + +(source "gnu") + +(depends-on "emacs" "26.1") diff --git a/test/jest/lint/keywords-bad/keywords-ok.el b/test/jest/lint/keywords-bad/keywords-ok.el new file mode 100644 index 00000000..0d110f0b --- /dev/null +++ b/test/jest/lint/keywords-bad/keywords-ok.el @@ -0,0 +1,36 @@ +;;; keywords-ok.el --- summary -*- lexical-binding: t -*- + +;; Author: +;; Maintainer: +;; Version: 1.0.0 +;; Package-Requires: (dependencies) +;; Keywords: frog, bag + + +;; 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: + +;; commentary + +;;; Code: + +(message "Hello World!") + +(provide 'keywords-ok) + +;;; keywords-ok.el ends here diff --git a/test/jest/lint/keywords-ok/Eask b/test/jest/lint/keywords-ok/Eask new file mode 100644 index 00000000..a904c514 --- /dev/null +++ b/test/jest/lint/keywords-ok/Eask @@ -0,0 +1,15 @@ +;; -*- mode: eask; lexical-binding: t -*- + +(package "keywords-ok" + "1.0.0" + "") + +(keywords "tools") + +(package-file "keywords-ok.el") + +(script "test" "echo \"Error: no test specified\" && exit 1") + +(source "gnu") + +(depends-on "emacs" "26.1") diff --git a/test/jest/lint/keywords-ok/keywords-ok.el b/test/jest/lint/keywords-ok/keywords-ok.el new file mode 100644 index 00000000..4d8e9d65 --- /dev/null +++ b/test/jest/lint/keywords-ok/keywords-ok.el @@ -0,0 +1,36 @@ +;;; keywords-ok.el --- summary -*- lexical-binding: t -*- + +;; Author: +;; Maintainer: +;; Version: version +;; Package-Requires: (dependencies) +;; Keywords: tools + + +;; 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: + +;; commentary + +;;; Code: + +(message "Hello World!") + +(provide 'keywords-ok) + +;;; keywords-ok.el ends here From 5ccda08d29729e46a812af6eb435074c2ce900b0 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 19:14:16 -0800 Subject: [PATCH 05/14] lint package should respect --strict flag --- lisp/lint/package.el | 12 +++++++++++- test/jest/lint.test.js | 13 +++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lisp/lint/package.el b/lisp/lint/package.el index 676ddcdc..f23efb6e 100644 --- a/lisp/lint/package.el +++ b/lisp/lint/package.el @@ -43,6 +43,9 @@ ;; ;;; Core +(defvar eask-lint-package--warnings-p nil + "Non-nil if any warnings were reported in the run.") + (defconst eask-lint-package--version nil "`package-lint' version.") @@ -55,6 +58,10 @@ (with-current-buffer (find-file filename) (package-lint-current-buffer) (kill-current-buffer))) + (with-current-buffer "*Package-Lint*" + (goto-char (point-min)) + (when (re-search-forward "warning:" nil t) + (setq eask-lint-package--warnings-p t))) (eask-print-log-buffer "*Package-Lint*")) (eask-start @@ -77,7 +84,10 @@ (mapcar #'eask-lint-package--file files) (eask-msg "") (eask-info "(Total of %s file%s linted)" (length files) - (eask--sinr files "" "s"))) + (eask--sinr files "" "s")) + (when (and eask-lint-package--warnings-p + (eask-strict-p)) + (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns (eask-msg "") diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index 23db1426..1261686a 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -201,12 +201,21 @@ describe("lint", () => { await ctx.runEask("lint package declare-ok.el"); }); - // note that all files are checked anyway so --allow-error has no effect - it.failing("should error given --strict", async () => { + it("should error given --strict", async () => { await expect( ctx.runEask("lint package --strict declare-ok.el"), ).rejects.toMatchObject({ code: 1 }); }); + + // note that all files are checked anyway so --allow-error has no effect + it("should check all files given --allow-error", async () => { + await expect( + ctx.runEask("lint package --allow-error *.el"), + ).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("`declare-ok.el` with package-lint"), + }); + }); }); describe("regexps", () => { From 4fed46fe436a0871ec14e59322209b6dc9a13170 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 19:24:47 -0800 Subject: [PATCH 06/14] Update relint format matcher for relint 2.1 --- lisp/lint/regexps.el | 9 +++++---- test/jest/lint.test.js | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lisp/lint/regexps.el b/lisp/lint/regexps.el index 9540863c..0d6e5d55 100644 --- a/lisp/lint/regexps.el +++ b/lisp/lint/regexps.el @@ -47,12 +47,13 @@ (with-current-buffer (find-file filename) (setq errors (relint-buffer (current-buffer))) (dolist (err errors) - (let* ((msg (nth 0 err)) - (error-pos (nth 2 err)) - (severity (nth 5 err)) + (let* ((msg (seq-elt err 0)) + (error-pos (seq-elt err 2)) + (severity (seq-elt err 7)) (report-func (pcase severity (`error #'eask-error) - (`warning #'eask-warn)))) + (`warning #'eask-warn) + (_ #'eask-info)))) (funcall report-func "%s:%s %s: %s" file (line-number-at-pos error-pos) (capitalize (eask-2str severity)) msg))) diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index 1261686a..1e0b5872 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -223,7 +223,6 @@ describe("lint", () => { await ctx.runEask("lint regexps declare-ok.el"); }); - // TODO this prints a stack trace it("should error on regexp-warn.el", async () => { await expect( ctx.runEask("lint regexps regexp-warn.el"), From ef72bc8fad0b590f91ce3f08104d1d914e3f3c93 Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 19:35:41 -0800 Subject: [PATCH 07/14] lint regexps should respect --strict --- lisp/lint/regexps.el | 10 +++++++++- test/jest/lint.test.js | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lisp/lint/regexps.el b/lisp/lint/regexps.el index 0d6e5d55..ff09b347 100644 --- a/lisp/lint/regexps.el +++ b/lisp/lint/regexps.el @@ -37,6 +37,9 @@ (defconst eask-lint-regexps--relint-version nil "`relint' version.") +(defvar eask-lint-regexps--warnings-p nil + "Non-nil if any warnings were reported in the run.") + (defun eask-lint-regexps--relint-file (filename) "Package lint FILENAME." (let* ((filename (expand-file-name filename)) @@ -54,6 +57,8 @@ (`error #'eask-error) (`warning #'eask-warn) (_ #'eask-info)))) + (when (eq severity 'warning) + (setq eask-lint-regexps--warnings-p 't)) (funcall report-func "%s:%s %s: %s" file (line-number-at-pos error-pos) (capitalize (eask-2str severity)) msg))) @@ -80,7 +85,10 @@ (mapcar #'eask-lint-regexps--relint-file files) (eask-msg "") (eask-info "(Total of %s file%s linted)" (length files) - (eask--sinr files "" "s"))) + (eask--sinr files "" "s")) + (when (and eask-lint-regexps--warnings-p + (eask-strict-p)) + (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns (eask-msg "") diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index 1e0b5872..128d39e3 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -223,16 +223,25 @@ describe("lint", () => { await ctx.runEask("lint regexps declare-ok.el"); }); - it("should error on regexp-warn.el", async () => { + it("should have warnings on regexp-warn.el", async () => { await expect( ctx.runEask("lint regexps regexp-warn.el"), - ).rejects.toThrow(); + ).resolves.toMatchObject({ stderr: expect.stringContaining("Warning:") }); }); - it.failing("should work with --allow-error", async () => { + it("should error on regexp-warn.el with --strict", async () => { await expect( - ctx.runEask("lint regexps --allow-error regexp-warn.el declare-ok.el"), + ctx.runEask("lint regexps --strict regexp-warn.el"), + ).rejects.toMatchObject({ code: 1 }); + }); + + it("should work with --allow-error", async () => { + await expect( + ctx.runEask( + "lint regexps --allow-error --strict regexp-warn.el declare-ok.el", + ), ).rejects.toMatchObject({ + code: 1, stderr: expect.stringContaining("2 files linted"), }); }); From f4fa4474491c48da176747b0d008f8c1a2cd9d4b Mon Sep 17 00:00:00 2001 From: Josh Bax Date: Thu, 13 Nov 2025 20:14:38 -0800 Subject: [PATCH 08/14] lint elsa should exit with code 1 on errors or given --strict --- lisp/lint/elsa.el | 22 ++++++++++++++++++---- test/jest/lint.test.js | 15 +++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lisp/lint/elsa.el b/lisp/lint/elsa.el index fdc52e16..1861034e 100644 --- a/lisp/lint/elsa.el +++ b/lisp/lint/elsa.el @@ -41,6 +41,12 @@ (defconst eask-lint-elsa--version nil "Elsa version.") +(defvar eask-lint-elsa--warnings-p nil + "Non-nil if any warnings were reported in the run.") + +(defvar eask-lint-elsa--errors-p nil + "Non-nil if any errors were reported in the run.") + (defun eask-lint-elsa--analyse-file (filename) "Process FILENAME." (let* ((filename (expand-file-name filename)) @@ -49,12 +55,16 @@ (eask-msg "") (eask-msg "`%s` with elsa (%s)" (ansi-green file) eask-lint-elsa--version) (eask-with-verbosity 'debug - (setq errors (oref (elsa-analyse-file filename elsa-global-state) errors))) + (setq errors (oref (elsa-analyse-file filename elsa-global-state) errors))) (if errors (--each (reverse errors) (let ((line (string-trim (concat file ":" (elsa-message-format it))))) - (cond ((string-match-p "[: ][Ee]rror:" line) (eask-error line)) - ((string-match-p "[: ][Ww]arning:" line) (eask-warn line)) + (cond ((string-match-p "[: ][Ee]rror:" line) + (setq eask-lint-elsa--errors-p 't) + (eask-error line)) + ((string-match-p "[: ][Ww]arning:" line) + (setq eask-lint-elsa--warnings-p 't) + (eask-warn line)) (t (eask-log line))))) (eask-msg "No issues found")))) @@ -77,7 +87,11 @@ (mapcar #'eask-lint-elsa--analyse-file files) (eask-msg "") (eask-info "(Total of %s file%s linted)" (length files) - (eask--sinr files "" "s"))) + (eask--sinr files "" "s")) + (when (or eask-lint-elsa--errors-p + (and eask-lint-elsa--warnings-p + (eask-strict-p))) + (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns (eask-msg "") diff --git a/test/jest/lint.test.js b/test/jest/lint.test.js index 128d39e3..aeed67b5 100644 --- a/test/jest/lint.test.js +++ b/test/jest/lint.test.js @@ -125,7 +125,8 @@ describe("lint", () => { }); describe("elsa", () => { - // TODO prints a lot of garbage + // prints a lot of garbage + // likely an upstream problem, unclear how to fix it("should work on elisp-lint-ok.el", async () => { await ctx.runEask("lint elsa elisp-lint-ok.el"); }); @@ -134,19 +135,25 @@ describe("lint", () => { await ctx.runEask("lint elsa elsa-warn.el"); }); - // TODO prints out "error" but no exit code it("should error on declare-ok.el", async () => { await expect( ctx.runEask("lint elsa declare-ok.el"), ).rejects.toMatchObject({ code: 1 }); }); - // TODO strict has no effect - it.failing("should error given --strict", async () => { + it("should error given --strict", async () => { await expect( ctx.runEask("lint elsa --strict elsa-warn.el"), ).rejects.toMatchObject({ code: 1 }); }); + + it("should run all files given --allow-error", async () => { + await expect( + ctx.runEask( + "lint elsa --strict --allow-errors elsa-warn.el elisp-lint-ok.el", + ), + ).rejects.toMatchObject({ code: 1 }); + }); }); describe("indent", () => { From 2150ff093ea788e1421804581cb0f4316c2be143 Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Fri, 14 Nov 2025 14:33:18 +0800 Subject: [PATCH 09/14] fix: Indentation and clean up logic --- lisp/lint/elint.el | 22 ++++++++++++++-------- lisp/lint/elsa.el | 17 +++++++++++------ lisp/lint/package.el | 22 +++++++++++++++------- lisp/lint/regexps.el | 15 ++++++++++----- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/lisp/lint/elint.el b/lisp/lint/elint.el index 9a66bb73..c04e4c07 100644 --- a/lisp/lint/elint.el +++ b/lisp/lint/elint.el @@ -43,12 +43,18 @@ (eask-lint-first-newline) (eask-msg "`%s` with elint" (ansi-green file)) (eask-with-verbosity 'debug (elint-file filename)) - (eask-print-log-buffer (elint-get-log-buffer)) - (with-current-buffer (elint-get-log-buffer) - (goto-char (point-min)) - (when (re-search-forward ":Warning:" nil t) - (setq eask-lint-elint--warnings-p t))) - (kill-buffer (elint-get-log-buffer)))) + (let ((log-buffer (elint-get-log-buffer))) + (eask-print-log-buffer log-buffer) + (with-current-buffer log-buffer + (goto-char (point-min)) + (when (re-search-forward ":Warning:" nil t) + (setq eask-lint-elint--warnings-p t))) + (kill-buffer log-buffer)))) + +(defun eask-lint-elint--has-error-p () + "Return non-nil if we should report error for exit status." + (and eask-lint-elint--warnings-p + (eask-strict-p))) (eask-start (require 'elint) @@ -64,8 +70,8 @@ (eask-info "(Total of %s file%s %s checked)" (length files) (eask--sinr files "" "s") (eask--sinr files "has" "have")) - (when (and eask-lint-elint--warnings-p - (eask-strict-p)) + ;; Report error. + (when (eask-lint-elint--has-error-p) (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns diff --git a/lisp/lint/elsa.el b/lisp/lint/elsa.el index 1861034e..d7c08454 100644 --- a/lisp/lint/elsa.el +++ b/lisp/lint/elsa.el @@ -55,19 +55,25 @@ (eask-msg "") (eask-msg "`%s` with elsa (%s)" (ansi-green file) eask-lint-elsa--version) (eask-with-verbosity 'debug - (setq errors (oref (elsa-analyse-file filename elsa-global-state) errors))) + (setq errors (oref (elsa-analyse-file filename elsa-global-state) errors))) (if errors (--each (reverse errors) (let ((line (string-trim (concat file ":" (elsa-message-format it))))) (cond ((string-match-p "[: ][Ee]rror:" line) - (setq eask-lint-elsa--errors-p 't) + (setq eask-lint-elsa--errors-p t) (eask-error line)) ((string-match-p "[: ][Ww]arning:" line) - (setq eask-lint-elsa--warnings-p 't) + (setq eask-lint-elsa--warnings-p t) (eask-warn line)) (t (eask-log line))))) (eask-msg "No issues found")))) +(defun eask-lint-elsa--has-error-p () + "Return non-nil if we should report error for exit status." + (or eask-lint-elsa--errors-p + (and eask-lint-elsa--warnings-p + (eask-strict-p)))) + (eask-start ;; Preparation (eask-archive-install-packages '("gnu" "melpa") @@ -88,9 +94,8 @@ (eask-msg "") (eask-info "(Total of %s file%s linted)" (length files) (eask--sinr files "" "s")) - (when (or eask-lint-elsa--errors-p - (and eask-lint-elsa--warnings-p - (eask-strict-p))) + ;; Report error. + (when (eask-lint-elsa--has-error-p) (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns diff --git a/lisp/lint/package.el b/lisp/lint/package.el index f23efb6e..a2f4d424 100644 --- a/lisp/lint/package.el +++ b/lisp/lint/package.el @@ -43,6 +43,9 @@ ;; ;;; Core +(defconst eask-lint-package--buffer-name "*Package-Lint*" + "The buffer name for `package-lint's log file.") + (defvar eask-lint-package--warnings-p nil "Non-nil if any warnings were reported in the run.") @@ -58,11 +61,16 @@ (with-current-buffer (find-file filename) (package-lint-current-buffer) (kill-current-buffer))) - (with-current-buffer "*Package-Lint*" - (goto-char (point-min)) - (when (re-search-forward "warning:" nil t) - (setq eask-lint-package--warnings-p t))) - (eask-print-log-buffer "*Package-Lint*")) + (with-current-buffer eask-lint-package--buffer-name + (goto-char (point-min)) + (when (re-search-forward "warning:" nil t) + (setq eask-lint-package--warnings-p t))) + (eask-print-log-buffer eask-lint-package--buffer-name)) + +(defun eask-lint-package--has-error-p () + "Return non-nil if we should report error for exit status." + (and eask-lint-package--warnings-p + (eask-strict-p))) (eask-start ;; Preparation @@ -85,8 +93,8 @@ (eask-msg "") (eask-info "(Total of %s file%s linted)" (length files) (eask--sinr files "" "s")) - (when (and eask-lint-package--warnings-p - (eask-strict-p)) + ;; Report error. + (when (eask-lint-package--has-error-p) (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns diff --git a/lisp/lint/regexps.el b/lisp/lint/regexps.el index ff09b347..779d4c83 100644 --- a/lisp/lint/regexps.el +++ b/lisp/lint/regexps.el @@ -54,11 +54,11 @@ (error-pos (seq-elt err 2)) (severity (seq-elt err 7)) (report-func (pcase severity - (`error #'eask-error) + (`error #'eask-error) (`warning #'eask-warn) - (_ #'eask-info)))) + (_ #'eask-info)))) (when (eq severity 'warning) - (setq eask-lint-regexps--warnings-p 't)) + (setq eask-lint-regexps--warnings-p t)) (funcall report-func "%s:%s %s: %s" file (line-number-at-pos error-pos) (capitalize (eask-2str severity)) msg))) @@ -66,6 +66,11 @@ (eask-msg "No issues found")) (kill-current-buffer)))) +(defun eask-lint-regexps--has-error-p () + "Return non-nil if we should report error for exit status." + (and eask-lint-regexps--warnings-p + (eask-strict-p))) + (eask-start ;; Preparation (eask-archive-install-packages '("gnu") @@ -86,8 +91,8 @@ (eask-msg "") (eask-info "(Total of %s file%s linted)" (length files) (eask--sinr files "" "s")) - (when (and eask-lint-regexps--warnings-p - (eask-strict-p)) + ;; Report error. + (when (eask-lint-regexps--has-error-p) (eask--exit 'failure))) ;; Pattern defined, but no file found! (patterns From 05c64f320000cdf67fc5ff22c1aa250e8bd3f83c Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Fri, 14 Nov 2025 15:31:39 +0800 Subject: [PATCH 10/14] fix: output log should be clean string --- lisp/_prepare.el | 68 +++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/lisp/_prepare.el b/lisp/_prepare.el index 77915034..09fd4343 100644 --- a/lisp/_prepare.el +++ b/lisp/_prepare.el @@ -479,10 +479,15 @@ You can pass BUFFER-OR-NAME to replace current buffer." (with-current-buffer (or buffer-or-name (current-buffer)) (goto-char (point-min)) (while (not (eobp)) - (let ((line (buffer-substring-no-properties (line-beginning-position) (line-end-position)))) - (cond ((string-match-p "[: ][Ee]rror: " line) (eask-error line)) - ((string-match-p "[: ][Ww]arning: " line) (eask-warn line)) - (t (eask-log line)))) + (let ((line (buffer-substring-no-properties (line-beginning-position) + (line-end-position)))) + ;; The variable `line' can contains format specifier, avoid it with `%s'! + (cond ((string-match-p "[: ][Ee]rror: " line) + (eask-error "%s" line)) + ((string-match-p "[: ][Ww]arning: " line) + (eask-warn "%s" line)) + (t + (eask-log "%s" line)))) (forward-line 1)))) (defun eask-delete-file (filename) @@ -1821,7 +1826,8 @@ Execute forms BODY limit by the verbosity level (SYMBOL)." (defun eask--ansi (symbol string) "Paint STRING with color defined by log level (SYMBOL)." (if-let* ((ansi-function (cdr (assq symbol eask-level-color)))) - (funcall ansi-function string) + ;; The `%s` is use to avoid `not enough arguments for string` error. + (funcall ansi-function "%s" string) string)) (defun eask--format (prefix fmt &rest args) @@ -1829,41 +1835,39 @@ Execute forms BODY limit by the verbosity level (SYMBOL)." Argument PREFIX is a string identify the type of this messages. Arguments FMT and ARGS are used to pass through function `format'." - (apply #'format - (concat (when eask-timestamps (format-time-string "%Y-%m-%d %H:%M:%S ")) - (when eask-log-level (concat prefix " ")) - fmt) - args)) + (concat (when eask-timestamps (format-time-string "%Y-%m-%d %H:%M:%S ")) + (when eask-log-level (concat prefix " ")) + (apply #'format fmt args))) -(defun eask--msg (symbol prefix msg &rest args) +(defun eask--msg (symbol prefix fmt &rest args) "If level (SYMBOL) is at or below `eask-verbosity'; then, log the message. -For arguments PREFIX, MSG and ARGS, please see funtion `eask--format' for the +For arguments PREFIX, FMT and ARGS, please see funtion `eask--format' for the detials." (eask-with-verbosity symbol - (let* ((string (apply #'eask--format prefix msg args)) - (output (eask--ansi symbol string)) + (let* ((output (apply #'eask--format prefix fmt args)) + (output (eask--ansi symbol output)) (output (eask--msg-displayable-kwds output)) ; Don't color, but replace it! (func (cl-case symbol ((or error warn) symbol) - (t #'message)))) + (t #'message)))) (funcall func "%s" output)))) -(defun eask-debug (msg &rest args) - "Send debug message; see function `eask--msg' for arguments MSG and ARGS." - (apply #'eask--msg 'debug "[DEBUG]" msg args)) -(defun eask-log (msg &rest args) - "Send log message; see function `eask--msg' for arguments MSG and ARGS." - (apply #'eask--msg 'log "[LOG]" msg args)) -(defun eask-info (msg &rest args) - "Send info message; see function `eask--msg' for arguments MSG and ARGS." - (apply #'eask--msg 'info "[INFO]" msg args)) -(defun eask-warn (msg &rest args) - "Send warn message; see function `eask--msg' for arguments MSG and ARGS." - (apply #'eask--msg 'warn "[WARNING]" msg args)) -(defun eask-error (msg &rest args) - "Send error message; see function `eask--msg' for arguments MSG and ARGS." - (apply #'eask--msg 'error "[ERROR]" msg args)) +(defun eask-debug (fmt &rest args) + "Send debug message; see function `eask--msg' for arguments FMT and ARGS." + (apply #'eask--msg 'debug "[DEBUG]" fmt args)) +(defun eask-log (fmt &rest args) + "Send log message; see function `eask--msg' for arguments FMT and ARGS." + (apply #'eask--msg 'log "[LOG]" fmt args)) +(defun eask-info (fmt &rest args) + "Send info message; see function `eask--msg' for arguments FMT and ARGS." + (apply #'eask--msg 'info "[INFO]" fmt args)) +(defun eask-warn (fmt &rest args) + "Send warn message; see function `eask--msg' for arguments FMT and ARGS." + (apply #'eask--msg 'warn "[WARNING]" fmt args)) +(defun eask-error (fmt &rest args) + "Send error message; see function `eask--msg' for arguments FMT and ARGS." + (apply #'eask--msg 'error "[ERROR]" fmt args)) (defun eask--msg-char-displayable (char replacement s) "Ensure CHAR is displayable in S; if not, we fallback to REPLACEMENT @@ -1981,8 +1985,8 @@ Argument ARGS are direct arguments for functions `eask-error' or `eask-warn'." (defun eask--trigger-error () "Trigger error event." (when (and (not eask--ignore-error-p) - (not (eask-checker-p))) ; ignore when checking Eask-file - (if (eask-allow-error-p) ; Trigger error at the right time + (not (eask-checker-p))) ; Ignore when checking Eask-file. + (if (eask-allow-error-p) ; Trigger error at the right time. (add-hook 'eask-after-command-hook #'eask--exit) (eask--exit)))) From a802cc4701425b70c2e1b2f262d0ff917752ac44 Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Fri, 14 Nov 2025 15:32:09 +0800 Subject: [PATCH 11/14] fix: Revert load deps and files for indent-lint command --- lisp/lint/indent.el | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lisp/lint/indent.el b/lisp/lint/indent.el index 5f85e60a..f322ce10 100644 --- a/lisp/lint/indent.el +++ b/lisp/lint/indent.el @@ -68,6 +68,12 @@ (let* ((patterns (eask-args)) (files (if patterns (eask-expand-file-specs (eask-args)) (eask-package-el-files)))) + ;; XXX: Load all dependencies and elisp files to ensure + ;; all macros' indentation is applied. + (progn + (eask-install-dependencies) + (eask-with-verbosity 'debug + (ignore-errors (mapc #'load (eask-package-el-files))))) (cond ;; Files found, do the action! (files From adda12609aef28db9132c995b018ae71eb1bd86c Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Fri, 14 Nov 2025 15:37:18 +0800 Subject: [PATCH 12/14] fix: Handle indent list infos can be missing --- lisp/lint/indent.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lisp/lint/indent.el b/lisp/lint/indent.el index f322ce10..ea6c3e96 100644 --- a/lisp/lint/indent.el +++ b/lisp/lint/indent.el @@ -53,9 +53,10 @@ (bs (buffer-string))) (eask-with-temp-buffer (insert bs)) (eask--silent (indent-region (point-min) (point-max))) - (if (/= tick (buffer-modified-tick)) + (if-let* (((/= tick (buffer-modified-tick))) + (infos (eask-lint-indent--undo-infos buffer-undo-list))) ;; Indentation changed: warn for each line. - (dolist (info (eask-lint-indent--undo-infos buffer-undo-list)) + (dolist (info infos) (let* ((line (nth 0 info)) (column (nth 1 info)) (current (eask-with-buffer From 57e7ae953cd4cf424348ea096e7895aedb353c8c Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Fri, 14 Nov 2025 15:57:52 +0800 Subject: [PATCH 13/14] feat: Introduce global error/warn flag --- lisp/_prepare.el | 8 ++++++++ lisp/lint/elint.el | 9 +-------- lisp/lint/elsa.el | 12 ++---------- lisp/lint/package.el | 14 ++------------ lisp/lint/regexps.el | 7 +------ 5 files changed, 14 insertions(+), 36 deletions(-) diff --git a/lisp/_prepare.el b/lisp/_prepare.el index 09fd4343..a929a421 100644 --- a/lisp/_prepare.el +++ b/lisp/_prepare.el @@ -1967,6 +1967,12 @@ Argument ARGS are direct arguments for functions `eask-error' or `eask-warn'." (defvar eask-inhibit-error-message nil "Non-nil to stop error/warning message.") +(defvar eask--has-error-p nil + "Non-nil if an error has occurred.") + +(defvar eask--has-warn-p nil + "Non-nil if a warning has occurred.") + (defmacro eask-ignore-errors (&rest body) "Execute BODY without killing the process." (declare (indent 0) (debug t)) @@ -1994,6 +2000,7 @@ Argument ARGS are direct arguments for functions `eask-error' or `eask-warn'." "On error. Arguments FNC and ARGS are used for advice `:around'." + (setq eask--has-error-p t) (let ((msg (eask--ansi 'error (apply #'format-message args)))) (unless eask-inhibit-error-message (eask--unsilent (eask-msg "%s" msg))) @@ -2005,6 +2012,7 @@ Arguments FNC and ARGS are used for advice `:around'." "On warn. Arguments FNC and ARGS are used for advice `:around'." + (setq eask--has-warn-p t) (let ((msg (eask--ansi 'warn (apply #'format-message args)))) (unless eask-inhibit-error-message (eask--unsilent (eask-msg "%s" msg))) diff --git a/lisp/lint/elint.el b/lisp/lint/elint.el index c04e4c07..278f4815 100644 --- a/lisp/lint/elint.el +++ b/lisp/lint/elint.el @@ -32,9 +32,6 @@ ;; ;;; Core -(defvar eask-lint-elint--warnings-p nil - "Non-nil if any warnings were reported in the run.") - (defun eask-lint-elint--file (filename) "Run elint on FILENAME." (let* ((filename (expand-file-name filename)) @@ -45,15 +42,11 @@ (eask-with-verbosity 'debug (elint-file filename)) (let ((log-buffer (elint-get-log-buffer))) (eask-print-log-buffer log-buffer) - (with-current-buffer log-buffer - (goto-char (point-min)) - (when (re-search-forward ":Warning:" nil t) - (setq eask-lint-elint--warnings-p t))) (kill-buffer log-buffer)))) (defun eask-lint-elint--has-error-p () "Return non-nil if we should report error for exit status." - (and eask-lint-elint--warnings-p + (and eask--has-warn-p (eask-strict-p))) (eask-start diff --git a/lisp/lint/elsa.el b/lisp/lint/elsa.el index d7c08454..21392432 100644 --- a/lisp/lint/elsa.el +++ b/lisp/lint/elsa.el @@ -41,12 +41,6 @@ (defconst eask-lint-elsa--version nil "Elsa version.") -(defvar eask-lint-elsa--warnings-p nil - "Non-nil if any warnings were reported in the run.") - -(defvar eask-lint-elsa--errors-p nil - "Non-nil if any errors were reported in the run.") - (defun eask-lint-elsa--analyse-file (filename) "Process FILENAME." (let* ((filename (expand-file-name filename)) @@ -60,18 +54,16 @@ (--each (reverse errors) (let ((line (string-trim (concat file ":" (elsa-message-format it))))) (cond ((string-match-p "[: ][Ee]rror:" line) - (setq eask-lint-elsa--errors-p t) (eask-error line)) ((string-match-p "[: ][Ww]arning:" line) - (setq eask-lint-elsa--warnings-p t) (eask-warn line)) (t (eask-log line))))) (eask-msg "No issues found")))) (defun eask-lint-elsa--has-error-p () "Return non-nil if we should report error for exit status." - (or eask-lint-elsa--errors-p - (and eask-lint-elsa--warnings-p + (or eask--has-error-p + (and eask--has-warn-p (eask-strict-p)))) (eask-start diff --git a/lisp/lint/package.el b/lisp/lint/package.el index a2f4d424..9ba6d09b 100644 --- a/lisp/lint/package.el +++ b/lisp/lint/package.el @@ -43,12 +43,6 @@ ;; ;;; Core -(defconst eask-lint-package--buffer-name "*Package-Lint*" - "The buffer name for `package-lint's log file.") - -(defvar eask-lint-package--warnings-p nil - "Non-nil if any warnings were reported in the run.") - (defconst eask-lint-package--version nil "`package-lint' version.") @@ -61,15 +55,11 @@ (with-current-buffer (find-file filename) (package-lint-current-buffer) (kill-current-buffer))) - (with-current-buffer eask-lint-package--buffer-name - (goto-char (point-min)) - (when (re-search-forward "warning:" nil t) - (setq eask-lint-package--warnings-p t))) - (eask-print-log-buffer eask-lint-package--buffer-name)) + (eask-print-log-buffer "*Package-Lint*")) (defun eask-lint-package--has-error-p () "Return non-nil if we should report error for exit status." - (and eask-lint-package--warnings-p + (and eask--has-warn-p (eask-strict-p))) (eask-start diff --git a/lisp/lint/regexps.el b/lisp/lint/regexps.el index 779d4c83..5818ef3d 100644 --- a/lisp/lint/regexps.el +++ b/lisp/lint/regexps.el @@ -37,9 +37,6 @@ (defconst eask-lint-regexps--relint-version nil "`relint' version.") -(defvar eask-lint-regexps--warnings-p nil - "Non-nil if any warnings were reported in the run.") - (defun eask-lint-regexps--relint-file (filename) "Package lint FILENAME." (let* ((filename (expand-file-name filename)) @@ -57,8 +54,6 @@ (`error #'eask-error) (`warning #'eask-warn) (_ #'eask-info)))) - (when (eq severity 'warning) - (setq eask-lint-regexps--warnings-p t)) (funcall report-func "%s:%s %s: %s" file (line-number-at-pos error-pos) (capitalize (eask-2str severity)) msg))) @@ -68,7 +63,7 @@ (defun eask-lint-regexps--has-error-p () "Return non-nil if we should report error for exit status." - (and eask-lint-regexps--warnings-p + (and eask--has-warn-p (eask-strict-p))) (eask-start From 29b171c2c38f3984f724457346c493de164ab6c2 Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Fri, 14 Nov 2025 16:31:52 +0800 Subject: [PATCH 14/14] fix: Copyright info --- test/jest/lint/checkdoc-fail.el | 2 +- test/jest/lint/declare-fail.el | 2 +- test/jest/lint/declare-ok.el | 2 +- test/jest/lint/elisp-lint-ok.el | 2 +- test/jest/lint/elsa-warn.el | 2 +- test/jest/lint/indent-warn.el | 2 +- test/jest/lint/regexp-warn.el | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/jest/lint/checkdoc-fail.el b/test/jest/lint/checkdoc-fail.el index ecbc4aad..f521198d 100644 --- a/test/jest/lint/checkdoc-fail.el +++ b/test/jest/lint/checkdoc-fail.el @@ -1,6 +1,6 @@ ;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;; 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 diff --git a/test/jest/lint/declare-fail.el b/test/jest/lint/declare-fail.el index fa2739e3..2a3207e5 100644 --- a/test/jest/lint/declare-fail.el +++ b/test/jest/lint/declare-fail.el @@ -1,6 +1,6 @@ ;;; declare-fail.el --- Test lint declare -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;; 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 diff --git a/test/jest/lint/declare-ok.el b/test/jest/lint/declare-ok.el index 0ff0ff03..70ab1bfe 100644 --- a/test/jest/lint/declare-ok.el +++ b/test/jest/lint/declare-ok.el @@ -1,6 +1,6 @@ ;;; ert-test.el --- Test the command ert -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;; 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 diff --git a/test/jest/lint/elisp-lint-ok.el b/test/jest/lint/elisp-lint-ok.el index 4b25a403..29915e81 100644 --- a/test/jest/lint/elisp-lint-ok.el +++ b/test/jest/lint/elisp-lint-ok.el @@ -1,6 +1,6 @@ ;;; elisp-lint-ok.el --- Test the linting -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;;; Version: 0.0.1 ;;; URL: https://foo.com diff --git a/test/jest/lint/elsa-warn.el b/test/jest/lint/elsa-warn.el index a91f18c9..d7e9ace4 100644 --- a/test/jest/lint/elsa-warn.el +++ b/test/jest/lint/elsa-warn.el @@ -1,6 +1,6 @@ ;;; elsa-warn.el --- Test elsa linting -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;; 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 diff --git a/test/jest/lint/indent-warn.el b/test/jest/lint/indent-warn.el index 7e009664..d2d6156e 100644 --- a/test/jest/lint/indent-warn.el +++ b/test/jest/lint/indent-warn.el @@ -1,6 +1,6 @@ ;;; indent-warn.el --- Test indent linting -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;; 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 diff --git a/test/jest/lint/regexp-warn.el b/test/jest/lint/regexp-warn.el index 5025297b..ecfdc2b2 100644 --- a/test/jest/lint/regexp-warn.el +++ b/test/jest/lint/regexp-warn.el @@ -1,6 +1,6 @@ ;;; regexp-warn.el --- Test regexp linting -*- lexical-binding: t; -*- -;; Copyright (C) 2022-2024 the Eask authors. +;; Copyright (C) 2025 the Eask authors. ;; 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