Subject: bug#76471: [PATCH] 31.0.50; dockerfile-ts-mode lacks fontification for most grammar-elements in the Dockerfile AST

From: Jostein Kjønigsen <[email-masked]>
Date: Fri, 21 Feb 2025 15:01:52 +0100

Hey everyone.

I'm using dockerfile-ts-mode to work with Docker-files, and while it technically does work, it does not highlight most things you want highlighted in a language-specific major-mode, making its use over fundamental-mode fairly limited. As a matter of fact the MELPA package dockerfile-mode currently provides more rich fontification than dockerfile-ts-mode does, even without the tree-sitter AST.

Rather than just complain, I decided to do something about that, and created the patch attached to this bug :)

￼

This patch adds support for fontifying the following grammar-elements:

- image-declarations (image-name, image-tag & image alias)
- strings in more general terms
- string-expansion statements
- treat path-values as strings
- identifiers names for ENV and ARG statements
- argument values for ENV and ARG statements

Most changes here should be fairly uncontroversial. Attached below are screenshots showing before and after patch to provide an easy reference of discussion.

One change I did, where someone might have opinions, is to Dockerfile FROM-AS statements, like the one below:

     FROM python:3.13-slim AS build

A Dockerfile can have many FROM-AS statements, where each one declares a target which can be built. In my opinion that makes such a statement a -function declaration- for a function which builds that target, based on the instructions provided underneath it.

As such I changed the fontification of these statements from font-lock-constant-face to font-lock-function-name-face (which in the existing code is the same face used for numerical values).

I think this makes more sense, and makes the visually parsing files way more intuitive, efficient and logical, especially when you have many targets.

Without this change, all fontification tended to go in the "same direction", making it hard to distinguish language-elements based on fontification alone.

Let me know what you think. Screenshots below!

Cheers
Jostein

After - WITH patch:

￼

Before - WITHOUT patch:

￼

In GNU Emacs 31.0.50 (build 15, aarch64-apple-darwin24.0.0, NS
 appkit-2566.00 Version 15.0.1 (Build 24A348)) of 2025-02-13 built on
 SOK67R3KWV97
Repository revision: ddcbdbc8150eec16ce3154208f1bae4463a5a709
Repository branch: master
Windowing system distributor 'Apple', version 10.3.2575
System Description:  macOS 15.3.1

Configured using:
 'configure --with-tree-sitter --with-native-compilation --with-json
 --with-imagemagick --with-harfbuzz'

Configured features:
ACL GLIB GNUTLS IMAGEMAGICK LCMS2 LIBXML2 MODULES NATIVE_COMP NOTIFY
KQUEUE NS PDUMPER PNG RSVG SQLITE3 THREADS TOOLKIT_SCROLL_BARS
TREE_SITTER WEBP XIM ZLIB

Important settings:
  value of $LC_ALL: en_US.UTF-8
  value of $LC_CTYPE: UTF-8
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Dockerfile

Minor modes in effect:
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  global-undo-tree-mode: t
  undo-tree-mode: t
  electric-pair-mode: t
  highlight-symbol-mode: t
  flycheck-mode: t
  editorconfig-mode: t
  company-mode: t
  indent-bars--ts-mode: t
  indent-bars-mode: t
  eglot--managed-mode: t
  flymake-mode: t
  which-function-mode: t
  helm-mode: t
  helm-minibuffer-history-mode: t
  async-bytecomp-package-mode: t
  delete-selection-mode: t
  global-auto-revert-mode: t
  yas-global-mode: t
  yas-minor-mode: t
  poetry-tracking-mode: t
  global-nlinum-mode: t
  nlinum-mode: t
  ido-yes-or-no-mode: t
  override-global-mode: t
  server-mode: t
  global-hl-line-mode: t
  pixel-scroll-precision-mode: t
  doom-modeline-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  minibuffer-regexp-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  hs-minor-mode: t

Load-path shadows:
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-go hides /Users/josteink/.emacs.d/elpa/structur/combobulate-go
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-css hides /Users/josteink/.emacs.d/elpa/structur/combobulate-css
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-html hides /Users/josteink/.emacs.d/elpa/structur/combobulate-html
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-display hides /Users/josteink/.emacs.d/elpa/structur/combobulate-display
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-manipulation hides /Users/josteink/.emacs.d/elpa/structur/combobulate-manipulation
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-debug hides /Users/josteink/.emacs.d/elpa/structur/combobulate-debug
/Users/josteink/.emacs.d/elpa/combobulate/.ts-setup hides /Users/josteink/.emacs.d/elpa/structur/.ts-setup
/Users/josteink/.emacs.d/elpa/combobulate/.ts-test hides /Users/josteink/.emacs.d/elpa/structur/.ts-test
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-js-ts hides /Users/josteink/.emacs.d/elpa/structur/combobulate-js-ts
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-navigation hides /Users/josteink/.emacs.d/elpa/structur/combobulate-navigation
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-setup hides /Users/josteink/.emacs.d/elpa/structur/combobulate-setup
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-misc hides /Users/josteink/.emacs.d/elpa/structur/combobulate-misc
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-rules hides /Users/josteink/.emacs.d/elpa/structur/combobulate-rules
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-json hides /Users/josteink/.emacs.d/elpa/structur/combobulate-json
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-toml hides /Users/josteink/.emacs.d/elpa/structur/combobulate-toml
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-ztree hides /Users/josteink/.emacs.d/elpa/structur/combobulate-ztree
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-envelope hides /Users/josteink/.emacs.d/elpa/structur/combobulate-envelope
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-cursor hides /Users/josteink/.emacs.d/elpa/structur/combobulate-cursor
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-query hides /Users/josteink/.emacs.d/elpa/structur/combobulate-query
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-interface hides /Users/josteink/.emacs.d/elpa/structur/combobulate-interface
/Users/josteink/.emacs.d/elpa/combobulate/combobulate hides /Users/josteink/.emacs.d/elpa/structur/combobulate
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-settings hides /Users/josteink/.emacs.d/elpa/structur/combobulate-settings
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-yaml hides /Users/josteink/.emacs.d/elpa/structur/combobulate-yaml
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-procedure hides /Users/josteink/.emacs.d/elpa/structur/combobulate-procedure
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-ui hides /Users/josteink/.emacs.d/elpa/structur/combobulate-ui
/Users/josteink/.emacs.d/elpa/combobulate/combobulate-python hides /Users/josteink/.emacs.d/elpa/structur/combobulate-python
/Users/josteink/.emacs.d/elpa/transient-20240421.1327/transient hides /Users/josteink/build/emacs/lisp/transient
/Users/josteink/.emacs.d/elpa/editorconfig-20240318.2049/editorconfig hides /Users/josteink/build/emacs/lisp/editorconfig
/Users/josteink/.emacs.d/elpa/editorconfig-20240318.2049/editorconfig-conf-mode hides /Users/josteink/build/emacs/lisp/editorconfig-conf-mode
/Users/josteink/.emacs.d/elpa/editorconfig-20240318.2049/editorconfig-core hides /Users/josteink/build/emacs/lisp/editorconfig-core
/Users/josteink/.emacs.d/elpa/editorconfig-20240318.2049/editorconfig-core-handle hides /Users/josteink/build/emacs/lisp/editorconfig-core-handle
/Users/josteink/.emacs.d/elpa/editorconfig-20240318.2049/editorconfig-fnmatch hides /Users/josteink/build/emacs/lisp/editorconfig-fnmatch

Features:
(shadow sort mail-extr emacsbug help-fns radix-tree tabify vc goto-addr
git-rebase magit-extras magit-bookmark magit-submodule magit-blame
magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch
magit-clone magit-remote magit-commit magit-sequence magit-notes
magit-worktree magit-tag magit-merge magit-branch magit-reset
magit-files magit-refs magit-status magit magit-repos magit-apply
magit-wip magit-log magit-diff smerge-mode git-commit log-edit pcvs-util
magit-core magit-autorevert magit-margin magit-transient magit-process
with-editor magit-mode magit-git magit-base magit-section cursor-sensor
crm undo-tree queue bug-reference markdown-mode dockerfile-mode lisp-mnt
elec-pair dockerfile-ts-mode helm-command helm-elisp helm-eval edebug
misearch multi-isearch vc-git vc-dispatcher helm-bookmark helm-net
helm-adaptive helm-info bookmark winner tramp-archive tramp-gvfs
tramp-cache time-stamp tramp-sh add-log pulse ido-completing-read+
memoize minibuf-eldef org-duration diary-lib diary-loaddefs cal-iso
oc-basic ol-eww ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect gnus-art
mm-uu mml2015 mm-view mml-smime smime dig gnus-sum gnus-group gnus-undo
gnus-start gnus-dbus dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo
gnus-spec gnus-int gnus-range gnus-win ol-docview doc-view jka-compr
ol-bibtex bibtex ol-bbdb ol-w3m ol-doi org-link-doi org-agenda
org-element org-persist org-id org-element-ast inline avl-tree
org-refile elisp-slime-nav highlight-symbol flycheck editorconfig
editorconfig-core editorconfig-core-handle editorconfig-fnmatch
company-oddmuse company-keywords company-etags etags fileloop
company-gtags company-dabbrev-code company-dabbrev company-files
company-clang company-capf company-cmake company-semantic
company-template company-bbdb company indent-bars-ts indent-bars
face-remap color eglot tree-widget external-completion jsonrpc flymake
diff ert ewoc debug backtrace which-func hideshow disp-table cus-edit pp
cus-start cus-load eww vtable url-queue shr pixel-fill kinsoku url-file
svg xml dom mm-url gnus nnheader range wid-edit helm-imenu helm-mode
helm-misc helm-files image-dired image-dired-tags image-dired-external
image-dired-util image-mode exif tramp trampver tramp-integration
tramp-message tramp-compat shell parse-time iso8601 tramp-loaddefs
helm-buffers helm-occur helm-tags helm-locate helm-grep helm-regexp
helm-utils helm-help helm-types helm helm-global-bindings helm-easymenu
helm-core async-bytecomp helm-source helm-multi-match helm-lib async
imenu ob-plantuml delsel autorevert filenotify org ob ob-tangle ob-ref
ob-lob ob-table ob-exp org-macro org-src sh-script smie executable
ob-comint org-pcomplete org-list org-footnote org-faces org-entities
noutline outline org-version ob-emacs-lisp ob-core ob-eval org-cycle
org-table ol org-fold org-fold-core org-keys oc org-loaddefs thingatpt
find-func cal-menu calendar cal-loaddefs org-compat org-macs yasnippet
paredit mm-archive message sendmail yank-media dired dired-loaddefs
rfc822 mml mml-sec epa derived epg rfc6068 gnus-util time-date
mailabbrev gmm-utils mailheader mm-decode mm-bodies mm-encode mail-utils
gnutls network-stream url-cache url-http url-auth mail-parse rfc2231
rfc2047 rfc2045 mm-util ietf-drums mail-prsvr url-gw nsm puny epg-config
poetry pyvenv eshell esh-cmd esh-ext esh-proc esh-opt esh-io esh-arg
pcomplete esh-module esh-module-loaddefs esh-util files-x transient
nlinum linum ido-yes-or-no advice ido use-package-bind-key bind-key xref
server hl-line pixel-scroll cua-base compile-eslint compile
text-property-search all-the-icons all-the-icons-faces data-material
data-weathericons data-octicons data-fileicons data-faicons
data-alltheicons doom-modeline doom-modeline-segments doom-modeline-env
doom-modeline-core shrink-path f s dash nerd-icons nerd-icons-faces
nerd-icons-data nerd-icons-data-mdicon nerd-icons-data-flicon
nerd-icons-data-codicon nerd-icons-data-devicon nerd-icons-data-sucicon
nerd-icons-data-wicon nerd-icons-data-faicon nerd-icons-data-powerline
nerd-icons-data-octicon nerd-icons-data-pomicon nerd-icons-data-ipsicon
dracula-theme use-package-ensure use-package-core
all-the-icons-autoloads bitwarden-autoloads bmx-mode-autoloads
cargo-autoloads cmake-mode-autoloads company-autoloads
copilot-mode-autoloads crontab-mode-autoloads csv-mode-autoloads
bui-autoloads dockerfile-mode-autoloads doom-modeline-autoloads
dracula-theme-autoloads editorconfig-autoloads elisp-slime-nav-autoloads
expand-region-autoloads flycheck-autoloads helm-autoloads
helm-core-autoloads async-autoloads highlight-symbol-autoloads
ido-yes-or-no-autoloads ido-completing-read+-autoloads
indent-bars-autoloads lsp-treemacs-autoloads lsp-mode-autoloads
magit-autoloads git-commit-autoloads magit-section-autoloads
markdown-mode-autoloads memoize-autoloads multiple-cursors-autoloads
nerd-icons-autoloads nlinum-autoloads paredit-autoloads
pkg-info-autoloads epl-autoloads poetry-autoloads popup-autoloads
powershell-autoloads pyvenv-autoloads quelpa-use-package-autoloads
quelpa-autoloads shrink-path-autoloads f-autoloads spinner-autoloads
format-spec edmacro kmacro combobulate-display let-alist
combobulate-ztree combobulate-envelope combobulate-manipulation python
project compat comint ansi-osc ring ansi-color combobulate-procedure
combobulate-navigation comp comp-cstr cl-extra help-mode warnings
comp-run comp-common rx combobulate-misc combobulate-setup tempo
combobulate-interface pcase combobulate-settings diff-mode track-changes
easy-mmode treesit generator combobulate-rules finder-inf
structurizr-ts-mode-autoloads swift-mode-autoloads transient-autoloads
treemacs-autoloads cfrs-autoloads posframe-autoloads ht-autoloads
hydra-autoloads lv-autoloads pfuture-autoloads ace-window-autoloads
avy-autoloads s-autoloads dash-autoloads undo-tree-autoloads
queue-autoloads wfnames-autoloads info with-editor-autoloads
wsd-mode-autoloads yasnippet-autoloads package browse-url xdg url
url-proxy url-privacy url-expand url-methods url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs icons password-cache json
subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib
rmc iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook
vc-hooks lisp-float-type elisp-mode mwheel term/ns-win ns-win
ucs-normalize mule-util term/common-win tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu
timer select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads kqueue cocoa ns lcms2
multi-tty make-network-process tty-child-frames native-compile emacs)

Memory information:
((conses 16 1578371 309862) (symbols 48 58852 1)
 (strings 32 398369 17620) (string-bytes 1 11348795)
 (vectors 16 174989) (vector-slots 8 2536732 293004)
 (floats 8 2453 4139) (intervals 56 32941 10517) (buffers 992 64))