all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
@ 2024-03-31 13:44 Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-03-31 14:25 ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-03-31 13:44 UTC (permalink / raw)
  To: 70105; +Cc: monnier

Package: Emacs
Version: 30.0.50


https://editorconfig.org/ seems to be a popular standard to specify
settings such as the size of an indentation step in an
editor-agnostic way.

There's an `editorconfig` package for it up on NonGNU ELPA, but I think
we should support it out of the box.


        Stefan


 In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.38, cairo version 1.16.0) of 2024-03-28 built on pastel
Repository revision: 751b97741c49abf50558e526ee4a8315a412a0e7
Repository branch: work
Windowing system distributor 'The X.Org Foundation', version 11.0.12101007
System Description: Debian GNU/Linux 12 (bookworm)

Configured using:
 'configure -C --enable-checking --enable-check-lisp-object-type --with-modules --with-cairo --with-tiff=ifavailable
 'CFLAGS=-Wall -g3 -Og -Wno-pointer-sign' --without-native-compilation
 PKG_CONFIG_PATH=/home/monnier/lib/pkgconfig'

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON
LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND
THREADS TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM
GTK3 ZLIB

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

Major mode: InactiveMinibuffer

Minor modes in effect:
  server-mode: t
  electric-pair-mode: t
  global-reveal-mode: t
  reveal-mode: t
  auto-insert-mode: t
  savehist-mode: t
  minibuffer-electric-default-mode: t
  type-break-mode: t
  global-compact-docstrings-mode: t
  global-corfu-mode: t
  url-handler-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  global-prettify-symbols-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  minibuffer-regexp-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/home/monnier/src/emacs/nongnu/packages/jade-mode/jade-mode hides /home/monnier/src/emacs/nongnu/packages/stylus-mode/jade-mode
/home/monnier/src/emacs/nongnu/packages/jade-mode/sws-mode hides /home/monnier/src/emacs/nongnu/packages/stylus-mode/sws-mode
/home/monnier/src/emacs/nongnu/packages/jade-mode/stylus-mode hides /home/monnier/src/emacs/nongnu/packages/stylus-mode/stylus-mode
/home/monnier/src/emacs/nongnu/packages/paredit/test hides /home/monnier/src/emacs/elpa/packages/easy-kill/test
/home/monnier/src/emacs/elpa/packages/embark-consult/embark-consult hides /home/monnier/src/emacs/elpa/packages/embark/embark-consult
/home/monnier/src/emacs/elpa/packages/embark-consult/embark-org hides /home/monnier/src/emacs/elpa/packages/embark/embark-org
/home/monnier/src/emacs/elpa/packages/embark-consult/embark hides /home/monnier/src/emacs/elpa/packages/embark/embark
/home/monnier/src/emacs/elpa/packages/embark-consult/avy-embark-collect hides /home/monnier/src/emacs/elpa/packages/embark/avy-embark-collect
/home/monnier/src/emacs/elpa/packages/ada-mode/prj hides /home/monnier/src/emacs/elpa/packages/gpr-query/prj
/home/monnier/src/emacs/elpa/packages/idlwave/lpath hides /home/monnier/src/emacs/elpa/packages/auctex/lpath
/home/monnier/src/emacs/nongnu/packages/forth-mode/build hides /home/monnier/src/emacs/elpa/packages/lentic/build
/home/monnier/src/emacs/elpa/packages/ef-themes/theme-loaddefs hides /home/monnier/src/emacs/elpa/packages/modus-themes/theme-loaddefs
/home/monnier/src/emacs/nongnu/packages/paredit/test hides /home/monnier/src/emacs/elpa/packages/num3-mode/test
/home/monnier/src/emacs/nongnu/packages/org-contrib/lisp/ob-asymptote hides /home/monnier/src/emacs/elpa/packages/ob-asymptote/ob-asymptote
/home/monnier/src/emacs/elpa/packages/realgud-lldb/cask-install hides /home/monnier/src/emacs/elpa/packages/realgud-trepan-ni/cask-install
/home/monnier/src/emacs/elpa/packages/realgud-lldb/cask-install hides /home/monnier/src/emacs/elpa/packages/realgud/cask-install
/home/monnier/src/emacs/elpa/packages/realgud-lldb/cask-install hides /home/monnier/src/emacs/elpa/packages/loc-changes/cask-install
/home/monnier/src/emacs/elpa/packages/ef-themes/theme-loaddefs hides /home/monnier/src/emacs/elpa/packages/standard-themes/theme-loaddefs
/home/monnier/src/emacs/elpa/packages/elsa/Elsafile hides /home/monnier/src/emacs/elpa/packages/trinary/Elsafile
/home/monnier/src/emacs/elpa/packages/url-http-oauth-demo/url-http-oauth-demo hides /home/monnier/src/emacs/elpa/packages/url-http-oauth/url-http-oauth-demo
/home/monnier/src/emacs/nongnu/packages/vm/lisp/vcard hides /home/monnier/src/emacs/elpa/packages/vcard/vcard
/home/monnier/src/emacs/elpa/packages/hydra/hydra-test hides /home/monnier/src/emacs/elpa/packages/lv/hydra-test
/home/monnier/src/emacs/elpa/packages/hydra/hydra hides /home/monnier/src/emacs/elpa/packages/lv/hydra
/home/monnier/src/emacs/elpa/packages/hydra/lv hides /home/monnier/src/emacs/elpa/packages/lv/lv
/home/monnier/src/emacs/elpa/packages/hydra/hydra-ox hides /home/monnier/src/emacs/elpa/packages/lv/hydra-ox
/home/monnier/src/emacs/elpa/packages/hydra/hydra-examples hides /home/monnier/src/emacs/elpa/packages/lv/hydra-examples
/home/monnier/src/emacs/elpa/packages/ef-themes/theme-loaddefs hides /home/monnier/src/emacs/work/lisp/theme-loaddefs
/home/monnier/src/emacs/elpa/packages/idlwave/idlw-help hides /home/monnier/src/emacs/work/lisp/progmodes/idlw-help
/home/monnier/src/emacs/elpa/packages/idlwave/idlw-complete-structtag hides /home/monnier/src/emacs/work/lisp/progmodes/idlw-complete-structtag
/home/monnier/src/emacs/elpa/packages/idlwave/idlw-toolbar hides /home/monnier/src/emacs/work/lisp/progmodes/idlw-toolbar
/home/monnier/src/emacs/elpa/packages/idlwave/idlwave hides /home/monnier/src/emacs/work/lisp/progmodes/idlwave
/home/monnier/src/emacs/elpa/packages/csharp-mode/csharp-mode hides /home/monnier/src/emacs/work/lisp/progmodes/csharp-mode
/home/monnier/src/emacs/nongnu/packages/lua-mode/lua-mode hides /home/monnier/src/emacs/work/lisp/progmodes/lua-mode
/home/monnier/src/emacs/elpa/packages/idlwave/idlw-shell hides /home/monnier/src/emacs/work/lisp/progmodes/idlw-shell
/home/monnier/src/emacs/elpa/packages/org/lisp/org-src hides /home/monnier/src/emacs/work/lisp/org/org-src
/home/monnier/src/emacs/elpa/packages/org/lisp/oc hides /home/monnier/src/emacs/work/lisp/org/oc
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-screen hides /home/monnier/src/emacs/work/lisp/org/ob-screen
/home/monnier/src/emacs/elpa/packages/org/lisp/org-loaddefs hides /home/monnier/src/emacs/work/lisp/org/org-loaddefs
/home/monnier/src/emacs/elpa/packages/org/lisp/org-agenda hides /home/monnier/src/emacs/work/lisp/org/org-agenda
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-dot hides /home/monnier/src/emacs/work/lisp/org/ob-dot
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-plantuml hides /home/monnier/src/emacs/work/lisp/org/ob-plantuml
/home/monnier/src/emacs/elpa/packages/org/lisp/org-inlinetask hides /home/monnier/src/emacs/work/lisp/org/org-inlinetask
/home/monnier/src/emacs/elpa/packages/org/lisp/oc-natbib hides /home/monnier/src/emacs/work/lisp/org/oc-natbib
/home/monnier/src/emacs/elpa/packages/org/lisp/org-attach-git hides /home/monnier/src/emacs/work/lisp/org/org-attach-git
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-docview hides /home/monnier/src/emacs/work/lisp/org/ol-docview
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-exp hides /home/monnier/src/emacs/work/lisp/org/ob-exp
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-mhe hides /home/monnier/src/emacs/work/lisp/org/ol-mhe
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-awk hides /home/monnier/src/emacs/work/lisp/org/ob-awk
/home/monnier/src/emacs/elpa/packages/org/lisp/org-fold-core hides /home/monnier/src/emacs/work/lisp/org/org-fold-core
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-doi hides /home/monnier/src/emacs/work/lisp/org/ol-doi
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-ref hides /home/monnier/src/emacs/work/lisp/org/ob-ref
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-calc hides /home/monnier/src/emacs/work/lisp/org/ob-calc
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-js hides /home/monnier/src/emacs/work/lisp/org/ob-js
/home/monnier/src/emacs/elpa/packages/org/lisp/org-colview hides /home/monnier/src/emacs/work/lisp/org/org-colview
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-julia hides /home/monnier/src/emacs/work/lisp/org/ob-julia
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-ruby hides /home/monnier/src/emacs/work/lisp/org/ob-ruby
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-forth hides /home/monnier/src/emacs/work/lisp/org/ob-forth
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-lua hides /home/monnier/src/emacs/work/lisp/org/ob-lua
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-lob hides /home/monnier/src/emacs/work/lisp/org/ob-lob
/home/monnier/src/emacs/elpa/packages/org/lisp/org-compat hides /home/monnier/src/emacs/work/lisp/org/org-compat
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-matlab hides /home/monnier/src/emacs/work/lisp/org/ob-matlab
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-scheme hides /home/monnier/src/emacs/work/lisp/org/ob-scheme
/home/monnier/src/emacs/elpa/packages/org/lisp/org-table hides /home/monnier/src/emacs/work/lisp/org/org-table
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-haskell hides /home/monnier/src/emacs/work/lisp/org/ob-haskell
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-octave hides /home/monnier/src/emacs/work/lisp/org/ob-octave
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-processing hides /home/monnier/src/emacs/work/lisp/org/ob-processing
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-bibtex hides /home/monnier/src/emacs/work/lisp/org/ol-bibtex
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-ocaml hides /home/monnier/src/emacs/work/lisp/org/ob-ocaml
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-bbdb hides /home/monnier/src/emacs/work/lisp/org/ol-bbdb
/home/monnier/src/emacs/elpa/packages/org/lisp/org-plot hides /home/monnier/src/emacs/work/lisp/org/org-plot
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-core hides /home/monnier/src/emacs/work/lisp/org/ob-core
/home/monnier/src/emacs/elpa/packages/org/lisp/org-refile hides /home/monnier/src/emacs/work/lisp/org/org-refile
/home/monnier/src/emacs/elpa/packages/org/lisp/org-lint hides /home/monnier/src/emacs/work/lisp/org/org-lint
/home/monnier/src/emacs/elpa/packages/org/lisp/org-footnote hides /home/monnier/src/emacs/work/lisp/org/org-footnote
/home/monnier/src/emacs/elpa/packages/org/lisp/org hides /home/monnier/src/emacs/work/lisp/org/org
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-w3m hides /home/monnier/src/emacs/work/lisp/org/ol-w3m
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-info hides /home/monnier/src/emacs/work/lisp/org/ol-info
/home/monnier/src/emacs/elpa/packages/org/lisp/org-num hides /home/monnier/src/emacs/work/lisp/org/org-num
/home/monnier/src/emacs/elpa/packages/org/lisp/org-cycle hides /home/monnier/src/emacs/work/lisp/org/org-cycle
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-tangle hides /home/monnier/src/emacs/work/lisp/org/ob-tangle
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-clojure hides /home/monnier/src/emacs/work/lisp/org/ob-clojure
/home/monnier/src/emacs/elpa/packages/org/lisp/org-attach hides /home/monnier/src/emacs/work/lisp/org/org-attach
/home/monnier/src/emacs/elpa/packages/org/lisp/org-element hides /home/monnier/src/emacs/work/lisp/org/org-element
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-comint hides /home/monnier/src/emacs/work/lisp/org/ob-comint
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-latex hides /home/monnier/src/emacs/work/lisp/org/ox-latex
/home/monnier/src/emacs/elpa/packages/org/lisp/org-faces hides /home/monnier/src/emacs/work/lisp/org/org-faces
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-html hides /home/monnier/src/emacs/work/lisp/org/ox-html
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-lisp hides /home/monnier/src/emacs/work/lisp/org/ob-lisp
/home/monnier/src/emacs/elpa/packages/org/lisp/org-persist hides /home/monnier/src/emacs/work/lisp/org/org-persist
/home/monnier/src/emacs/elpa/packages/org/lisp/oc-basic hides /home/monnier/src/emacs/work/lisp/org/oc-basic
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-maxima hides /home/monnier/src/emacs/work/lisp/org/ob-maxima
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-gnuplot hides /home/monnier/src/emacs/work/lisp/org/ob-gnuplot
/home/monnier/src/emacs/elpa/packages/org/lisp/org-archive hides /home/monnier/src/emacs/work/lisp/org/org-archive
/home/monnier/src/emacs/elpa/packages/org/lisp/org-protocol hides /home/monnier/src/emacs/work/lisp/org/org-protocol
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-gnus hides /home/monnier/src/emacs/work/lisp/org/ol-gnus
/home/monnier/src/emacs/elpa/packages/org/lisp/org-indent hides /home/monnier/src/emacs/work/lisp/org/org-indent
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-java hides /home/monnier/src/emacs/work/lisp/org/ob-java
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-shell hides /home/monnier/src/emacs/work/lisp/org/ob-shell
/home/monnier/src/emacs/elpa/packages/org/lisp/org-tempo hides /home/monnier/src/emacs/work/lisp/org/org-tempo
/home/monnier/src/emacs/elpa/packages/org/lisp/oc-bibtex hides /home/monnier/src/emacs/work/lisp/org/oc-bibtex
/home/monnier/src/emacs/elpa/packages/org/lisp/ob hides /home/monnier/src/emacs/work/lisp/org/ob
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-texinfo hides /home/monnier/src/emacs/work/lisp/org/ox-texinfo
/home/monnier/src/emacs/elpa/packages/org/lisp/org-ctags hides /home/monnier/src/emacs/work/lisp/org/org-ctags
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-beamer hides /home/monnier/src/emacs/work/lisp/org/ox-beamer
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-perl hides /home/monnier/src/emacs/work/lisp/org/ob-perl
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-man hides /home/monnier/src/emacs/work/lisp/org/ox-man
/home/monnier/src/emacs/elpa/packages/org/lisp/org-version hides /home/monnier/src/emacs/work/lisp/org/org-version
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-R hides /home/monnier/src/emacs/work/lisp/org/ob-R
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-icalendar hides /home/monnier/src/emacs/work/lisp/org/ox-icalendar
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-python hides /home/monnier/src/emacs/work/lisp/org/ob-python
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-sass hides /home/monnier/src/emacs/work/lisp/org/ob-sass
/home/monnier/src/emacs/elpa/packages/org/lisp/oc-csl hides /home/monnier/src/emacs/work/lisp/org/oc-csl
/home/monnier/src/emacs/elpa/packages/org/lisp/org-feed hides /home/monnier/src/emacs/work/lisp/org/org-feed
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-ascii hides /home/monnier/src/emacs/work/lisp/org/ox-ascii
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-eshell hides /home/monnier/src/emacs/work/lisp/org/ob-eshell
/home/monnier/src/emacs/elpa/packages/org/lisp/org-id hides /home/monnier/src/emacs/work/lisp/org/org-id
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-man hides /home/monnier/src/emacs/work/lisp/org/ol-man
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-org hides /home/monnier/src/emacs/work/lisp/org/ox-org
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-ditaa hides /home/monnier/src/emacs/work/lisp/org/ob-ditaa
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-rmail hides /home/monnier/src/emacs/work/lisp/org/ol-rmail
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-C hides /home/monnier/src/emacs/work/lisp/org/ob-C
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-emacs-lisp hides /home/monnier/src/emacs/work/lisp/org/ob-emacs-lisp
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-makefile hides /home/monnier/src/emacs/work/lisp/org/ob-makefile
/home/monnier/src/emacs/elpa/packages/org/lisp/org-keys hides /home/monnier/src/emacs/work/lisp/org/org-keys
/home/monnier/src/emacs/elpa/packages/org/lisp/org-duration hides /home/monnier/src/emacs/work/lisp/org/org-duration
/home/monnier/src/emacs/elpa/packages/org/lisp/org-macro hides /home/monnier/src/emacs/work/lisp/org/org-macro
/home/monnier/src/emacs/elpa/packages/org/lisp/org-timer hides /home/monnier/src/emacs/work/lisp/org/org-timer
/home/monnier/src/emacs/elpa/packages/org/lisp/org-datetree hides /home/monnier/src/emacs/work/lisp/org/org-datetree
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-sed hides /home/monnier/src/emacs/work/lisp/org/ob-sed
/home/monnier/src/emacs/elpa/packages/org/lisp/ol hides /home/monnier/src/emacs/work/lisp/org/ol
/home/monnier/src/emacs/elpa/packages/org/lisp/org-list hides /home/monnier/src/emacs/work/lisp/org/org-list
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-eshell hides /home/monnier/src/emacs/work/lisp/org/ol-eshell
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-eval hides /home/monnier/src/emacs/work/lisp/org/ob-eval
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-css hides /home/monnier/src/emacs/work/lisp/org/ob-css
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-table hides /home/monnier/src/emacs/work/lisp/org/ob-table
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-eww hides /home/monnier/src/emacs/work/lisp/org/ol-eww
/home/monnier/src/emacs/elpa/packages/org/lisp/ox hides /home/monnier/src/emacs/work/lisp/org/ox
/home/monnier/src/emacs/elpa/packages/org/lisp/oc-biblatex hides /home/monnier/src/emacs/work/lisp/org/oc-biblatex
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-fortran hides /home/monnier/src/emacs/work/lisp/org/ob-fortran
/home/monnier/src/emacs/elpa/packages/org/lisp/org-habit hides /home/monnier/src/emacs/work/lisp/org/org-habit
/home/monnier/src/emacs/elpa/packages/org/lisp/ol-irc hides /home/monnier/src/emacs/work/lisp/org/ol-irc
/home/monnier/src/emacs/elpa/packages/org/lisp/org-mouse hides /home/monnier/src/emacs/work/lisp/org/org-mouse
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-koma-letter hides /home/monnier/src/emacs/work/lisp/org/ox-koma-letter
/home/monnier/src/emacs/elpa/packages/org/lisp/org-mobile hides /home/monnier/src/emacs/work/lisp/org/org-mobile
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-publish hides /home/monnier/src/emacs/work/lisp/org/ox-publish
/home/monnier/src/emacs/elpa/packages/org/lisp/org-clock hides /home/monnier/src/emacs/work/lisp/org/org-clock
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-lilypond hides /home/monnier/src/emacs/work/lisp/org/ob-lilypond
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-sqlite hides /home/monnier/src/emacs/work/lisp/org/ob-sqlite
/home/monnier/src/emacs/elpa/packages/org/lisp/org-macs hides /home/monnier/src/emacs/work/lisp/org/org-macs
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-odt hides /home/monnier/src/emacs/work/lisp/org/ox-odt
/home/monnier/src/emacs/elpa/packages/org/lisp/org-fold hides /home/monnier/src/emacs/work/lisp/org/org-fold
/home/monnier/src/emacs/elpa/packages/org/lisp/org-crypt hides /home/monnier/src/emacs/work/lisp/org/org-crypt
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-org hides /home/monnier/src/emacs/work/lisp/org/ob-org
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-latex hides /home/monnier/src/emacs/work/lisp/org/ob-latex
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-groovy hides /home/monnier/src/emacs/work/lisp/org/ob-groovy
/home/monnier/src/emacs/elpa/packages/org/lisp/ob-sql hides /home/monnier/src/emacs/work/lisp/org/ob-sql
/home/monnier/src/emacs/elpa/packages/org/lisp/org-pcomplete hides /home/monnier/src/emacs/work/lisp/org/org-pcomplete
/home/monnier/src/emacs/elpa/packages/org/lisp/ox-md hides /home/monnier/src/emacs/work/lisp/org/ox-md
/home/monnier/src/emacs/elpa/packages/org/lisp/org-capture hides /home/monnier/src/emacs/work/lisp/org/org-capture
/home/monnier/src/emacs/elpa/packages/org/lisp/org-entities hides /home/monnier/src/emacs/work/lisp/org/org-entities
/home/monnier/src/emacs/elpa/packages/org/lisp/org-goto hides /home/monnier/src/emacs/work/lisp/org/org-goto
/home/monnier/src/emacs/work/lisp/keymap hides /home/monnier/src/emacs/work/lisp/emacs-lisp/keymap
/home/monnier/src/emacs/elpa/packages/landmark/landmark hides /home/monnier/src/emacs/work/lisp/obsolete/landmark
/home/monnier/src/emacs/elpa/packages/crisp/crisp hides /home/monnier/src/emacs/work/lisp/obsolete/crisp

Features:
(shadow sort mail-extr emacsbug markdown-mode edit-indirect pulse etags
fileloop generator xref sm-c-mode smie crdt gnutls forms forms-mode
color xdg epa-file log-edit message sendmail yank-media puny dired
dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config
gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047
rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils gmm-utils
mailheader add-log smerge-mode whitespace dabbrev vc-backup log-view
pcvs-util vc diff shortdoc comp-common prefixed-core misearch
multi-isearch mule-util executable copyright edebug help-fns radix-tree
debug backtrace find-func cl-print track-changes ielm vc-git diff-mode
easy-mmode vc-dispatcher filecache bug-reference raku-detect server
time-date flymake project compile text-property-search comint ansi-osc
ansi-color ring warnings noutline outline flyspell ispell checkdoc
lisp-mnt thingatpt elec-pair reveal autoinsert savehist minibuf-eldef
disp-table type-break compact-docstrings corfu compat
adoc-mode-autoloads afternoon-theme-autoloads alect-themes-autoloads
ample-theme-autoloads annotate-autoloads anti-zenburn-theme-autoloads
apache-mode-autoloads apropospriate-theme-autoloads
arduino-mode-autoloads ede/auto eieio-base
auto-dim-other-buffers-autoloads bash-completion-autoloads
better-jumper-autoloads bison-mode-autoloads blow-autoloads
blueprint-ts-mode-autoloads boxquote-autoloads buttercup-autoloads
camera-autoloads cdlatex-autoloads cider-autoloads
clojure-ts-mode-autoloads coffee-mode-autoloads
consult-flycheck-autoloads corfu-terminal-autoloads crux-autoloads
cyberpunk-theme-autoloads cycle-at-point-autoloads d-mode-autoloads
dart-mode-autoloads dcs-mode-autoloads denote-refs-autoloads
devhelp-autoloads devil-autoloads diff-ansi-autoloads dirvish-autoloads
doc-show-inline-autoloads dracula-theme-autoloads drupal-mode-autoloads
eat-autoloads edit-indirect-autoloads editorconfig-autoloads
el-mock-autoloads elixir-mode-autoloads elpher-autoloads
emacsql-autoloads engine-mode-autoloads evil-anzu-autoloads
anzu-autoloads evil-args-autoloads evil-escape-autoloads
evil-exchange-autoloads evil-goggles-autoloads
evil-iedit-state-autoloads evil-indent-plus-autoloads
evil-lisp-state-autoloads bind-map-autoloads evil-matchit-autoloads
evil-nerd-commenter-autoloads evil-numbers-autoloads
evil-surround-autoloads evil-visual-mark-mode-autoloads
evil-visualstar-autoloads evil-autoloads exec-path-from-shell-autoloads
flx-ido-autoloads flx-autoloads flycheck-autoloads
flymake-guile-autoloads flymake-kondor-autoloads flymake-popon-autoloads
focus-autoloads forth-mode-autoloads free-keys-autoloads
gc-buffers-autoloads geiser-chez-autoloads geiser-chibi-autoloads
geiser-chicken-autoloads geiser-gambit-autoloads geiser-gauche-autoloads
geiser-guile-autoloads geiser-kawa-autoloads geiser-mit-autoloads
geiser-racket-autoloads geiser-stklos-autoloads geiser-autoloads
git-modes-autoloads gnu-apl-mode-autoloads gnu-indent-autoloads
gnuplot-autoloads go-mode-autoloads golden-ratio-autoloads
gotham-theme-autoloads goto-chg-autoloads graphql-mode-autoloads
gruber-darker-theme-autoloads gruvbox-theme-autoloads
autothemer-autoloads guru-mode-autoloads haskell-tng-mode-autoloads
helm-autoloads helm-core-autoloads highlight-parentheses-autoloads
hl-block-mode-autoloads hl-column-autoloads htmlize-autoloads
hyperdrive-autoloads idle-highlight-mode-autoloads idris-mode-autoloads
iedit-autoloads inf-clojure-autoloads clojure-mode-autoloads
inf-ruby-autoloads inkpot-theme-autoloads iwindow-autoloads
j-mode-autoloads jabber-autoloads jade-mode-autoloads
jinja2-mode-autoloads julia-mode-autoloads keycast-autoloads
kotlin-mode-autoloads lorem-ipsum-autoloads lua-mode-autoloads
markdown-mode-autoloads mastodon-autoloads material-theme-autoloads
mentor-autoloads meow-autoloads minibar-autoloads moe-theme-autoloads
monokai-theme-autoloads mpv-autoloads multiple-cursors-autoloads
nasm-mode-autoloads nginx-mode-autoloads nix-mode-autoloads
oblivion-theme-autoloads opam-switch-mode-autoloads
org-auto-tangle-autoloads org-drill-autoloads org-journal-autoloads
org-mime-autoloads org-present-autoloads org-superstar-autoloads
org-tree-slide-autoloads orgit-autoloads package-lint-autoloads
pacmacs-autoloads page-break-lines-autoloads paredit-autoloads
parseedn-autoloads parseclj-autoloads pcmpl-args-autoloads
pcre2el-autoloads popon-autoloads popup-autoloads prescient-autoloads
projectile-autoloads proof-general-autoloads proof-site proof-autoloads
prop-menu-autoloads racket-mode-autoloads rainbow-delimiters-autoloads
raku-mode-autoloads recomplete-autoloads rfc-mode-autoloads
rubocop-autoloads rust-mode-autoloads sass-mode-autoloads
haml-mode-autoloads scad-mode-autoloads scala-mode-autoloads
scroll-on-drag-autoloads scroll-on-jump-autoloads sesman-autoloads
shellcop-autoloads slime-autoloads macrostep-autoloads sly-autoloads
smartparens-autoloads solarized-theme-autoloads
spacemacs-theme-autoloads spell-fu-autoloads sqlite3-autoloads
stylus-mode-autoloads subatomic-theme-autoloads subed-autoloads
sweeprolog-autoloads swift-mode-autoloads swsw-autoloads
symbol-overlay-autoloads systemd-autoloads tablist-autoloads
tangotango-theme-autoloads telephone-line-autoloads
testcover-mark-line-autoloads textile-mode-autoloads toc-org-autoloads
totp-auth-autoloads base32-autoloads tuareg-autoloads rx caml-autoloads
typescript-mode-autoloads ujelly-theme-autoloads undo-fu-autoloads
undo-fu-session-autoloads vc-fossil-autoloads vcomplete-autoloads
visual-fill-column-autoloads vm-autoloads web-mode-autoloads
webpaste-autoloads wfnames-autoloads wgrep-autoloads why-this-autoloads
with-simulated-input-autoloads workroom-autoloads
writegood-mode-autoloads ws-butler-autoloads xah-fly-keys-autoloads
xkcd-autoloads xml-rpc-autoloads yaml-mode-autoloads
yasnippet-snippets-autoloads zenburn-theme-autoloads zig-mode-autoloads
reformatter-autoloads ace-window-autoloads ack-autoloads
activities-autoloads ada-mode-autoloads ada-ref-man-autoloads
adaptive-wrap-autoloads adjust-parens-autoloads advice-patch-autoloads
aggressive-completion-autoloads aggressive-indent-autoloads
agitate-autoloads ahungry-theme-autoloads aircon-theme-autoloads
all-autoloads altcaps-autoloads ampc-autoloads arbitools-autoloads
assess-autoloads aumix-mode-autoloads auto-correct-autoloads
auto-header-autoloads auto-overlays-autoloads autocrypt-autoloads
bbdb-autoloads beacon-autoloads beardbolt-autoloads beframe-autoloads
bicep-ts-mode-autoloads blist-autoloads bluetooth-autoloads
bnf-mode-autoloads boxy-headings-autoloads boxy-headlines-autoloads
breadcrumb-autoloads brief-autoloads buffer-env-autoloads
buffer-expose-autoloads bufferlo-autoloads bug-hunter-autoloads
buildbot-autoloads calibre-autoloads cape-autoloads
capf-autosuggest-autoloads caps-lock-autoloads captain-autoloads
chess-autoloads clipboard-collector-autoloads cobol-mode-autoloads
code-cells-autoloads compact-docstrings-autoloads company-ebdb-autoloads
company-math-autoloads company-statistics-autoloads company-autoloads
consult-hoogle-autoloads haskell-mode-autoloads consult-recoll-autoloads
context-coloring-autoloads corfu-autoloads coterm-autoloads
counsel-autoloads cpio-mode-autoloads cpupower-autoloads crdt-autoloads
crisp-autoloads csharp-mode-autoloads csv-mode-autoloads
cursory-autoloads cycle-quotes-autoloads dape-autoloads
darkroom-autoloads dbus-codegen-autoloads debbugs-autoloads
delight-autoloads denote-menu-autoloads denote-autoloads
detached-autoloads devdocs-autoloads devicetree-ts-mode-autoloads
dict-tree-autoloads diff-hl-autoloads diffview-autoloads
diminish-autoloads dired-du-autoloads dired-duplicates-autoloads
dired-git-info-autoloads dired-preview-autoloads disk-usage-autoloads
dismal-autoloads djvu-autoloads do-at-point-autoloads doc-toc-autoloads
docbook-autoloads drepl-autoloads comint-mime-autoloads
dts-mode-autoloads easy-escape-autoloads easy-kill-autoloads
ebdb-gnorb-autoloads cl-seq inline ebdb-i18n-chn-autoloads
ebdb-autoloads cl-extra help-mode ediprolog-autoloads eev-autoloads
ef-themes-autoloads el-search-autoloads electric-spacing-autoloads
elisp-benchmarks-autoloads ellama-autoloads elsa-autoloads
emacs-gc-stats-autoloads emacspeak-autoloads embark-consult-autoloads
consult-autoloads embark-autoloads ement-autoloads emms-autoloads
engrave-faces-autoloads enwc-autoloads epoch-view-autoloads
ergoemacs-mode-autoloads ess-autoloads excorporate-autoloads
expand-region-autoloads expreg-autoloads exwm-autoloads
f90-interface-browser-autoloads face-shift-autoloads
filechooser-autoloads filladapt-autoloads
firefox-javascript-repl-autoloads flylisp-autoloads
flymake-codespell-autoloads flymake-proselint-autoloads
fontaine-autoloads frame-tabs-autoloads frog-menu-autoloads
fsm-autoloads ftable-autoloads gcmh-autoloads ggtags-autoloads
gited-autoloads gle-mode-autoloads gnome-c-style-autoloads
gnorb-autoloads gnu-elpa-autoloads gnu-elpa-features
gnu-elpa-keyring-update-autoloads gnugo-autoloads
ascii-art-to-unicode-autoloads gnus-mock-autoloads gpastel-autoloads
gpr-mode-autoloads gpr-query-autoloads gnat-compiler-autoloads
graphql-autoloads greader-autoloads greenbar-autoloads
gtags-mode-autoloads guess-language-autoloads hcel-autoloads
hiddenquote-autoloads highlight-escape-sequences-autoloads
hook-helpers-autoloads html5-schema-autoloads idlwave-autoloads
ilist-autoloads inspector-autoloads ioccur-autoloads
isearch-mb-autoloads iterators-autoloads ivy-avy-autoloads avy-autoloads
ivy-explorer-autoloads ivy-hydra-autoloads ivy-posframe-autoloads
jarchive-autoloads javaimp-autoloads jgraph-mode-autoloads
jinx-autoloads jit-spell-autoloads js2-mode-autoloads
json-mode-autoloads jumpc-autoloads kind-icon-autoloads kiwix-autoloads
request-autoloads kmb-autoloads landmark-autoloads
latex-table-wizard-autoloads auctex-autoloads tex-site leaf-autoloads
lentic-server-autoloads lentic-autoloads lex-autoloads lin-autoloads
listen-autoloads llm-autoloads lmc-autoloads load-dir-autoloads
loccur-autoloads logos-autoloads luwak-autoloads m-buffer-autoloads
marginalia-autoloads markchars-autoloads math-symbol-lists-autoloads
mct-autoloads memory-usage-autoloads metar-autoloads midi-kbd-autoloads
mines-autoloads minibuffer-header-autoloads minibuffer-line-autoloads
minimap-autoloads modus-themes-autoloads mpdired-autoloads
multi-mode-autoloads multishell-autoloads muse-autoloads myers-autoloads
nameless-autoloads names-autoloads nano-agenda-autoloads
nano-modeline-autoloads nano-theme-autoloads nftables-mode-autoloads
nhexl-mode-autoloads nlinum-autoloads notes-mode-autoloads
notmuch-indicator-autoloads num3-mode-autoloads oauth2-autoloads
ob-asymptote-autoloads ob-haxe-autoloads objed-autoloads
omn-mode-autoloads on-screen-autoloads openpgp-autoloads
orderless-autoloads org-contacts-autoloads org-edna-autoloads
org-jami-bot-autoloads jami-bot-autoloads org-modern-autoloads
org-notify-autoloads org-real-autoloads boxy-autoloads
org-remark-autoloads org-transclusion-autoloads org-translate-autoloads
org-autoloads orgalist-autoloads osc-autoloads osm-autoloads
other-frame-window-autoloads pabbrev-autoloads paced-autoloads
parsec-autoloads parser-generator-autoloads path-iterator-autoloads
peg-autoloads perl-doc-autoloads persist-autoloads phpinspect-autoloads
phps-mode-autoloads pinentry-autoloads plz-see-autoloads poke-autoloads
poke-mode-autoloads poker-autoloads polymode-autoloads popper-autoloads
pq-autoloads prefixed-core-autoloads psgml-autoloads pspp-mode-autoloads
pulsar-autoloads pyim-autoloads async-autoloads pyim-basedict-autoloads
quarter-plane-autoloads rainbow-mode-autoloads rbit-autoloads
rcirc-color-autoloads rcirc-menu-autoloads rcirc-sqlite-autoloads
realgud-ipdb-autoloads realgud-jdb-autoloads realgud-lldb-autoloads
realgud-node-debug-autoloads realgud-node-inspect-autoloads
realgud-pdbpp-autoloads realgud-trepan-ni-autoloads
realgud-trepan-xpy-autoloads realgud-autoloads loc-changes-autoloads
load-relative-autoloads rec-mode-autoloads register-list-autoloads
relint-autoloads repology-autoloads rich-minority-autoloads
rmsbolt-autoloads rnc-mode-autoloads info rt-liberation-autoloads
ruby-end-autoloads rudel-autoloads satchel-autoloads scanner-autoloads
scroll-restore-autoloads sed-mode-autoloads setup-autoloads
shelisp-autoloads shell-command+-autoloads shell-quasiquote-autoloads
shen-mode-autoloads sisu-mode-autoloads site-lisp-autoloads
sketch-mode-autoloads slime-volleyball-autoloads sm-c-mode-autoloads
smalltalk-mode-autoloads smart-yank-autoloads sml-mode-autoloads
sokoban-autoloads sotlisp-autoloads spacious-padding-autoloads
spinner-autoloads sql-beeline-autoloads sql-cassandra-autoloads
sql-indent-autoloads sql-smie-autoloads finder-inf plz-autoloads
ssh-deploy-autoloads standard-themes-autoloads stream-autoloads
substitute-autoloads svg-clock-autoloads svg-tag-mode-autoloads
svg-lib-autoloads swiper-autoloads ivy-autoloads
switchy-window-autoloads sxhkdrc-mode-autoloads
system-packages-autoloads tam-autoloads taxy-magit-section-autoloads
taxy-autoloads dash-autoloads temp-buffer-browse-autoloads
tempel-autoloads test-simple-autoloads theme-buffet-autoloads
timerfunctions-autoloads tiny-autoloads tmr-autoloads tomelr-autoloads
topspace-autoloads tramp-nspawn-autoloads tramp-theme-autoloads
transcribe-autoloads transient-cycles-autoloads tree-inspector-autoloads
treeview-autoloads trie-autoloads heap-autoloads tNFA-autoloads
trinary-autoloads triples-autoloads typo-autoloads ulisp-repl-autoloads
undo-tree-autoloads uni-confusables-autoloads uniquify-files-autoloads
urgrep-autoloads url-http-ntlm-autoloads url-http-oauth-demo-autoloads
url-http-oauth-autoloads url-auth url-scgi-autoloads validate-autoloads
valign-autoloads vc-backup-autoloads vc-got-autoloads vc-hgcmd-autoloads
vcard-autoloads vcl-mode-autoloads vdiff-autoloads hydra-autoloads
lv-autoloads vertico-posframe-autoloads vertico-autoloads
posframe-autoloads vigenere-autoloads visual-filename-abbrev-autoloads
visual-fill-autoloads vlf-autoloads vundo-autoloads
wcheck-mode-autoloads wconf-autoloads web-server-autoloads
webfeeder-autoloads websocket-autoloads which-key-autoloads
window-commander-autoloads windower-autoloads windresize-autoloads
wisitoken-grammar-mode-autoloads mmm-mode-autoloads wisi-autoloads
wpuzzle-autoloads wrap-search-autoloads xclip-autoloads xeft-autoloads
xelb-autoloads xpm-autoloads queue-autoloads xr-autoloads
xref-union-autoloads yasnippet-classic-snippets-autoloads
yasnippet-autoloads zones-autoloads ztree-autoloads zuul-autoloads
package browse-url 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 eieio eieio-core cl-macs pcase
password-cache json subr-x map byte-opt bytecomp byte-compile url-vars
cus-edit pp cus-load icons wid-edit cl-loaddefs cl-lib gv rmc iso-transl
tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd
touch-screen 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 button loaddefs
theme-loaddefs oclosure cl-preloaded 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
dbusbind inotify dynamic-setting system-font-setting font-render-setting
cairo gtk x-toolkit xinput2 x multi-tty move-toolbar
make-network-process emacs)

Memory information:
((conses 16 475806 534790) (symbols 48 25990 390) (strings 32 107129 24187)
 (string-bytes 1 3914363) (vectors 16 54298) (vector-slots 8 1480489 381084)
 (floats 8 404 821) (intervals 56 31797 859) (buffers 992 57))






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-03-31 13:44 bug#70105: 30.0.50; Emacs should support EditorConfig out of the box Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-03-31 14:25 ` Eli Zaretskii
  2024-03-31 20:40   ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
                     ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Eli Zaretskii @ 2024-03-31 14:25 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 70105

> Cc: monnier@iro.umontreal.ca
> Date: Sun, 31 Mar 2024 09:44:00 -0400
> From:  Stefan Monnier via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
> 
> https://editorconfig.org/ seems to be a popular standard to specify
> settings such as the size of an indentation step in an
> editor-agnostic way.
> 
> There's an `editorconfig` package for it up on NonGNU ELPA, but I think
> we should support it out of the box.

I agree, but what is the plan? import the package on NonGNU ELPA
(probably hard) or develop our own (in which case "patches welcome")?





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-03-31 14:25 ` Eli Zaretskii
@ 2024-03-31 20:40   ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-03-31 22:26   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-06 23:51   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2 siblings, 0 replies; 34+ messages in thread
From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-03-31 20:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 70105, Stefan Monnier

Eli Zaretskii <eliz@gnu.org> writes:

>> Cc: monnier@iro.umontreal.ca
>> Date: Sun, 31 Mar 2024 09:44:00 -0400
>> From:  Stefan Monnier via "Bug reports for GNU Emacs,
>>  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
>> 
>> https://editorconfig.org/ seems to be a popular standard to specify
>> settings such as the size of an indentation step in an
>> editor-agnostic way.
>> 
>> There's an `editorconfig` package for it up on NonGNU ELPA, but I think
>> we should support it out of the box.
>
> I agree, but what is the plan? import the package on NonGNU ELPA
> (probably hard) or develop our own (in which case "patches welcome")?

Did anybody reach to the author of the editorconfig package?

The package works quite well providing a pure-lips based implementation
(probably useful for operating systems such as Microsoft Windows) or one
based on the editorconfig.org C based utilities.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-03-31 14:25 ` Eli Zaretskii
  2024-03-31 20:40   ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-03-31 22:26   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-06 23:51   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2 siblings, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-03-31 22:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 70105

> I agree, but what is the plan?  import the package on NonGNU ELPA
> (probably hard) or develop our own (in which case "patches welcome")?

On the technical side, there's a fair bit of rework to be done to better
integrate it.  But it would be good to try and get copyright assignment
for (some of) the code, so we don't have to reinvent the whole wheel.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-03-31 14:25 ` Eli Zaretskii
  2024-03-31 20:40   ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-03-31 22:26   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-06 23:51   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-08 12:50     ` Eli Zaretskii
  2024-06-09 11:49     ` Stefan Kangas
  2 siblings, 2 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-06 23:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Jen-Chieh Shen, Björn Bidar, 10sr, 70105

[-- Attachment #1: Type: text/plain, Size: 2850 bytes --]

I think I have a clear enough idea of how support for Editorconfig
should be integrated into Emacs, in terms of "how to hook it to the
right places".  There are still pending questions about how to adapt
the code of the `editorconfig` package, but in the mean time: here's
a first step to make sure Emacs offers the right hooks.

Find below two patch which do that.

The first patch slightly extends `auto-coding-functions` so that it can
use the file name to decide which coding system to use.  This is
a fairly simple change: this clearly the right place to hook ourselves
into.  I make the change by adding a dynamically scoped
`auto-coding-file-name` variable.  The resulting API would be cleaner if
we instead passed the filename as an additional argument, which we could
do easily (even with some amount of backward compatibility), but the
change proposed has the advantage of being 100% backward compatible.
The cleaner API would replace:

    (let ((auto-coding-file-name filename))
      (funcall (pop funcs) size))

with

    (let ((fun (pop funcs)))
      (condition-case nil
          (funcall fun size filename)
        (wrong-number-of-arguments (funcall fun size))))

In the long run the cleaner API is probably preferable, but it does come
with a slight risk of backward incompatibility.

The second patch adds a new hook
`hack-dir-local-get-variables-functions`.  This one is not as "obvious":
there are other places we could hook ourselves into.  E.g. it's tempting
to hook deeper into the dir-locals machinery so as to reuse its caching
mechanism.  In the end I decided not to do that because the dir-locals
machinery is not prepared to accept settings coming from different
levels of the directory tree, so that trying to shoehorn Editorconfig
into it would be a bit messy and/or unreliable.
The downside is that this hook forces its users to take care of their
own caching.  But since the current examples all need to do their
caching a bit differently, I think this is OK.

There's one other design choice I made:
`hack-dir-local-get-variables-functions` returns elements of the form
(DIR . ALIST) where DIR is used to obey
`safe-local-variable-directories' as well as to provide a bit more info
to the user when prompting for confirmation in cache of risky settings.
But that does not provide any actual info about the actual source of the
ALIST, so the message we emit when prompting the user can't tell the
user whether the settings come from a `.dir-locals.el` or
something else.  This is not a new problem: the current code already
can't tell the user if the settings come from a `.dir-locals.el`, or
a "project class" or a `.dir-locals-2.el`.  So, apparently, this is
a problem we have not deemed worthwhile to fix, so I left it
like unsolved.

I'm hoping this can get into Emacs-30.
Comments/objections?


        Stefan

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-find-auto-coding-Provide-filename-to-auto-coding-fun.patch --]
[-- Type: text/x-diff, Size: 4641 bytes --]

From d12c9bc2a4c8383abdf7fa32b67f1ca0379227e3 Mon Sep 17 00:00:00 2001
From: Stefan Monnier <monnier@iro.umontreal.ca>
Date: Tue, 4 Jun 2024 10:58:29 -0400
Subject: [PATCH 1/2] (find-auto-coding): Provide filename to
 `auto-coding-functions`

Allow `auto-coding-functions` to know the file name.
Motivated by the needs of Editorconfig support.

* lisp/international/mule.el (auto-coding-file-name): New var.
(find-auto-coding): Let-bind it for `auto-coding-functions`.
Document the expectation that the arg be an absolute file name.

* doc/lispref/nonascii.texi (Default Coding Systems):
Mention `auto-coding-file-name`.
---
 doc/lispref/nonascii.texi  |  3 +++
 etc/NEWS                   |  5 +++++
 lisp/international/mule.el | 17 ++++++++++++++---
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index b33082e2b24..1482becb9f5 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -1654,6 +1654,9 @@ Default Coding Systems
 starting from point.  If the function succeeds in determining a coding
 system for the file, it should return that coding system.  Otherwise,
 it should return @code{nil}.
+Each function can also find the name of the file to which
+the buffer's content belong in the variable
+@code{auto-coding-file-name}.
 
 The functions in this list could be called either when the file is
 visited and Emacs wants to decode its contents, and/or when the file's
diff --git a/etc/NEWS b/etc/NEWS
index 808cd0562db..52486b7bbe9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2163,6 +2163,11 @@ completion candidate.
 \f
 * Lisp Changes in Emacs 30.1
 
++++
+** 'auto-coding-functions' can know the name of the file.
+The functions on this hook take can now find the name of the file to
+which the text belongs by consulting the variable 'auto-coding-file-name'.
+
 +++
 ** New user option 'compilation-safety' to control safety of native code.
 It's now possible to control how safe is the code generated by native
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index a17221e6d21..ed74fdae755 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -1806,6 +1806,9 @@ auto-coding-regexp-alist-lookup
 	    (setq alist (cdr alist)))))
       coding-system)))
 
+(defvar auto-coding-file-name nil
+  "Variable holding the name of the file for `auto-coding-functions'.")
+
 ;; See the bottom of this file for built-in auto coding functions.
 (defcustom auto-coding-functions '(sgml-xml-auto-coding-function
 				   sgml-html-meta-auto-coding-function)
@@ -1820,6 +1823,9 @@ auto-coding-functions
 its contents, and when the file's buffer is about to be saved
 and Emacs wants to determine how to encode its contents.
 
+The name of the file is provided to the function via the variable
+`auto-coding-file-name'.
+
 If one of these functions succeeds in determining a coding
 system, it should return that coding system.  Otherwise, it
 should return nil.
@@ -1847,13 +1853,17 @@ auto-coding-alist-lookup
     coding-system))
 
 (put 'enable-character-translation 'permanent-local t)
-(put 'enable-character-translation 'safe-local-variable	'booleanp)
+(put 'enable-character-translation 'safe-local-variable	#'booleanp)
 
 (defun find-auto-coding (filename size)
+  ;; FIXME: Shouldn't we use nil rather than "" to mean that there's no file?
+  ;; FIXME: Clarify what the SOURCE is for in the return value?
   "Find a coding system for a file FILENAME of which SIZE bytes follow point.
 These bytes should include at least the first 1k of the file
 and the last 3k of the file, but the middle may be omitted.
 
+FILENAME should be an absolute file name
+or \"\" (which means that there is no associated file).
 The function checks FILENAME against the variable `auto-coding-alist'.
 If FILENAME doesn't match any entries in the variable, it checks the
 contents of the current buffer following point against
@@ -1998,7 +2008,8 @@ find-auto-coding
 	  (setq coding-system (ignore-errors
 				(save-excursion
 				  (goto-char (point-min))
-				  (funcall (pop funcs) size)))))
+				  (let ((auto-coding-file-name filename))
+				    (funcall (pop funcs) size))))))
 	(if coding-system
 	    (cons coding-system 'auto-coding-functions)))))
 
@@ -2013,7 +2024,7 @@ set-auto-coding
     (if (and found (coding-system-p (car found)))
 	(car found))))
 
-(setq set-auto-coding-function 'set-auto-coding)
+(setq set-auto-coding-function #'set-auto-coding)
 
 (defun after-insert-file-set-coding (inserted &optional visit)
   "Set `buffer-file-coding-system' of current buffer after text is inserted.
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-hack-dir-local-get-variables-functions-New-hook.patch --]
[-- Type: text/x-diff, Size: 8634 bytes --]

From 71ac0af5d0191cdf8ebc56066c7ca58dd93487cf Mon Sep 17 00:00:00 2001
From: Stefan Monnier <monnier@iro.umontreal.ca>
Date: Tue, 4 Jun 2024 11:00:32 -0400
Subject: [PATCH 2/2] (hack-dir-local-get-variables-functions): New hook

Make it possible to provide more dir-local variables, such as
done by the Editorconfig package.

* lisp/files.el (hack-dir-local--get-variables): Make arg optional.
(hack-dir-local-get-variables-functions): New hook.
(hack-dir-local-variables): Run it instead of calling
`hack-dir-local--get-variables`.

* doc/lispref/variables.texi (Directory Local Variables):
Document the new hook.
---
 doc/lispref/variables.texi | 29 +++++++++++++++
 etc/NEWS                   |  4 ++
 lisp/files.el              | 76 ++++++++++++++++++++++++++++++--------
 3 files changed, 93 insertions(+), 16 deletions(-)

diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index e05d3bb0f81..c63057e31ea 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -2277,6 +2277,35 @@ Directory Local Variables
 updates this list.
 @end defvar
 
+@defvar hack-dir-local-get-variables-functions
+This special hook holds the functions that gather the directory-local
+variables to use for a given buffer.  By default it contains just the
+function that obeys the other settings described in the present section.
+But it can be used to add support for more sources of directory-local
+variables, such as those used by other text editors.
+
+The functions on this hook are called with no argument, in the buffer to
+which we intend to apply the directory-local variables, after the
+buffer's major mode function has been run, so it can use sources of
+information such as @code{major-mode} or @code{buffer-file-name} to find
+the variables that should be applied.
+
+It should return either a cons cell of the form @code{(@var{directory}
+. @var{alist})} or a list of such cons-cells.  A @code{nil} return value
+means that it found no directory-local variables.  @var{directory}
+should be a string: the name of the directory to which the variables
+apply.  @var{alist} is a list of variables together with their values
+that apply to the current buffer, where every element is of the form
+@code{(@var{varname} . @var{value})}.
+
+The various @var{alist} returned by these functions will be combined,
+and in case of conflicts, the settings coming from deeper directories
+will take precedence over those coming from higher directories in the
+directory hierarchy.  Finally, since this hook is run every time we visit
+a file it is important to try and keep those functions efficient, which
+will usually require some of caching.
+@end defvar
+
 @defvar enable-dir-local-variables
 If @code{nil}, directory-local variables are ignored.  This variable
 may be useful for modes that want to ignore directory-locals while
diff --git a/etc/NEWS b/etc/NEWS
index 52486b7bbe9..14e5dafbadc 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2163,6 +2163,10 @@ completion candidate.
 \f
 * Lisp Changes in Emacs 30.1
 
+** New hook 'hack-dir-local-get-variables-functions'.
+This can be used to provide support for other directory-local settings
+beside '.dir-locals.el'.
+
 +++
 ** 'auto-coding-functions' can know the name of the file.
 The functions on this hook take can now find the name of the file to
diff --git a/lisp/files.el b/lisp/files.el
index 210cd0fa7ad..a36ac6b1318 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -3494,6 +3494,8 @@ set-auto-mode
      ;; Check for auto-mode-alist entry in dir-locals.
      (with-demoted-errors "Directory-local variables error: %s"
        ;; Note this is a no-op if enable-local-variables is nil.
+       ;; We don't use `hack-dir-local-get-variables-functions' here, because
+       ;; modes are specific to Emacs.
        (let* ((mode-alist (cdr (hack-dir-local--get-variables
                                 (lambda (key) (eq key 'auto-mode-alist))))))
          (set-auto-mode--apply-alist mode-alist keep-mode-if-same t)))
@@ -4769,7 +4771,7 @@ enable-remote-dir-locals
 
 (defvar hack-dir-local-variables--warned-coding nil)
 
-(defun hack-dir-local--get-variables (predicate)
+(defun hack-dir-local--get-variables (&optional predicate)
   "Read per-directory local variables for the current buffer.
 Return a cons of the form (DIR . ALIST), where DIR is the
 directory name (maybe nil) and ALIST is an alist of all variables
@@ -4799,6 +4801,16 @@ hack-dir-local--get-variables
                (dir-locals-get-class-variables class)
                dir-name nil predicate))))))
 
+(defvar hack-dir-local-get-variables-functions
+  (list #'hack-dir-local--get-variables)
+  "Special hook to compute the set of dir-local variables.
+Every function is called without arguments and should return either
+a cons of the form (DIR . ALIST) or a (possibly empty) list of such conses,
+where ALIST is an alist of (VAR . VAL) settings.
+DIR should be a string (a directory name) and is used to obey
+`safe-local-variable-directories'.
+This hook is run after the major mode has been setup.")
+
 (defun hack-dir-local-variables ()
   "Read per-directory local variables for the current buffer.
 Store the directory-local variables in `dir-local-variables-alist'
@@ -4806,21 +4818,53 @@ hack-dir-local-variables
 
 This does nothing if either `enable-local-variables' or
 `enable-dir-local-variables' are nil."
-  (let* ((items (hack-dir-local--get-variables nil))
-         (dir-name (car items))
-         (variables (cdr items)))
-    (when variables
-      (dolist (elt variables)
-        (if (eq (car elt) 'coding)
-            (unless hack-dir-local-variables--warned-coding
-              (setq hack-dir-local-variables--warned-coding t)
-              (display-warning 'files
-                               "Coding cannot be specified by dir-locals"))
-          (unless (memq (car elt) '(eval mode))
-            (setq dir-local-variables-alist
-                  (assq-delete-all (car elt) dir-local-variables-alist)))
-          (push elt dir-local-variables-alist)))
-      (hack-local-variables-filter variables dir-name))))
+  (let (items)
+    (when (and enable-local-variables
+	       enable-dir-local-variables
+	       (or enable-remote-dir-locals
+		   (not (file-remote-p (or (buffer-file-name)
+					   default-directory)))))
+      (run-hook-wrapped 'hack-dir-local-get-variables-functions
+                        (lambda (fun)
+                          (let ((res (funcall fun)))
+                            (cond
+                             ((null res))
+                             ((consp (car-safe res))
+                              (setq items (append res items)))
+                             (t (push res items)))))))
+    ;; Sort the entries from nearest dir to furthest dir.
+    (setq items (sort (nreverse items)
+                      :key (lambda (x) (length (car-safe x))) :reverse t))
+    ;; Filter out duplicates, preferring the settings from the nearest dir
+    ;; and from the first hook function.
+    (let ((seen nil))
+      (dolist (item items)
+        (when seen ;; Special case seen=nil since it's the most common case.
+          (setcdr item (seq-filter (lambda (vv) (not (memq (car-safe vv) seen)))
+                                   (cdr item))))
+        (setq seen (nconc (seq-difference (mapcar #'car (cdr item))
+                                          '(eval mode))
+                          seen))))
+    ;; Rather than a loop, maybe we should handle all the dirs
+    ;; "together", e.g.  prompting the user only once.  But if so, we'd
+    ;; probably want to also merge the prompt for file-local vars,
+    ;; which comes from the call to `hack-local-variables-filter' in
+    ;; `hack-local-variables'.
+    (dolist (item items)
+      (let ((dir-name (car items))
+            (variables (cdr items)))
+        (when variables
+          (dolist (elt variables)
+            (if (eq (car elt) 'coding)
+                (unless hack-dir-local-variables--warned-coding
+                  (setq hack-dir-local-variables--warned-coding t)
+                  (display-warning 'files
+                                   "Coding cannot be specified by dir-locals"))
+              (unless (memq (car elt) '(eval mode))
+                (setq dir-local-variables-alist
+                      (assq-delete-all (car elt) dir-local-variables-alist)))
+              (push elt dir-local-variables-alist)))
+          (hack-local-variables-filter variables dir-name))))))
 
 (defun hack-dir-local-variables-non-file-buffer ()
   "Apply directory-local variables to a non-file buffer.
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-06 23:51   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-08 12:50     ` Eli Zaretskii
  2024-06-09  4:21       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-09 11:49     ` Stefan Kangas
  1 sibling, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2024-06-08 12:50 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: 70105@debbugs.gnu.org, Björn Bidar
>  <bjorn.bidar@thaodan.de>,
>     10sr <8slashes+git@gmail.com>, Jen-Chieh Shen <jcs090218@gmail.com>
> Date: Thu, 06 Jun 2024 19:51:37 -0400
> 
> I'm hoping this can get into Emacs-30.
> Comments/objections?

Comments:

> +** 'auto-coding-functions' can know the name of the file.
> +The functions on this hook take can now find the name of the file to
                              ^^^^
The "take" part should probably be removed.

> +@defvar hack-dir-local-get-variables-functions
> +This special hook holds the functions that gather the directory-local
> +variables to use for a given buffer.  By default it contains just the
> +function that obeys the other settings described in the present section.
> +But it can be used to add support for more sources of directory-local
> +variables, such as those used by other text editors.
> +
> +The functions on this hook are called with no argument, in the buffer to
> +which we intend to apply the directory-local variables, after the
> +buffer's major mode function has been run, so it can use sources of

I'm guessing you meant "they", not "it", because this refers to
"functions on this hook", right?

> +directory hierarchy.  Finally, since this hook is run every time we visit
> +a file it is important to try and keep those functions efficient, which
> +will usually require some of caching.
                        ^^^^^^^^^^^^^^^
"some kind of caching", perhaps?





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-08 12:50     ` Eli Zaretskii
@ 2024-06-09  4:21       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-09  4:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105

> Comments:
>
>> +** 'auto-coding-functions' can know the name of the file.
>> +The functions on this hook take can now find the name of the file to
>                               ^^^^
> The "take" part should probably be removed.
>
>> +@defvar hack-dir-local-get-variables-functions
>> +This special hook holds the functions that gather the directory-local
>> +variables to use for a given buffer.  By default it contains just the
>> +function that obeys the other settings described in the present section.
>> +But it can be used to add support for more sources of directory-local
>> +variables, such as those used by other text editors.
>> +
>> +The functions on this hook are called with no argument, in the buffer to
>> +which we intend to apply the directory-local variables, after the
>> +buffer's major mode function has been run, so it can use sources of
>
> I'm guessing you meant "they", not "it", because this refers to
> "functions on this hook", right?
>
>> +directory hierarchy.  Finally, since this hook is run every time we visit
>> +a file it is important to try and keep those functions efficient, which
>> +will usually require some of caching.
>                         ^^^^^^^^^^^^^^^
> "some kind of caching", perhaps?

Well, the upside is that the above shows the value of taking one's time
when writing (I was in a bit of a hurry).

Thanks, pushed,


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-06 23:51   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-08 12:50     ` Eli Zaretskii
@ 2024-06-09 11:49     ` Stefan Kangas
  1 sibling, 0 replies; 34+ messages in thread
From: Stefan Kangas @ 2024-06-09 11:49 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii
  Cc: Jen-Chieh Shen, Björn Bidar, 10sr, 70105

Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs@gnu.org> writes:

> I'm hoping this can get into Emacs-30.
> Comments/objections?

Thanks for working on this.

Your patches LGTM with Eli's comments.

>  (defun find-auto-coding (filename size)
> +  ;; FIXME: Shouldn't we use nil rather than "" to mean that there's no file?
> +  ;; FIXME: Clarify what the SOURCE is for in the return value?

BTW, shouldn't this sentence now end with a "."?  :-)





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-09  4:21       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18  6:21           ` Ihor Radchenko
                             ` (4 more replies)
  0 siblings, 5 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18  6:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105

OK, here's the other part.

I pushed to the branch `scratch/emacs-editorconfig` a bunch of patches
which add a few `lisp/editorconfig*.el` files.

The main effect is to define a new (global) minor mode
`editorconfig-mode` (I assumed we'll keep it disabled by default in
Emacs-30, but I think it would make sense to enable by default in
Emacs-31 (i.e. on `master` after the branch is cut)) as well as a new
major mode `editorconfig-conf-mode` to edit `.editorconfig` files.

I'm still working on the actual metadata of that branch, as well as
etc/NEWS and doc, but in the mean time maybe you could look at the code to
see if you have any objections there.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-18  6:21           ` Ihor Radchenko
  2024-06-18 13:17             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18  9:10           ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
                             ` (3 subsequent siblings)
  4 siblings, 1 reply; 34+ messages in thread
From: Ihor Radchenko @ 2024-06-18  6:21 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs@gnu.org> writes:

> OK, here's the other part.
>
> I pushed to the branch `scratch/emacs-editorconfig` a bunch of patches
> which add a few `lisp/editorconfig*.el` files.
>
> The main effect is to define a new (global) minor mode
> `editorconfig-mode` (I assumed we'll keep it disabled by default in
> Emacs-30, but I think it would make sense to enable by default in
> Emacs-31 (i.e. on `master` after the branch is cut)) as well as a new
> major mode `editorconfig-conf-mode` to edit `.editorconfig` files.

Is it possible for major modes to indicate that [*] editorconfig setting
must not be used? In particular, Org mode needs to use a fixed
`tab-width' and editorconfig must not override that (it is a part of the
syntax).

We already had a user reporting problems caused by
https://github.com/editorconfig/editorconfig-emacs where tab-width was
changed to 4 by default.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18  6:21           ` Ihor Radchenko
@ 2024-06-18  9:10           ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
       [not found]           ` <87v826hb13.fsf@>
                             ` (2 subsequent siblings)
  4 siblings, 0 replies; 34+ messages in thread
From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18  9:10 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> OK, here's the other part.
>
> I pushed to the branch `scratch/emacs-editorconfig` a bunch of patches
> which add a few `lisp/editorconfig*.el` files.
>
> The main effect is to define a new (global) minor mode
> `editorconfig-mode` (I assumed we'll keep it disabled by default in
> Emacs-30, but I think it would make sense to enable by default in
> Emacs-31 (i.e. on `master` after the branch is cut)) as well as a new
> major mode `editorconfig-conf-mode` to edit `.editorconfig` files.
>
> I'm still working on the actual metadata of that branch, as well as
> etc/NEWS and doc, but in the mean time maybe you could look at the code to
> see if you have any objections there.
>
>         Stefan

Should your work complement/have a migration path from the upstream
editorconfig Emacs package? It be good to avoid duplication and provide
a smooth transition path.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
       [not found]           ` <87v826hb13.fsf@>
@ 2024-06-18 12:56             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18 12:56 UTC (permalink / raw)
  To: Björn Bidar; +Cc: jcs090218, Eli Zaretskii, 8slashes+git, 70105

>> OK, here's the other part.
>>
>> I pushed to the branch `scratch/emacs-editorconfig` a bunch of patches
>> which add a few `lisp/editorconfig*.el` files.
>>
>> The main effect is to define a new (global) minor mode
>> `editorconfig-mode` (I assumed we'll keep it disabled by default in
>> Emacs-30, but I think it would make sense to enable by default in
>> Emacs-31 (i.e. on `master` after the branch is cut)) as well as a new
>> major mode `editorconfig-conf-mode` to edit `.editorconfig` files.
>>
>> I'm still working on the actual metadata of that branch, as well as
>> etc/NEWS and doc, but in the mean time maybe you could look at the code to
>> see if you have any objections there.
>>
>>         Stefan
>
> Should your work complement/have a migration path from the upstream
> editorconfig Emacs package? It be good to avoid duplication and provide
> a smooth transition path.

"My work" is the integration of the upstream package into Emacs.
The submitted code is currently not completely in sync with upstream,
but mostly because I removed some features which I'm not completely sure
yet if/how we'll support them.  This non-syncness is temporary because
I want to try and have it included in Emacs-30.
Once that is done, I'll work on merging the changes I made back
upstream, as well as smoothing over the remaining differences.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18  6:21           ` Ihor Radchenko
@ 2024-06-18 13:17             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18 16:21               ` Ihor Radchenko
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18 13:17 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

>> I pushed to the branch `scratch/emacs-editorconfig` a bunch of patches
>> which add a few `lisp/editorconfig*.el` files.
>> The main effect is to define a new (global) minor mode
>> `editorconfig-mode` (I assumed we'll keep it disabled by default in
>> Emacs-30, but I think it would make sense to enable by default in
>> Emacs-31 (i.e. on `master` after the branch is cut)) as well as a new
>> major mode `editorconfig-conf-mode` to edit `.editorconfig` files.
> Is it possible for major modes to indicate that [*] editorconfig setting
> must not be used?

In the upstream package, yes, but I have not included that part
currently in the code I submit to Emacs.

> In particular, Org mode needs to use a fixed `tab-width' and
> editorconfig must not override that (it is a part of the syntax).

I don't understand: `tab-width` mostly affects the display, how can it
break Org mode?

In any case, Org is not the only mode with such needs (Makefile, Haskell,
Python, come to mind).  But also, disabling editorconfig wholesale seems
a bit crude.  Maybe we'll need a more targeted way to address the problem
(and there's always `hack-local-variables-hook`).

> We already had a user reporting problems caused by
> https://github.com/editorconfig/editorconfig-emacs where tab-width was
> changed to 4 by default.

The upstream code sets `tab-width` in more cases than the code
I'm submitting, so maybe I already fixed the problem?
Do you have a more precise URL for the issue?


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 13:17             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-18 16:21               ` Ihor Radchenko
  2024-06-18 19:37                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 34+ messages in thread
From: Ihor Radchenko @ 2024-06-18 16:21 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> In particular, Org mode needs to use a fixed `tab-width' and
>> editorconfig must not override that (it is a part of the syntax).
>
> I don't understand: `tab-width` mostly affects the display, how can it
> break Org mode?

Because Org mode syntax depends on indentation for lists:

- parent list
  - sub-list
    - sub-sub-list

When the indentation has tabs in it, (current-indentation) return value
becomes a variable of `tab-width'. As a result, Org file syntax
unexpectedly becomes dependent on seemingly unrelated Emacs
configuration toggle.

(I also considered let-binding `tab-width' when Org parser the file, but
lists will then look funny visually)

> In any case, Org is not the only mode with such needs (Makefile, Haskell,
> Python, come to mind).  But also, disabling editorconfig wholesale seems
> a bit crude.  Maybe we'll need a more targeted way to address the problem
> (and there's always `hack-local-variables-hook`).

I did not imply that editorconfig should be _completely_ disabled.
Just for tab-width in our case.

I guess that `hack-local-variables-hook' should be an ok
option. Although it feels a bit funny to:
1. Set tab-width in org-mode body
2. Set it again in hack-local-variables-hook

>> We already had a user reporting problems caused by
>> https://github.com/editorconfig/editorconfig-emacs where tab-width was
>> changed to 4 by default.
>
> The upstream code sets `tab-width` in more cases than the code
> I'm submitting, so maybe I already fixed the problem?
> Do you have a more precise URL for the issue?

Hmm... Sorry, I cannot see anything in the list archives.
Either I made things up in my mind or it was discussed on IRC/Matrix.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
                             ` (2 preceding siblings ...)
       [not found]           ` <87v826hb13.fsf@>
@ 2024-06-18 19:26           ` Stefan Kangas
  2024-06-18 19:47             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18 23:08           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  4 siblings, 1 reply; 34+ messages in thread
From: Stefan Kangas @ 2024-06-18 19:26 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105

[-- Attachment #1: Type: text/plain, Size: 565 bytes --]

Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs@gnu.org> writes:

> I'm still working on the actual metadata of that branch, as well as
> etc/NEWS and doc, but in the mean time maybe you could look at the code to
> see if you have any objections there.

No objections here.

I've attached a small patch with some minor doc fixes, feel free to use
it if it's of any help.

BTW, package-lint gives the following warning:

540:13: error: You should depend on (emacs "28.1") or the compat
package if you need `dlet'.

[-- Attachment #2: 0001-minor-fixes.patch --]
[-- Type: text/x-patch, Size: 6290 bytes --]

From adf7ddb350bc2ae5edcbfaed17074182e5fca112 Mon Sep 17 00:00:00 2001
From: Stefan Kangas <stefankangas@gmail.com>
Date: Tue, 18 Jun 2024 21:17:21 +0200
Subject: [PATCH] minor fixes

---
 doc/man/editorconfig.texi        | 35 ++++++++++++++++----------------
 lisp/editorconfig-core-handle.el |  3 +--
 lisp/editorconfig.el             |  4 ++--
 3 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/doc/man/editorconfig.texi b/doc/man/editorconfig.texi
index 5e7d3b85552..98bc87743a5 100644
--- a/doc/man/editorconfig.texi
+++ b/doc/man/editorconfig.texi
@@ -1,10 +1,10 @@
 @dircategory Emacs
 @direntry
-* EditorConfig: (editorconfig). EditorConfig Emacs Plugin.
+* EditorConfig: (editorconfig). EditorConfig Plugin.
 @end direntry
 
 @node Top
-@chapter EditorConfig Emacs Plugin
+@chapter EditorConfig Plugin
 @anchor{#editorconfig-emacs-plugin}
 This is an @uref{https://editorconfig.org,EditorConfig} plugin for
 @uref{https://www.gnu.org/software/emacs/,Emacs}.
@@ -23,18 +23,19 @@ Getting Started
 @anchor{#getting-started}
 
 @menu
-* packageel::
+* package::
 * use-package::
 * Manual installation::
 @end menu
 
-@node packageel
+@node package
 @subsection package.el
 @anchor{#package.el}
-This package is available from
-@uref{https://melpa.org/#/editorconfig,MELPA},
-@uref{https://stable.melpa.org/#/editorconfig,MELPA Stable} and
+
+This package is shipped with Emacs.  More recent versions can be
+installed from
 @uref{http://elpa.nongnu.org/nongnu/editorconfig.html,NonGNU ELPA}.
+
 Install from these repositories and enable global minor-mode
 @code{editorconfig-mode}:
 
@@ -43,7 +44,7 @@ packageel
 @end verbatim
 
 Normally, enabling @code{editorconfig-mode} should be enough for this
-plugin to work: all other configurations are optional. This mode sets up
+plugin to work: all other configurations are optional.  This mode sets up
 hooks so that EditorConfig properties will be loaded and applied to the
 new buffers automatically when visiting files.
 
@@ -129,7 +130,7 @@ File Type file_type_ext file_type_emacs
 @subsection File Type (file_type_ext, file_type_emacs)
 @anchor{#file-type-file_type_ext-file_type_emacs}
 File-type feature is currently disabled, because this package is now
-undergoing big internal refactoring. For those who want this
+undergoing big internal refactoring.  For those who want this
 functionality, please consider using
 @uref{https://github.com/10sr/editorconfig-custom-majormode-el,editorconfig-custom-majormode}.
 
@@ -159,7 +160,7 @@ editorconfig-trim-whitespaces-mode
 
 One possible value is
 @uref{https://github.com/lewang/ws-butler,@code{ws-butler-mode}}, with
-which only lines touched get trimmed. To use it, add following to your
+which only lines touched get trimmed.  To use it, add following to your
 init.el:
 
 @verbatim
@@ -215,7 +216,7 @@ Troubleshooting
 @code{M-x editorconfig-display-current-properties}.
 
 This command will open a new buffer and display the EditorConfig
-properties loaded for current buffer. You can check if EditorConfig
+properties loaded for current buffer.  You can check if EditorConfig
 properties were not read for buffers at all, or they were loaded but did
 not take effect for some other reasons.
 
@@ -232,8 +233,8 @@ Indentation for new major-modes
 @code{indent_size} property.
 
 By default this plugin ships with settings for many major-modes, but,
-sorry to say, it cannot be perfect. Especially it is difficult to
-support brand-new major-modes. Please feel free to submit issue or
+sorry to say, it cannot be perfect.  Especially it is difficult to
+support brand-new major-modes.  Please feel free to submit issue or
 pull-request for such major-mode!
 
 Supported major-modes and their indentation configs are defined in the
@@ -243,13 +244,13 @@ Not work at all for FOO-mode!
 @subsection Not work at all for FOO-mode!
 @anchor{#not-work-at-all-for-foo-mode}
 Most cases properties are loaded just after visiting files when
-@code{editorconfig-mode} is enabled. But it is known that there are
+@code{editorconfig-mode} is enabled.  But it is known that there are
 major-modes that this mechanism does not work for and require explicit
 call of @code{editorconfig-apply}.
 
 Typically it will occur when the major-mode is not defined using
 @code{define-derived-mode} (@code{rpm-spec-mode} is an example for
-this). Please feel free to submit issues if you find such modes!
+this).  Please feel free to submit issues if you find such modes!
 
 @node Submitting Bugs and Feature Requests
 @section Submitting Bugs and Feature Requests
@@ -288,10 +289,10 @@ License
 
 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
+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 @url{https://www.gnu.org/licenses/}.
+with this program.  If not, see @url{https://www.gnu.org/licenses/}.
 
 @bye
diff --git a/lisp/editorconfig-core-handle.el b/lisp/editorconfig-core-handle.el
index d225e1456ba..c24afa11455 100644
--- a/lisp/editorconfig-core-handle.el
+++ b/lisp/editorconfig-core-handle.el
@@ -74,8 +74,7 @@ editorconfig-core-handle
   Last modified time of .editorconfig file.
 
 `path'
-  Absolute path to .editorconfig file.'
-"
+  Absolute path to .editorconfig file."
   (top-props nil)
   (sections nil)
   (mtime nil)
diff --git a/lisp/editorconfig.el b/lisp/editorconfig.el
index 8c34f94093c..a7e34434258 100644
--- a/lisp/editorconfig.el
+++ b/lisp/editorconfig.el
@@ -1,4 +1,4 @@
-;;; editorconfig.el --- EditorConfig Emacs Plugin  -*- lexical-binding: t -*-
+;;; editorconfig.el --- EditorConfig Plugin  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2011-2024 EditorConfig Team
 
@@ -182,7 +182,7 @@ editorconfig-indentation-alist
     (web-mode . editorconfig--get-indentation-web-mode)
     (zig-mode zig-indent-offset)
     )
-  "Alist of indentation setting methods by modes
+  "Alist of indentation setting methods by modes.
 
 This is a fallback used for those modes which don't set
 `editorconfig-indent-size-vars'.
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 16:21               ` Ihor Radchenko
@ 2024-06-18 19:37                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-18 19:55                   ` Ihor Radchenko
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18 19:37 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

>>> In particular, Org mode needs to use a fixed `tab-width' and
>>> editorconfig must not override that (it is a part of the syntax).
>> I don't understand: `tab-width` mostly affects the display, how can it
>> break Org mode?
> Because Org mode syntax depends on indentation for lists:
>
> - parent list
>   - sub-list
>     - sub-sub-list
>
> When the indentation has tabs in it, (current-indentation) return value
> becomes a variable of `tab-width'. As a result, Org file syntax
> unexpectedly becomes dependent on seemingly unrelated Emacs
> configuration toggle.
> (I also considered let-binding `tab-width' when Org parser the file, but
> lists will then look funny visually)

If you use the `tab-width` set by the user then you have the advantage
that you parse the code in a way that is consistent with what the users
see (so the problem only bites the users who don't look at their code).

If you parse with a fixed `tab-width` OTOH the user may be puzzled
because the code looks like one thing to them but you parse it as
something else.

>> In any case, Org is not the only mode with such needs (Makefile, Haskell,
>> Python, come to mind).  But also, disabling editorconfig wholesale seems
>> a bit crude.  Maybe we'll need a more targeted way to address the problem
>> (and there's always `hack-local-variables-hook`).
> I did not imply that editorconfig should be _completely_ disabled.
> Just for tab-width in our case.

I mentioned it because that's the option that the upstream package offers.

> I guess that `hack-local-variables-hook' should be an ok
> option. Although it feels a bit funny to:
> 1. Set tab-width in org-mode body
> 2. Set it again in hack-local-variables-hook

There's also the option of saying that it's the user's fault.

It's hard to tell in general what would be the right behavior, so
I think it's important we look at concrete cases.

> Hmm... Sorry, I cannot see anything in the list archives.
> Either I made things up in my mind or it was discussed on IRC/Matrix.

I guess we'll have to wait to see if the issue pops up again.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 19:26           ` Stefan Kangas
@ 2024-06-18 19:47             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18 19:47 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

>> I'm still working on the actual metadata of that branch, as well as
>> etc/NEWS and doc, but in the mean time maybe you could look at the code to
>> see if you have any objections there.
> No objections here.
> I've attached a small patch with some minor doc fixes, feel free to use
> it if it's of any help.

Thanks. I'm planning on integrating the texi into Emacs's user manual,
so I'll probably have to massage it significantly.

> BTW, package-lint gives the following warning:
> 540:13: error: You should depend on (emacs "28.1") or the compat
> package if you need `dlet'.

Good catch, thanks.  It's not an issue for `master` (it's even in code
that's not used on `master`), but I'll have to deal with that when
I send the patches upstream.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 19:37                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-18 19:55                   ` Ihor Radchenko
  2024-06-18 20:07                     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 34+ messages in thread
From: Ihor Radchenko @ 2024-06-18 19:55 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> (I also considered let-binding `tab-width' when Org parser the file, but
>> lists will then look funny visually)
>
> If you use the `tab-width` set by the user then you have the advantage
> that you parse the code in a way that is consistent with what the users
> see (so the problem only bites the users who don't look at their code).

Indeed, but what if an Org file comes from another user, with different
tab-width? Parsing it differently is simply wrong.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 19:55                   ` Ihor Radchenko
@ 2024-06-18 20:07                     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18 20:07 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

>>> (I also considered let-binding `tab-width' when Org parser the file, but
>>> lists will then look funny visually)
>> If you use the `tab-width` set by the user then you have the advantage
>> that you parse the code in a way that is consistent with what the users
>> see (so the problem only bites the users who don't look at their code).
> Indeed, but what if an Org file comes from another user, with different
> tab-width?  Parsing it differently is simply wrong.

Exactly: there's no way to win in all cases.  Which is why I think it's
important to see the real cases so we can have a better idea of the
origin of the problem and how best to mitigate it.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
                             ` (3 preceding siblings ...)
  2024-06-18 19:26           ` Stefan Kangas
@ 2024-06-18 23:08           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19  5:48             ` Rudolf Schlatte
                               ` (2 more replies)
  4 siblings, 3 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-18 23:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105

[-- Attachment #1: Type: text/plain, Size: 498 bytes --]

> I'm still working on the actual metadata of that branch, as well as
> etc/NEWS and doc, but in the mean time maybe you could look at the code to
> see if you have any objections there.

OK, I have a first cut at the doc done.
So, here's what I'm proposing, presented as a single diff.
Some commit messages still need to be improved (and I just noticed that
the files' copyright lines also need to be fixed), but other than that,
I think it's about ready.

Comments?  Objections?


        Stefan

[-- Attachment #2: editorconfig.patch --]
[-- Type: text/x-diff, Size: 70887 bytes --]

diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 6bf4cbe00df..5287a90bb71 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1550,6 +1550,41 @@ Directory Variables
 do not visit a file directly but perform work within a directory, such
 as Dired buffers (@pxref{Dired}).
 
+@node EditorConfig support
+@subsubsection Per-Directory Variables via EditorConfig
+@cindex EditorConfig support
+
+The EditorConfig standard is an alternative to the @code{.dir-locals.el}
+files, which can control only a very small number of variables, but
+has the advantage of being editor-neutral.  Those settings are stored in
+files named @code{.editorconfig}.
+
+If you want Emacs to obey those settings, you need to enable
+the @code{editorconfig-mode} minor mode.  This is usually all that is
+needed: when the mode is activated, Emacs will look for @code{.editorconfig}
+files whenever a file is visited, just as it does for @code{.dir-locals.el}.
+
+When both @code{.editorconfig} and @code{.dir-locals.el} files are
+encountered, the corresponding settings are combined, and in case there
+is overlap, the settings coming from the nearest file take precedence.
+
+The @code{indent_size} setting of the EditorConfig standard does not
+correspond to a fixed variable in Emacs, but instead needs to set
+different variables depending on the major mode.  Ideally all major
+modes should set the corresponding @code{editorconfig-indent-size-vars},
+but if you use a major mode in which @code{indent_size} does not take
+effect because the major mode does not yet support it, you can customize
+the @code{editorconfig-indentation-alist} variable to tell Emacs which
+variables need to be set in that major mode.
+
+Similarly, there are several different ways to ``trim whitespace'' at
+the end of lines.  When the EditorConfig @code{trim_trailing_whitespace}
+setting is used, by default @code{editorconfig-mode} simply calls
+@code{delete-trailing-whitespace} every time you save your file.
+If you prefer some other behavior, You can customize
+@code{editorconfig-trim-whitespaces-mode} to the minor mode of
+your preference, such as @code{ws-butler-mode}.
+
 @node Connection Variables
 @subsection Per-Connection Local Variables
 @cindex local variables, for all remote connections
diff --git a/etc/NEWS b/etc/NEWS
index b2fdbc4a88f..06742d24afe 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1964,6 +1964,14 @@ The following new XML schemas are now supported:
 \f
 * New Modes and Packages in Emacs 30.1
 
+** New package EditorConfig.
+This package provides support for the EditorConfig standard that
+is an editor-neutral way to provide directory local settings.
+It is enabled via a new global minor mode 'editorconfig-mode'
+which makes Emacs obey the '.editorconfig' files.
+And the package also comes with a new major mode 'editorconfig-conf-mode'
+to edit those configuration files.
+
 +++
 ** New package Track-Changes.
 This library is a layer of abstraction above 'before-change-functions'
diff --git a/lisp/editorconfig-conf-mode.el b/lisp/editorconfig-conf-mode.el
new file mode 100644
index 00000000000..2b4ddd4410f
--- /dev/null
+++ b/lisp/editorconfig-conf-mode.el
@@ -0,0 +1,95 @@
+;;; editorconfig-conf-mode.el --- Major mode for editing .editorconfig files  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2011-2024 EditorConfig Team
+
+;; Author: EditorConfig Team <editorconfig@googlegroups.com>
+
+;; See
+;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
+;; or the CONTRIBUTORS file for the list of contributors.
+
+;; This file is part of EditorConfig Emacs Plugin.
+
+;; EditorConfig Emacs Plugin 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.
+
+;; EditorConfig Emacs Plugin 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
+;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Major mode for editing .editorconfig files.
+
+;;; Code:
+
+(require 'conf-mode)
+
+(defvar editorconfig-conf-mode-syntax-table
+  (let ((table (make-syntax-table conf-unix-mode-syntax-table)))
+    (modify-syntax-entry ?\; "<" table)
+    table)
+  "Syntax table in use in `editorconfig-conf-mode' buffers.")
+
+(defvar editorconfig-conf-mode-abbrev-table nil
+  "Abbrev table in use in `editorconfig-conf-mode' buffers.")
+(define-abbrev-table 'editorconfig-conf-mode-abbrev-table ())
+
+;;;###autoload
+(define-derived-mode editorconfig-conf-mode conf-unix-mode "Conf[EditorConfig]"
+  "Major mode for editing .editorconfig files."
+  (set-variable 'indent-line-function 'indent-relative)
+  (let ((key-property-list
+         '("charset"
+           "end_of_line"
+           "file_type_emacs"
+           "file_type_ext"
+           "indent_size"
+           "indent_style"
+           "insert_final_newline"
+           "max_line_length"
+           "root"
+           "tab_width"
+           "trim_trailing_whitespace"))
+        (key-value-list
+         '("unset"
+           "true"
+           "false"
+           "lf"
+           "cr"
+           "crlf"
+           "space"
+           "tab"
+           "latin1"
+           "utf-8"
+           "utf-8-bom"
+           "utf-16be"
+           "utf-16le"))
+        (font-lock-value
+         '(("^[ \t]*\\[\\(.+?\\)\\]" 1 font-lock-type-face)
+           ("^[ \t]*\\(.+?\\)[ \t]*[=:]" 1 font-lock-variable-name-face))))
+
+    ;; Highlight all key values
+    (dolist (key-value key-value-list)
+      (push `(,(format "[=:][ \t]*\\(%s\\)\\([ \t]\\|$\\)" key-value)
+              1 font-lock-constant-face)
+            font-lock-value))
+    ;; Highlight all key properties
+    (dolist (key-property key-property-list)
+      (push `(,(format "^[ \t]*\\(%s\\)[ \t]*[=:]" key-property)
+              1 font-lock-builtin-face)
+            font-lock-value))
+
+    (conf-mode-initialize "#" font-lock-value)))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.editorconfig\\'" . editorconfig-conf-mode))
+
+(provide 'editorconfig-conf-mode)
+;;; editorconfig-conf-mode.el ends here
diff --git a/lisp/editorconfig-core-handle.el b/lisp/editorconfig-core-handle.el
new file mode 100644
index 00000000000..868d622af94
--- /dev/null
+++ b/lisp/editorconfig-core-handle.el
@@ -0,0 +1,223 @@
+;;; editorconfig-core-handle.el --- Handle Class for EditorConfig File  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2011-2024 EditorConfig Team
+
+;; Author: EditorConfig Team <editorconfig@googlegroups.com>
+
+;; See
+;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
+;; or the CONTRIBUTORS file for the list of contributors.
+
+;; This file is part of EditorConfig Emacs Plugin.
+
+;; EditorConfig Emacs Plugin 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.
+
+;; EditorConfig Emacs Plugin 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
+;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Handle structures for EditorConfig config file.  This library is used
+;; internally from editorconfig-core.el .
+
+;;; Code:
+
+(require 'cl-lib)
+
+(require 'editorconfig-fnmatch)
+
+(defvar editorconfig-core-handle--cache-hash
+  (make-hash-table :test 'equal)
+  "Hash of EditorConfig filename and its `editorconfig-core-handle' instance.")
+
+(cl-defstruct editorconfig-core-handle-section
+  "Structure representing one section in a .editorconfig file.
+
+Slots:
+
+`name'
+  String of section name (glob string).
+
+`props'
+  Alist of properties: (KEY . VALUE)."
+  (name nil)
+  (props nil))
+
+(defun editorconfig-core-handle-section-get-properties (section file)
+  "Return properties alist when SECTION name match FILE.
+
+FILE should be a relative file name, relative to the directory where
+the `.editorconfig' file which has SECTION lives.
+If not match, return nil."
+  (when (editorconfig-core-handle--fnmatch-p
+         file (editorconfig-core-handle-section-name section))
+    (editorconfig-core-handle-section-props section)))
+
+(cl-defstruct editorconfig-core-handle
+  "Structure representing an .editorconfig file.
+
+Slots:
+`top-props'
+  Alist of top properties like ((\"root\" . \"true\"))
+
+`sections'
+  List of `editorconfig-core-handle-section' structure objects.
+
+`mtime'
+  Last modified time of .editorconfig file.
+
+`path'
+  Absolute path to .editorconfig file."
+  (top-props nil)
+  (sections nil)
+  (mtime nil)
+  (path nil))
+
+
+(defun editorconfig-core-handle (conf)
+  "Return EditorConfig handle for CONF, which should be a file path.
+
+If CONF does not exist return nil."
+  (when (file-readable-p conf)
+    (let ((cached (gethash conf editorconfig-core-handle--cache-hash))
+          (mtime (nth 5 (file-attributes conf))))
+      (if (and cached
+               (equal (editorconfig-core-handle-mtime cached) mtime))
+          cached
+        (let ((parsed (editorconfig-core-handle--parse-file conf)))
+          (puthash conf parsed editorconfig-core-handle--cache-hash))))))
+
+(defun editorconfig-core-handle-root-p (handle)
+  "Return non-nil if HANDLE represent root EditorConfig file.
+
+If HANDLE is nil return nil."
+  (when handle
+    (string-equal "true"
+                  (downcase (or (cdr (assoc "root"
+                                            (editorconfig-core-handle-top-props handle)))
+                                "")))))
+
+(defun editorconfig-core-handle-get-properties (handle file)
+  "Return list of alist of properties from HANDLE for FILE.
+The list returned will be ordered by the lines they appear.
+
+If HANDLE is nil return nil."
+  (declare (obsolete editorconfig-core-handle-get-properties-hash "0.8.0"))
+  (when handle
+    (let* ((dir (file-name-directory (editorconfig-core-handle-path handle)))
+           (file (file-relative-name file dir)))
+      (cl-loop for section in (editorconfig-core-handle-sections handle)
+               for props = (editorconfig-core-handle-section-get-properties
+                            section file)
+               when props collect (copy-alist props)))))
+
+
+(defun editorconfig-core-handle-get-properties-hash (handle file)
+  "Return hash of properties from HANDLE for FILE.
+
+If HANDLE is nil return nil."
+  (when handle
+    (let ((hash (make-hash-table))
+          (file (file-relative-name file (editorconfig-core-handle-path
+                                          handle))))
+      (dolist (section (editorconfig-core-handle-sections handle))
+        (cl-loop for (key . value) in (editorconfig-core-handle-section-get-properties section file)
+                 do (puthash (intern key) value hash)))
+      hash)))
+
+(defun editorconfig-core-handle--fnmatch-p (name pattern)
+  "Return non-nil if NAME match PATTERN.
+If pattern has slash, pattern should be relative to DIR.
+
+This function is a fnmatch with a few modification for EditorConfig usage."
+  (if (string-match-p "/" pattern)
+      (let ((pattern (replace-regexp-in-string "\\`/" "" pattern)))
+        (editorconfig-fnmatch-p name pattern))
+    (editorconfig-fnmatch-p (file-name-nondirectory name) pattern)))
+
+(defsubst editorconfig-core-handle--string-trim (str)
+  "Remove leading and trailing whitespaces from STR."
+  (replace-regexp-in-string "[[:space:]]+\\'"
+                            ""
+                            (replace-regexp-in-string "\\`[[:space:]]+"
+                                                      ""
+                                                      str)))
+
+(defun editorconfig-core-handle--parse-file (conf)
+  "Parse EditorConfig file CONF.
+
+This function returns a `editorconfig-core-handle'.
+If CONF is not found return nil."
+  (when (file-readable-p conf)
+    (with-temp-buffer
+      ;; NOTE: Use this instead of insert-file-contents-literally to enable
+      ;; code conversion
+      (insert-file-contents conf)
+      (goto-char (point-min))
+      (let ((sections ())
+            (top-props nil)
+
+            ;; nil when pattern not appeared yet, "" when pattern is empty ("[]")
+            (pattern nil)
+            ;; Alist of properties for current PATTERN
+            (props ())
+
+            ;; Current line num
+            (current-line-number 1))
+        (while (not (eobp))
+          (skip-chars-forward " \t\f")
+          (cond
+           ((looking-at "\\(?:[#;].*\\)?$")
+            nil)
+
+           ;; Start of section
+           ((looking-at "\\[\\(.*\\)\\][ \t]*$")
+            (let ((newpattern (match-string 1)))
+              (when pattern
+                (push (make-editorconfig-core-handle-section
+                       :name pattern
+                       :props (nreverse props))
+                      sections))
+              (setq props nil)
+              (setq pattern newpattern)))
+
+           ((looking-at "\\([^=: \t]+\\)[ \t]*[=:][ \t]*\\(.*?\\)[ \t]*$")
+            (let ((key (downcase (match-string 1)))
+                  (value (match-string 2)))
+              (when (and (< (length key) 51)
+                         (< (length value) 256))
+                (if pattern
+                    (when (< (length pattern) 4097) ;;FIXME: 4097?
+                      (push `(,key . ,value)
+                            props))
+                  (push `(,key . ,value)
+                        top-props)))))
+
+           (t (error "Error while reading config file: %s:%d:\n    %s\n"
+                     conf current-line-number
+                     (buffer-substring-no-properties (line-beginning-position)
+                                                     (line-end-position)))))
+          (setq current-line-number (1+ current-line-number))
+          (goto-char (point-min))
+          (forward-line (1- current-line-number)))
+        (when pattern
+          (push (make-editorconfig-core-handle-section
+                 :name pattern
+                 :props (nreverse props))
+                sections))
+        (make-editorconfig-core-handle
+         :top-props (nreverse top-props)
+         :sections (nreverse sections)
+         :mtime (nth 5 (file-attributes conf))
+         :path conf)))))
+
+(provide 'editorconfig-core-handle)
+;;; editorconfig-core-handle.el ends here
diff --git a/lisp/editorconfig-core.el b/lisp/editorconfig-core.el
new file mode 100644
index 00000000000..908d5db6f7e
--- /dev/null
+++ b/lisp/editorconfig-core.el
@@ -0,0 +1,156 @@
+;;; editorconfig-core.el --- EditorConfig Core library in Emacs Lisp  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2011-2024 EditorConfig Team
+
+;; Author: EditorConfig Team <editorconfig@googlegroups.com>
+
+;; See
+;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
+;; or the CONTRIBUTORS file for the list of contributors.
+
+;; This file is part of EditorConfig Emacs Plugin.
+
+;; EditorConfig Emacs Plugin 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.
+
+;; EditorConfig Emacs Plugin 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
+;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library is one implementation of EditorConfig Core, which parses
+;; .editorconfig files and returns properties for given files.
+;; This can be used in place of, for example, editorconfig-core-c.
+
+
+;; Use from EditorConfig Emacs Plugin
+
+;; Emacs plugin (v0.5 or later) can utilize this implementation.
+;; By default, the plugin first search for any EditorConfig executable,
+;; and fallback to this library if not found.
+;; If you always want to use this library, add following lines to your init.el:
+
+;;     (setq editorconfig-get-properties-function
+;;           'editorconfig-core-get-properties-hash)
+
+
+;; Functions
+
+;; editorconfig-core-get-properties-hash (&optional file confname confversion)
+
+;; Get EditorConfig properties for FILE.
+
+;; This function is almost same as `editorconfig-core-get-properties', but
+;; returns hash object instead.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(require 'editorconfig-core-handle)
+
+(eval-when-compile
+  (require 'subr-x))
+
+
+(defun editorconfig-core--get-handles (dir confname &optional result)
+  "Get list of EditorConfig handlers for DIR from CONFNAME.
+
+In the resulting list, the handle for root config file comes first, and the
+nearest comes last.
+The list may contains nil when no file was found for directories.
+RESULT is used internally and normally should not be used."
+  (setq dir (expand-file-name dir))
+  (let ((handle (editorconfig-core-handle (concat (file-name-as-directory dir)
+                                                  confname)))
+        (parent (file-name-directory (directory-file-name dir))))
+    (if (or (string= parent dir)
+            (and handle (editorconfig-core-handle-root-p handle)))
+        (cl-remove-if-not #'identity (cons handle result))
+      (editorconfig-core--get-handles parent
+                                      confname
+                                      (cons handle result)))))
+
+(defun editorconfig-core-get-nearest-editorconfig (directory)
+  "Return path to .editorconfig file that is closest to DIRECTORY."
+  (when-let* ((handle (car (last
+                           (editorconfig-core--get-handles directory
+                                                           ".editorconfig")))))
+    (editorconfig-core-handle-path handle)))
+
+(defun editorconfig-core--hash-merge (into update)
+  "Merge two hashes INTO and UPDATE.
+
+This is a destructive function, hash INTO will be modified.
+When the same key exists in both two hashes, values of UPDATE takes precedence."
+  (maphash (lambda (key value) (puthash key value into)) update)
+  into)
+
+(defun editorconfig-core-get-properties-hash (&optional file confname confversion)
+  "Get EditorConfig properties for FILE.
+If FILE is not given, use currently visiting file.
+Give CONFNAME for basename of config file other than .editorconfig.
+If need to specify config format version, give CONFVERSION.
+
+This function is almost same as `editorconfig-core-get-properties', but returns
+hash object instead."
+  (setq file
+        (expand-file-name (or file
+                              buffer-file-name
+                              (error "FILE is not given and `buffer-file-name' is nil"))))
+  (setq confname (or confname ".editorconfig"))
+  (setq confversion (or confversion "0.12.0"))
+  (let ((result (make-hash-table)))
+    (dolist (handle (editorconfig-core--get-handles (file-name-directory file)
+                                                    confname))
+      (editorconfig-core--hash-merge result
+                                     (editorconfig-core-handle-get-properties-hash handle
+                                                                                   file)))
+
+    ;; Downcase known boolean values
+    ;; FIXME: Why not do that in `editorconfig-core-handle--parse-file'?
+    (dolist (key '( end_of_line indent_style indent_size insert_final_newline
+                    trim_trailing_whitespace charset))
+      (when-let* ((val (gethash key result)))
+        (puthash key (downcase val) result)))
+
+    ;; Add indent_size property
+    ;; FIXME: Why?  Which part of the spec requires that?
+    ;;(let ((v-indent-size (gethash 'indent_size result))
+    ;;      (v-indent-style (gethash 'indent_style result)))
+    ;;  (when (and (not v-indent-size)
+    ;;             (string= v-indent-style "tab")
+    ;;             ;; If VERSION < 0.9.0, indent_size should have no default value
+    ;;             (version<= "0.9.0"
+    ;;                        confversion))
+    ;;    (puthash 'indent_size
+    ;;             "tab"
+    ;;             result)))
+    ;; Add tab_width property
+    ;; FIXME: Why?  Which part of the spec requires that?
+    ;;(let ((v-indent-size (gethash 'indent_size result))
+    ;;      (v-tab-width (gethash 'tab_width result)))
+    ;;  (when (and v-indent-size
+    ;;             (not v-tab-width)
+    ;;             (not (string= v-indent-size "tab")))
+    ;;    (puthash 'tab_width v-indent-size result)))
+    ;; Update indent-size property
+    ;; FIXME: Why?  Which part of the spec requires that?
+    ;;(let ((v-indent-size (gethash 'indent_size result))
+    ;;      (v-tab-width (gethash 'tab_width result)))
+    ;;  (when (and v-indent-size
+    ;;             v-tab-width
+    ;;             (string= v-indent-size "tab"))
+    ;;    (puthash 'indent_size v-tab-width result)))
+
+    result))
+
+(provide 'editorconfig-core)
+;;; editorconfig-core.el ends here
diff --git a/lisp/editorconfig-fnmatch.el b/lisp/editorconfig-fnmatch.el
new file mode 100644
index 00000000000..74d1795ee75
--- /dev/null
+++ b/lisp/editorconfig-fnmatch.el
@@ -0,0 +1,292 @@
+;;; editorconfig-fnmatch.el --- Glob pattern matching in Emacs lisp  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2011-2024 EditorConfig Team
+
+;; Author: EditorConfig Team <editorconfig@googlegroups.com>
+
+;; See
+;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
+;; or the CONTRIBUTORS file for the list of contributors.
+
+;; This file is part of EditorConfig Emacs Plugin.
+
+;; EditorConfig Emacs Plugin 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.
+
+;; EditorConfig Emacs Plugin 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
+;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; editorconfig-fnmatch.el provides a fnmatch implementation with a few
+;; extensions.
+;; The main usage of this library is glob pattern matching for EditorConfig, but
+;; it can also act solely.
+
+;; editorconfig-fnmatch-p (name pattern)
+
+;; Test whether NAME match PATTERN.
+
+;; PATTERN should be a shell glob pattern, and some zsh-like wildcard matchings
+;; can be used:
+
+;; *           Matches any string of characters, except path separators (/)
+;; **          Matches any string of characters
+;; ?           Matches any single character
+;; [name]      Matches any single character in name
+;; [^name]     Matches any single character not in name
+;; {s1,s2,s3}  Matches any of the strings given (separated by commas)
+;; {min..max}  Matches any number between min and max
+
+
+;; This library is a port from editorconfig-core-py library.
+;; https://github.com/editorconfig/editorconfig-core-py/blob/master/editorconfig/fnmatch.py
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defvar editorconfig-fnmatch--cache-hashtable
+  nil
+  "Cache of shell pattern and its translation.")
+;; Clear cache on file reload
+(setq editorconfig-fnmatch--cache-hashtable
+      (make-hash-table :test 'equal))
+
+
+(defconst editorconfig-fnmatch--left-brace-regexp
+  "\\(^\\|[^\\]\\){"
+  "Regular expression for left brace ({).")
+
+(defconst editorconfig-fnmatch--right-brace-regexp
+  "\\(^\\|[^\\]\\)}"
+  "Regular expression for right brace (}).")
+
+
+(defconst editorconfig-fnmatch--numeric-range-regexp
+  "\\([+-]?[0-9]+\\)\\.\\.\\([+-]?[0-9]+\\)"
+  "Regular expression for numeric range (like {-3..+3}).")
+
+(defun editorconfig-fnmatch--match-num (regexp string)
+  "Return how many times REGEXP is found in STRING."
+  (let ((num 0))
+    ;; START arg does not work as expected in this case
+    (while (string-match regexp string)
+      (setq num (1+ num)
+            string (substring string (match-end 0))))
+    num))
+
+(defun editorconfig-fnmatch-p (string pattern)
+  "Test whether STRING match PATTERN.
+
+Matching ignores case if `case-fold-search' is non-nil.
+
+PATTERN should be a shell glob pattern, and some zsh-like wildcard matchings can
+be used:
+
+*           Matches any string of characters, except path separators (/)
+**          Matches any string of characters
+?           Matches any single character
+[name]      Matches any single character in name
+[^name]     Matches any single character not in name
+{s1,s2,s3}  Matches any of the strings given (separated by commas)
+{min..max}  Matches any number between min and max"
+  (string-match (editorconfig-fnmatch-translate pattern)
+                string))
+
+;;(editorconfig-fnmatch-translate "{a,{-3..3}}.js")
+;;(editorconfig-fnmatch-p "1.js" "{a,{-3..3}}.js")
+
+(defun editorconfig-fnmatch-translate (pattern)
+  "Translate a shell PATTERN to a regular expression.
+
+Translation result will be cached, so same translation will not be done twice."
+  (let ((cached (gethash pattern
+                         editorconfig-fnmatch--cache-hashtable)))
+    (or cached
+        (puthash pattern
+                 (editorconfig-fnmatch--do-translate pattern)
+                 editorconfig-fnmatch--cache-hashtable))))
+
+
+(defun editorconfig-fnmatch--do-translate (pattern &optional nested)
+  "Translate a shell PATTERN to a regular expression.
+
+Set NESTED to t when this function is called from itself.
+
+This function is called from `editorconfig-fnmatch-translate', when no cached
+translation is found for PATTERN."
+  (let ((index 0)
+        (length (length pattern))
+        (brace-level 0)
+        (in-brackets nil)
+        ;; List of strings of resulting regexp, in reverse order.
+        (result ())
+        (is-escaped nil)
+        (matching-braces (= (editorconfig-fnmatch--match-num
+                             editorconfig-fnmatch--left-brace-regexp
+                             pattern)
+                            (editorconfig-fnmatch--match-num
+                             editorconfig-fnmatch--right-brace-regexp
+                             pattern)))
+
+        current-char
+        pos
+        has-slash
+        has-comma
+        num-range)
+
+    (while (< index length)
+      (if (and (not is-escaped)
+               (string-match "[^]\\*?[{},/\\-]+"
+                             ;;(string-match "[^]\\*?[{},/\\-]+" "?.a")
+                             pattern
+                             index)
+               (eq index (match-beginning 0)))
+          (progn
+            (push (regexp-quote (match-string 0 pattern)) result)
+            (setq index (match-end 0)
+                  is-escaped nil))
+
+        (setq current-char (aref pattern index)
+              index (1+ index))
+
+        (cl-case current-char
+          (?*
+           (setq pos index)
+           (if (and (< pos length)
+                    (= (aref pattern pos) ?*))
+               (push ".*" result)
+             (push "[^/]*" result)))
+
+          (??
+           (push "[^/]" result))
+
+          (?\[
+           (if in-brackets
+               (push "\\[" result)
+             (if (= (aref pattern index) ?/)
+                 ;; Slash after an half-open bracket
+                 (progn
+                   (push "\\[/" result)
+                   (setq index (+ index 1)))
+               (setq pos index
+                     has-slash nil)
+               (while (and (< pos length)
+                           (not (= (aref pattern pos) ?\]))
+                           (not has-slash))
+                 (if (and (= (aref pattern pos) ?/)
+                          (not (= (aref pattern (- pos 1)) ?\\)))
+                     (setq has-slash t)
+                   (setq pos (1+ pos))))
+               (if has-slash
+                   (progn
+                     (push (concat "\\["
+                                   (substring pattern
+                                              index
+                                              (1+ pos))
+                                   "\\]")
+                           result)
+                     (setq index (+ pos 2)))
+                 (if (and (< index length)
+                          (memq (aref pattern index)
+                                '(?! ?^)))
+                     (progn
+                       (setq index (1+ index))
+                       (push "[^" result))
+                   (push "[" result))
+                 (setq in-brackets t)))))
+
+          (?-
+           (if in-brackets
+               (push "-" result)
+             (push "\\-" result)))
+
+          (?\]
+           (push "]" result)
+           (setq in-brackets nil))
+
+          (?{
+           (setq pos index
+                 has-comma nil)
+           (while (and (or (and (< pos length)
+                                (not (= (aref pattern pos) ?})))
+                           is-escaped)
+                       (not has-comma))
+             (if (and (eq (aref pattern pos) ?,)
+                      (not is-escaped))
+                 (setq has-comma t)
+               (setq is-escaped (and (eq (aref pattern pos)
+                                         ?\\)
+                                     (not is-escaped))
+                     pos (1+ pos))))
+           (if (and (not has-comma)
+                    (< pos length))
+               (let ((pattern-sub (substring pattern index pos)))
+                 (setq num-range (string-match editorconfig-fnmatch--numeric-range-regexp
+                                               pattern-sub))
+                 (if num-range
+                     (let ((number-start (string-to-number (match-string 1
+                                                                         pattern-sub)))
+                           (number-end (string-to-number (match-string 2
+                                                                       pattern-sub))))
+                       (push (concat "\\(?:"
+                                     (mapconcat #'number-to-string
+                                                (cl-loop for i from number-start to number-end
+                                                         collect i)
+                                                "\\|")
+                                     "\\)")
+                             result))
+                   (let ((inner (editorconfig-fnmatch--do-translate pattern-sub t)))
+                     (push (format "{%s}" inner) result)))
+                 (setq index (1+ pos)))
+             (if matching-braces
+                 (progn
+                   (push "\\(?:" result)
+                   (setq brace-level (1+ brace-level)))
+               (push "{" result))))
+
+          (?,
+           (if (and (> brace-level 0)
+                    (not is-escaped))
+               (push "\\|" result)
+             (push "\\," result)))
+
+          (?}
+           (if (and (> brace-level 0)
+                    (not is-escaped))
+               (progn
+                 (push "\\)" result)
+                 (setq brace-level (- brace-level 1)))
+             (push "}" result)))
+
+          (?/
+           (if (and (<= (+ index 3) (length pattern))
+                    (string= (substring pattern index (+ index 3)) "**/"))
+               (progn
+                 (push "\\(?:/\\|/.*/\\)" result)
+                 (setq index (+ index 3)))
+             (push "/" result)))
+
+          (t
+           (unless (= current-char ?\\)
+             (push (regexp-quote (char-to-string current-char)) result))))
+
+        (if (= current-char ?\\)
+            (progn (when is-escaped
+                     (push "\\\\" result))
+                   (setq is-escaped (not is-escaped)))
+          (setq is-escaped nil))))
+    (unless nested
+      (setq result `("\\'" ,@result "\\`")))
+    (apply #'concat (reverse result))))
+
+(provide 'editorconfig-fnmatch)
+;;; editorconfig-fnmatch.el ends here
diff --git a/lisp/editorconfig-tools.el b/lisp/editorconfig-tools.el
new file mode 100644
index 00000000000..4738a6c4d94
--- /dev/null
+++ b/lisp/editorconfig-tools.el
@@ -0,0 +1,119 @@
+;;; editorconfig-tools.el --- Editorconfig tools   -*- lexical-binding: t -*-
+
+;; Copyright (C) 2011-2024 EditorConfig Team
+
+;; Author: EditorConfig Team <editorconfig@googlegroups.com>
+
+;; See
+;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
+;; or the CONTRIBUTORS file for the list of contributors.
+
+;; This file is part of EditorConfig Emacs Plugin.
+
+;; EditorConfig Emacs Plugin 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.
+
+;; EditorConfig Emacs Plugin 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
+;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Some utility commands for users, not used from editorconfig-mode.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(eval-when-compile
+  (require 'subr-x))
+
+
+(require 'editorconfig)
+
+;;;###autoload
+(defun editorconfig-apply ()
+  "Get and apply EditorConfig properties to current buffer.
+
+This function does not respect the values of `editorconfig-exclude-modes' and
+`editorconfig-exclude-regexps' and always applies available properties.
+Use `editorconfig-mode-apply' instead to make use of these variables."
+  (interactive)
+  (when buffer-file-name
+    (condition-case err
+        (progn
+          (let ((props (editorconfig-call-get-properties-function buffer-file-name)))
+            (condition-case err
+                (run-hook-with-args 'editorconfig-hack-properties-functions props)
+              (error
+               (display-warning '(editorconfig editorconfig-hack-properties-functions)
+                                (format "Error while running editorconfig-hack-properties-functions, abort running hook: %S"
+                                        err)
+                                :warning)))
+            (setq editorconfig-properties-hash props)
+            (editorconfig-set-local-variables props)
+            (editorconfig-set-coding-system-revert
+             (gethash 'end_of_line props)
+             (gethash 'charset props))
+            (condition-case err
+                (run-hook-with-args 'editorconfig-after-apply-functions props)
+              (error
+               (display-warning '(editorconfig editorconfig-after-apply-functions)
+                                (format "Error while running editorconfig-after-apply-functions, abort running hook: %S"
+                                        err)
+                                :warning)))))
+      (error
+       (display-warning '(editorconfig editorconfig-apply)
+                        (format "Error in editorconfig-apply, styles will not be applied: %S" err)
+                        :error)))))
+
+(defun editorconfig-mode-apply ()
+  "Get and apply EditorConfig properties to current buffer.
+
+This function does nothing when the major mode is listed in
+`editorconfig-exclude-modes', or variable `buffer-file-name' matches
+any of regexps in `editorconfig-exclude-regexps'."
+  (interactive)
+  (when (and major-mode buffer-file-name)
+    (editorconfig-apply)))
+
+
+;;;###autoload
+(defun editorconfig-find-current-editorconfig ()
+  "Find the closest .editorconfig file for current file."
+  (interactive)
+  (eval-and-compile (require 'editorconfig-core))
+  (when-let* ((file (editorconfig-core-get-nearest-editorconfig
+                    default-directory)))
+    (find-file file)))
+
+;;;###autoload
+(defun editorconfig-display-current-properties ()
+  "Display EditorConfig properties extracted for current buffer."
+  (interactive)
+  (if editorconfig-properties-hash
+      (let ((buf (get-buffer-create "*EditorConfig Properties*"))
+            (file buffer-file-name)
+            (props editorconfig-properties-hash))
+        (with-current-buffer buf
+          (erase-buffer)
+          (insert (format "# EditorConfig for %s\n" file))
+          (maphash (lambda (k v)
+                     (insert (format "%S = %s\n" k v)))
+                   props))
+        (display-buffer buf))
+    (message "Properties are not applied to current buffer yet.")
+    nil))
+;;;###autoload
+(defalias 'describe-editorconfig-properties
+  #'editorconfig-display-current-properties)
+
+
+(provide 'editorconfig-tools)
+;;; editorconfig-tools.el ends here
diff --git a/lisp/editorconfig.el b/lisp/editorconfig.el
new file mode 100644
index 00000000000..a7e34434258
--- /dev/null
+++ b/lisp/editorconfig.el
@@ -0,0 +1,711 @@
+;;; editorconfig.el --- EditorConfig Plugin  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2011-2024 EditorConfig Team
+
+;; Author: EditorConfig Team <editorconfig@googlegroups.com>
+;; Version: 0.11.0
+;; URL: https://github.com/editorconfig/editorconfig-emacs#readme
+;; Package-Requires: ((emacs "26.1"))
+;; Keywords: convenience editorconfig
+
+;; See
+;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
+;; or the CONTRIBUTORS file for the list of contributors.
+
+;; This file is part of EditorConfig Emacs Plugin.
+
+;; EditorConfig Emacs Plugin 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.
+
+;; EditorConfig Emacs Plugin 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
+;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; EditorConfig helps developers define and maintain consistent
+;; coding styles between different editors and IDEs.
+
+;; The EditorConfig project consists of a file format for defining
+;; coding styles and a collection of text editor plugins that enable
+;; editors to read the file format and adhere to defined styles.
+;; EditorConfig files are easily readable and they work nicely with
+;; version control systems.
+
+;;; News:
+
+;; - In `editorconfig-indentation-alist', if a mode is associated to a function
+;;   that function should not set the vars but should instead *return* them.
+;; - New var `editorconfig-indent-size-vars' for major modes to set.
+;; - New hook `editorconfig-get-local-variables-functions' to support
+;;   additional settings.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(eval-when-compile (require 'subr-x))
+
+(require 'editorconfig-core)
+
+(defgroup editorconfig nil
+  "EditorConfig Emacs Plugin.
+
+EditorConfig helps developers define and maintain consistent
+coding styles between different editors and IDEs."
+  :tag "EditorConfig"
+  :prefix "editorconfig-"
+  :group 'tools)
+
+(when (< emacs-major-version 30)
+  (define-obsolete-variable-alias
+    'edconf-custom-hooks
+    'editorconfig-after-apply-functions
+    "0.5")
+  (define-obsolete-variable-alias
+    'editorconfig-custom-hooks
+    'editorconfig-after-apply-functions
+    "0.7.14")
+  (defcustom editorconfig-after-apply-functions ()
+    "A list of functions after loading common EditorConfig settings.
+
+Each element in this list is a hook function.  This hook function
+takes one parameter, which is a property hash table.  The value
+of properties can be obtained through gethash function.
+
+The hook does not have to be coding style related; you can add
+whatever functionality you want.  For example, the following is
+an example to add a new property emacs_linum to decide whether to
+show line numbers on the left:
+
+  (add-hook \\='editorconfig-after-apply-functions
+    \\='(lambda (props)
+       (let ((show-line-num (gethash \\='emacs_linum props)))
+         (cond ((equal show-line-num \"true\") (linum-mode 1))
+           ((equal show-line-num \"false\") (linum-mode 0))))))
+
+This hook will be run even when there are no matching sections in
+\".editorconfig\", or no \".editorconfig\" file was found at all."
+    :type 'hook))
+
+(when (< emacs-major-version 30)
+  (defcustom editorconfig-hack-properties-functions ()
+    "A list of function to alter property values before applying them.
+
+These functions will be run after loading \".editorconfig\" files and before
+applying them to current buffer, so that you can alter some properties from
+\".editorconfig\" before they take effect.
+\(Since 2021/08/30 (v0.9.0): Buffer coding-systems are set before running
+this functions, so this variable cannot be used to change coding-systems.)
+
+For example, Makefiles always use tab characters for indentation: you can
+overwrite \"indent_style\" property when current `major-mode' is a
+`makefile-mode' with following code:
+
+  (add-hook \\='editorconfig-hack-properties-functions
+            \\='(lambda (props)
+               (when (derived-mode-p \\='makefile-mode)
+                 (puthash \\='indent_style \"tab\" props))))
+
+This hook will be run even when there are no matching sections in
+\".editorconfig\", or no \".editorconfig\" file was found at all."
+    :type 'hook))
+(make-obsolete-variable 'editorconfig-hack-properties-functions
+                        'editorconfig-get-local-variables-functions
+                        "2024")
+
+(define-obsolete-variable-alias
+  'edconf-indentation-alist
+  'editorconfig-indentation-alist
+  "0.5")
+(defcustom editorconfig-indentation-alist
+  ;; For contributors: Sort modes in alphabetical order
+  `((apache-mode apache-indent-level)
+    (bash-ts-mode sh-basic-offset
+                  sh-indentation)
+    (bpftrace-mode c-basic-offset)
+    (c++-ts-mode c-basic-offset
+                 c-ts-mode-indent-offset)
+    (c-ts-mode c-basic-offset
+               c-ts-mode-indent-offset)
+    (cmake-mode cmake-tab-width)
+    (cmake-ts-mode cmake-tab-width
+                   cmake-ts-mode-indent-offset)
+    (csharp-mode c-basic-offset)
+    (csharp-ts-mode c-basic-offset
+                    csharp-ts-mode-indent-offset)
+    (emacs-lisp-mode . editorconfig--get-indentation-lisp-mode)
+    (ess-mode ess-indent-offset)
+    (feature-mode feature-indent-offset
+                  feature-indent-level)
+    (gdscript-mode gdscript-indent-offset)
+    (go-ts-mode go-ts-mode-indent-offset)
+    (hcl-mode hcl-indent-level)
+    (html-ts-mode html-ts-mode-indent-offset)
+    (java-ts-mode c-basic-offset
+                  java-ts-mode-indent-offset)
+    (js-mode js-indent-level)
+    (jsonian-mode jsonian-default-indentation)
+    (latex-mode . editorconfig--get-indentation-latex-mode)
+    (lisp-mode . editorconfig--get-indentation-lisp-mode)
+    (matlab-mode matlab-indent-level)
+    (octave-mode octave-block-offset)
+    ;; No need to change `php-mode-coding-style' value for php-mode
+    ;; since we run editorconfig later than it resets `c-basic-offset'.
+    ;; See https://github.com/editorconfig/editorconfig-emacs/issues/116
+    ;; for details.
+    (php-mode c-basic-offset)
+    (php-ts-mode php-ts-mode-indent-offset)
+    (ps-mode ps-mode-tab)
+    (ruby-mode ruby-indent-level)
+    (rust-ts-mode rust-indent-offset
+                  rust-ts-mode-indent-offset)
+    (scss-mode css-indent-offset)
+    (sgml-mode sgml-basic-offset)
+    (sh-mode sh-indentation)
+    (svelte-mode svelte-basic-offset)
+    (tcl-mode tcl-indent-level
+              tcl-continued-indent-level)
+    (toml-ts-mode toml-ts-mode-indent-offset)
+    (verilog-mode verilog-indent-level
+                  verilog-indent-level-behavioral
+                  verilog-indent-level-declaration
+                  verilog-indent-level-module
+                  verilog-cexp-indent
+                  verilog-case-indent)
+    (web-mode . editorconfig--get-indentation-web-mode)
+    (zig-mode zig-indent-offset)
+    )
+  "Alist of indentation setting methods by modes.
+
+This is a fallback used for those modes which don't set
+`editorconfig-indent-size-vars'.
+
+Each element should look like (MODE . SETTING) where SETTING
+should obey the same rules as `editorconfig-indent-size-vars'."
+  :type '(alist :key-type symbol
+                :value-type (choice function (repeat symbol)))
+  :risky t)
+
+(defcustom editorconfig-trim-whitespaces-mode nil
+  "Buffer local minor-mode to use to trim trailing whitespaces.
+
+If set, enable that mode when `trim_trailing_whitespace` is set to true.
+Otherwise, use `delete-trailing-whitespace'."
+  :type 'symbol)
+
+(defvar editorconfig-properties-hash nil
+  "Hash object of EditorConfig properties that was enabled for current buffer.
+Set by `editorconfig-apply' and nil if that is not invoked in
+current buffer yet.")
+(make-variable-buffer-local 'editorconfig-properties-hash)
+(put 'editorconfig-properties-hash
+     'permanent-local
+     t)
+
+(defvar editorconfig-lisp-use-default-indent nil
+  "Selectively ignore the value of indent_size for Lisp files.
+Prevents `lisp-indent-offset' from being set selectively.
+
+nil - `lisp-indent-offset' is always set normally.
+t   - `lisp-indent-offset' is never set normally
+       (always use default indent for lisps).
+number - `lisp-indent-offset' is not set only if indent_size is
+         equal to this number.  For example, if this is set to 2,
+         `lisp-indent-offset' will not be set only if indent_size is 2.")
+
+(define-error 'editorconfig-error
+              "Error thrown from editorconfig lib")
+
+(defun editorconfig-error (&rest args)
+  "Signal an `editorconfig-error'.
+Make a message by passing ARGS to `format-message'."
+  (signal 'editorconfig-error (list (apply #'format-message args))))
+
+(defun editorconfig-string-integer-p (string)
+  "Return non-nil if STRING represents integer."
+  (and (stringp string)
+       (string-match-p "\\`[0-9]+\\'" string)))
+
+(defun editorconfig--get-indentation-web-mode (size)
+  `((web-mode-indent-style . 2)
+    (web-mode-markup-indent-offset . ,size)
+    (web-mode-css-indent-offset . ,size)
+    (web-mode-code-indent-offset . ,size)))
+
+(defun editorconfig--get-indentation-latex-mode (size)
+  "Vars to set `latex-mode' indent size to SIZE."
+  `((tex-indent-basic . ,size)
+    (tex-indent-item . ,size)
+    (tex-indent-arg . ,(* 2 size))
+    ;; For AUCTeX
+    (TeX-brace-indent-level . ,size)
+    (LaTeX-indent-level . ,size)
+    (LaTeX-item-indent . ,(- size))))
+
+(defun editorconfig--get-indentation-lisp-mode (size)
+  "Set indent size to SIZE for Lisp mode(s)."
+  (when (cond ((null editorconfig-lisp-use-default-indent)  t)
+              ((eql t editorconfig-lisp-use-default-indent) nil)
+              ((numberp editorconfig-lisp-use-default-indent)
+               (not (eql size editorconfig-lisp-use-default-indent)))
+              (t t))
+    `((lisp-indent-offset . ,size))))
+
+(cl-defun editorconfig--should-set (symbol)
+  "Determine if editorconfig should set SYMBOL."
+  (display-warning '(editorconfig editorconfig--should-set)
+                   (format "symbol: %S"
+                           symbol)
+                   :debug)
+  (when (assq symbol file-local-variables-alist)
+    (cl-return-from editorconfig--should-set
+      nil))
+
+  (when (assq symbol dir-local-variables-alist)
+    (cl-return-from editorconfig--should-set
+      nil))
+
+  t)
+
+(defvar editorconfig-indent-size-vars
+  #'editorconfig--default-indent-size-function
+  "Rule to use to set a given `indent_size'.
+Can take the form of a function, in which case we call it with a single SIZE
+argument (an integer) and it should return a list of (VAR . VAL) pairs.
+Otherwise it can be a list of symbols (those which should be set to SIZE).
+Major modes are expected to set this buffer-locally.")
+
+(defun editorconfig--default-indent-size-function (size)
+  (let ((parents (if (fboundp 'derived-mode-all-parents) ;Emacs-30
+                     (derived-mode-all-parents major-mode)
+                   (let ((modes nil)
+                         (mode major-mode))
+                     (while mode
+                       (push mode modes)
+                       (setq mode (get mode 'derived-mode--parent)))
+                     (nreverse modes))))
+        entry)
+    (let ((parents parents))
+      (while (and parents (not entry))
+        (setq entry (assq (pop parents) editorconfig-indentation-alist))))
+    (or
+     (when entry
+       (let ((rule (cdr entry)))
+         ;; Filter out settings of unknown vars.
+         (delq nil
+               (mapcar (lambda (elem)
+                         (let ((v (car elem)))
+                           (cond
+                            ((not (symbolp v))
+                             (message "Unsupported element in `editorconfig-indentation-alist': %S" elem))
+                            ((or (eq 'eval v) (boundp v)) elem))))
+                       (if (functionp rule)
+                           (funcall rule size)
+                         (mapcar (lambda (elem) `(,elem . ,size)) rule))))))
+     ;; Fallback, let's try and guess.
+     (let ((suffixes '("-indent-level" "-basic-offset" "-indent-offset"
+                       "-block-offset"))
+           (guess ()))
+       (while (and parents (not guess))
+         (let* ((mode (pop parents))
+                (modename (symbol-name mode))
+                (name (substring modename 0
+                                 (string-match "-mode\\'" modename))))
+           (dolist (suffix suffixes)
+             (let ((sym (intern-soft (concat name suffix))))
+               (when (and sym (boundp sym))
+                 (setq guess sym))))))
+       (when guess `((,guess . ,size))))
+     (and (local-variable-p 'smie-rules-function)
+          `((smie-indent-basic . ,size))))))
+
+(defun editorconfig--get-indentation (props)
+  "Get indentation vars according to STYLE, SIZE, and TAB_WIDTH."
+  (let ((style (gethash 'indent_style props))
+        (size (gethash 'indent_size props))
+        (tab_width (gethash 'tab_width props)))
+    (when tab_width
+      (setq tab_width (string-to-number tab_width)))
+
+    (setq size
+          (cond ((editorconfig-string-integer-p size)
+                 (string-to-number size))
+                ((equal size "tab")
+                 (or tab_width tab-width))
+                (t
+                 nil)))
+    `(,@(if tab_width `((tab-width . ,tab_width)))
+
+      ,@(pcase style
+          ("space" `((indent-tabs-mode . nil)))
+          ("tab" `((indent-tabs-mode . t))))
+
+      ,@(when (and size (featurep 'evil))
+          `((evil-shift-width . ,size)))
+
+      ,@(cond
+         ((null size) nil)
+         ((functionp editorconfig-indent-size-vars)
+          (funcall editorconfig-indent-size-vars size))
+         (t (mapcar (lambda (v) `(,v . ,size)) editorconfig-indent-size-vars))))))
+
+(defvar-local editorconfig--apply-coding-system-currently nil
+  "Used internally.")
+(put 'editorconfig--apply-coding-system-currently
+     'permanent-local
+     t)
+
+(defun editorconfig-merge-coding-systems (end-of-line charset)
+  "Return merged coding system symbol of END-OF-LINE and CHARSET."
+  (let ((eol (cond
+              ((equal end-of-line "lf") 'undecided-unix)
+              ((equal end-of-line "cr") 'undecided-mac)
+              ((equal end-of-line "crlf") 'undecided-dos)))
+        (cs (cond
+             ((equal charset "latin1") 'iso-latin-1)
+             ((equal charset "utf-8") 'utf-8)
+             ((equal charset "utf-8-bom") 'utf-8-with-signature)
+             ((equal charset "utf-16be") 'utf-16be-with-signature)
+             ((equal charset "utf-16le") 'utf-16le-with-signature))))
+    (if (and eol cs)
+        (merge-coding-systems cs eol)
+      (or eol cs))))
+
+(cl-defun editorconfig-set-coding-system-revert (end-of-line charset)
+  "Set buffer coding system by END-OF-LINE and CHARSET.
+
+This function will revert buffer when the coding-system has been changed."
+  ;; `editorconfig--advice-find-file-noselect' does not use this function
+  (let ((coding-system (editorconfig-merge-coding-systems end-of-line
+                                                          charset)))
+    (display-warning '(editorconfig editorconfig-set-coding-system-revert)
+                     (format "editorconfig-set-coding-system-revert: buffer-file-name: %S | buffer-file-coding-system: %S | coding-system: %S | apply-currently: %S"
+                             buffer-file-name
+                             buffer-file-coding-system
+                             coding-system
+                             editorconfig--apply-coding-system-currently)
+                     :debug)
+    (when (memq coding-system '(nil undecided))
+      (cl-return-from editorconfig-set-coding-system-revert))
+    (when (and buffer-file-coding-system
+               (memq buffer-file-coding-system
+                     (coding-system-aliases (merge-coding-systems coding-system
+                                                                  buffer-file-coding-system))))
+      (cl-return-from editorconfig-set-coding-system-revert))
+    (unless (file-readable-p buffer-file-name)
+      (set-buffer-file-coding-system coding-system)
+      (cl-return-from editorconfig-set-coding-system-revert))
+    (unless (memq coding-system
+                  (coding-system-aliases editorconfig--apply-coding-system-currently))
+      ;; Revert functions might call `editorconfig-apply' again
+      ;; FIXME: I suspect `editorconfig--apply-coding-system-currently'
+      ;; gymnastics is not needed now that we hook into `find-auto-coding'.
+      (unwind-protect
+          (progn
+            (setq editorconfig--apply-coding-system-currently coding-system)
+            ;; Revert without query if buffer is not modified
+            (let ((revert-without-query '(".")))
+              (revert-buffer-with-coding-system coding-system)))
+        (setq editorconfig--apply-coding-system-currently nil)))))
+
+(defun editorconfig--get-trailing-nl (props)
+  "Get the vars to require final newline according to PROPS."
+  (pcase (gethash 'insert_final_newline props)
+    ("true"
+     ;; Keep prefs around how/when the nl is added, if set.
+     `((require-final-newline
+        . ,(or require-final-newline mode-require-final-newline t))))
+    ("false"
+     `((require-final-newline . nil)))))
+
+(defun editorconfig--delete-trailing-whitespace ()
+  "Call `delete-trailing-whitespace' unless the buffer is read-only."
+  (unless buffer-read-only (delete-trailing-whitespace)))
+
+;; Arrange for our (eval . (add-hook ...)) "local var" to be considered safe.
+(defun editorconfig--add-hook-safe-p (exp)
+  (equal exp '(add-hook 'before-save-hook
+                        #'editorconfig--delete-trailing-whitespace nil t)))
+(let ((predicates (get 'add-hook 'safe-local-eval-function)))
+  (when (functionp predicates)
+    (setq predicates (list predicates)))
+  (unless (memq #'editorconfig--add-hook-safe-p predicates)
+    (put 'add-hook 'safe-local-eval-function #'editorconfig--add-hook-safe-p)))
+
+(defun editorconfig--get-trailing-ws (props)
+  "Get vars to trim of trailing whitespace according to PROPS."
+  (pcase (gethash 'trim_trailing_whitespace props)
+    ("true"
+     `((eval
+        . ,(if editorconfig-trim-whitespaces-mode
+               `(,editorconfig-trim-whitespaces-mode 1)
+             '(add-hook 'before-save-hook
+                        #'editorconfig--delete-trailing-whitespace nil t)))))
+    ("false"
+     ;; Just do it right away rather than return a (VAR . VAL), which
+     ;; would be probably more trouble than it's worth.
+     (when editorconfig-trim-whitespaces-mode
+       (funcall editorconfig-trim-whitespaces-mode 0))
+     (remove-hook 'before-save-hook
+                  #'editorconfig--delete-trailing-whitespace t)
+     nil)))
+
+(defun editorconfig--get-line-length (props)
+  "Get the max line length (`fill-column') to PROPS."
+  (let ((length (gethash 'max_line_length props)))
+    (when (and (editorconfig-string-integer-p length)
+               (> (string-to-number length) 0))
+      `((fill-column . ,(string-to-number length))))))
+
+(defun editorconfig-call-get-properties-function (filename)
+  "Call `editorconfig-core-get-properties-hash' with FILENAME and return result.
+
+This function also removes `unset' properties and calls
+`editorconfig-hack-properties-functions'."
+  (if (stringp filename)
+      (setq filename (expand-file-name filename))
+    (editorconfig-error "Invalid argument: %S" filename))
+  (let ((props nil))
+    (condition-case err
+        (setq props (editorconfig-core-get-properties-hash filename))
+      (error
+       (editorconfig-error "Error from editorconfig-core-get-properties-hash: %S"
+                           err)))
+    (cl-loop for k being the hash-keys of props using (hash-values v)
+             when (equal v "unset") do (remhash k props))
+    props))
+
+(defvar editorconfig-get-local-variables-functions
+  '(editorconfig--get-indentation
+    editorconfig--get-trailing-nl
+    editorconfig--get-trailing-ws
+    editorconfig--get-line-length)
+  "Special hook run to convert EditorConfig settings to their Emacs equivalent.
+Every function is called with one argument, a hash-table indexed by
+EditorConfig settings represented as symbols and whose corresponding value
+is represented as a string.  It should return a list of (VAR . VAL) settings
+where VAR is an ELisp variable and VAL is the value to which it should be set.")
+
+(defun editorconfig--get-local-variables (props)
+  "Get variables settings according to EditorConfig PROPS."
+  (let ((alist ()))
+    (run-hook-wrapped 'editorconfig-get-local-variables-functions
+                      (lambda (fun props)
+                        (setq alist (append (funcall fun props) alist))
+                        nil)
+                      props)
+    alist))
+
+(defun editorconfig-set-local-variables (props)
+  "Set buffer variables according to EditorConfig PROPS."
+  (pcase-dolist (`(,var . ,val) (editorconfig--get-local-variables props))
+    (if (eq 'eval var)
+        (eval val t)
+      (when (editorconfig--should-set var)
+        (set (make-local-variable var) val)))))
+
+(defun editorconfig-major-mode-hook ()
+  "Function to run when `major-mode' has been changed.
+
+This functions does not reload .editorconfig file, just sets local variables
+again.  Changing major mode can reset these variables.
+
+This function also executes `editorconfig-after-apply-functions' functions."
+  (display-warning '(editorconfig editorconfig-major-mode-hook)
+                   (format "editorconfig-major-mode-hook: editorconfig-mode: %S, major-mode: %S, -properties-hash: %S"
+                           (and (boundp 'editorconfig-mode)
+                                editorconfig-mode)
+                           major-mode
+                           editorconfig-properties-hash)
+                   :debug)
+  (when (and (bound-and-true-p editorconfig-mode)
+             editorconfig-properties-hash)
+    (editorconfig-set-local-variables editorconfig-properties-hash)
+    (condition-case err
+        (run-hook-with-args 'editorconfig-after-apply-functions editorconfig-properties-hash)
+      (error
+       (display-warning '(editorconfig editorconfig-major-mode-hook)
+                        (format "Error while running `editorconfig-after-apply-functions': %S"
+                                err))))))
+
+(defun editorconfig--advice-find-auto-coding (filename &rest _args)
+  "Consult `charset' setting of EditorConfig."
+  (let ((cs (dlet ((auto-coding-file-name filename))
+              (editorconfig--get-coding-system))))
+    (when cs (cons cs 'EditorConfig))))
+
+(defun editorconfig--advice-find-file-noselect (f filename &rest args)
+  "Get EditorConfig properties and apply them to buffer to be visited.
+
+This function should be added as an advice function to `find-file-noselect'.
+F is that function, and FILENAME and ARGS are arguments passed to F."
+  (let ((props nil)
+        (ret nil))
+    (condition-case err
+        (when (stringp filename)
+          (setq props (editorconfig-call-get-properties-function filename)))
+      (error
+       (display-warning '(editorconfig editorconfig--advice-find-file-noselect)
+                        (format "Failed to get properties, styles will not be applied: %S"
+                                err)
+                        :warning)))
+
+    (setq ret (apply f filename args))
+
+    (condition-case err
+        (with-current-buffer ret
+          (when props
+
+            ;; NOTE: hack-properties-functions cannot affect coding-system value,
+            ;; because it has to be set before initializing buffers.
+            (condition-case err
+                (run-hook-with-args 'editorconfig-hack-properties-functions props)
+              (error
+               (display-warning '(editorconfig editorconfig-hack-properties-functions)
+                                (format "Error while running editorconfig-hack-properties-functions, abort running hook: %S"
+                                        err)
+                                :warning)))
+            (setq editorconfig-properties-hash props)
+            ;; When initializing buffer, `editorconfig-major-mode-hook'
+            ;; will be called before setting `editorconfig-properties-hash', so
+            ;; execute this explicitly here.
+            (editorconfig-set-local-variables props)
+
+            (condition-case err
+                (run-hook-with-args 'editorconfig-after-apply-functions props)
+              (error
+               (display-warning '(editorconfig editorconfig--advice-find-file-noselect)
+                                (format "Error while running `editorconfig-after-apply-functions': %S"
+                                        err))))))
+      (error
+       (display-warning '(editorconfig editorconfig--advice-find-file-noselect)
+                        (format "Error while setting variables from EditorConfig: %S" err))))
+    ret))
+
+(defvar editorconfig--getting-coding-system nil)
+
+(defun editorconfig--get-coding-system (&optional _size)
+  "Return the coding system to use according to EditorConfig.
+Meant to be used on `auto-coding-functions'."
+  (defvar auto-coding-file-name) ;; Emacs≥30
+  (when (and (stringp auto-coding-file-name)
+             (file-name-absolute-p auto-coding-file-name)
+	     ;; Don't recurse infinitely.
+	     (not (member auto-coding-file-name
+	                  editorconfig--getting-coding-system)))
+    (let* ((editorconfig--getting-coding-system
+            (cons auto-coding-file-name editorconfig--getting-coding-system))
+           (props (editorconfig-call-get-properties-function
+                   auto-coding-file-name)))
+      (editorconfig-merge-coding-systems (gethash 'end_of_line props)
+                                         (gethash 'charset props)))))
+
+(defun editorconfig--get-dir-local-variables ()
+  "Return the directory local variables specified via EditorConfig.
+Meant to be used on `hack-dir-local-get-variables-functions'."
+  (when (stringp buffer-file-name)
+    (let* ((props (editorconfig-call-get-properties-function buffer-file-name))
+           (alist (editorconfig--get-local-variables props)))
+      ;; FIXME: Actually, we should loop over the "editorconfig-core-handles"
+      ;; since each one comes from a different directory.
+      (when alist
+        (cons
+         ;; FIXME: This should be the dir where we found the
+         ;; `.editorconfig' file.
+         (file-name-directory buffer-file-name)
+         alist)))))
+
+;;;###autoload
+(define-minor-mode editorconfig-mode
+  "Toggle EditorConfig feature."
+  :global t
+  (if (boundp 'hack-dir-local-get-variables-functions) ;Emacs≥30
+      (if editorconfig-mode
+          (progn
+            (add-hook 'hack-dir-local-get-variables-functions
+                      ;; Give them slightly lower precedence than settings from
+                      ;; `dir-locals.el'.
+                      #'editorconfig--get-dir-local-variables t)
+            ;; `auto-coding-functions' also exists in Emacs<30 but without
+            ;; access to the file's name via `auto-coding-file-name'.
+            (add-hook 'auto-coding-functions
+                      #'editorconfig--get-coding-system))
+        (remove-hook 'hack-dir-local-get-variables-functions
+                     #'editorconfig--get-dir-local-variables)
+        (remove-hook 'auto-coding-functions
+                     #'editorconfig--get-coding-system))
+    ;; Emacs<30
+    (let ((modehooks '(prog-mode-hook
+                       text-mode-hook
+                       ;; Some modes call `kill-all-local-variables' in their init
+                       ;; code, which clears some values set by editorconfig.
+                       ;; For those modes, editorconfig-apply need to be called
+                       ;; explicitly through their hooks.
+                       rpm-spec-mode-hook)))
+      (if editorconfig-mode
+          (progn
+            (advice-add 'find-file-noselect :around #'editorconfig--advice-find-file-noselect)
+            (advice-add 'find-auto-coding :after-until
+                        #'editorconfig--advice-find-auto-coding)
+            (dolist (hook modehooks)
+              (add-hook hook
+                        #'editorconfig-major-mode-hook
+                        t)))
+        (advice-remove 'find-file-noselect #'editorconfig--advice-find-file-noselect)
+        (advice-remove 'find-auto-coding
+                       #'editorconfig--advice-find-auto-coding)
+        (dolist (hook modehooks)
+          (remove-hook hook #'editorconfig-major-mode-hook))))))
+
+
+;; (defconst editorconfig--version
+;;   (eval-when-compile
+;;     (require 'lisp-mnt)
+;;     (declare-function lm-version "lisp-mnt" nil)
+;;     (lm-version))
+;;   "EditorConfig version.")
+
+;;;###autoload
+(defun editorconfig-version (&optional show-version)
+  "Get EditorConfig version as string.
+
+If called interactively or if SHOW-VERSION is non-nil, show the
+version in the echo area and the messages buffer."
+  (interactive (list t))
+  (let ((version-full
+         (if (fboundp 'package-get-version)
+             (package-get-version)
+           (let* ((version
+                   (with-temp-buffer
+                     (require 'find-func)
+                     (declare-function find-library-name "find-func" (library))
+                     (insert-file-contents (find-library-name "editorconfig"))
+                     (require 'lisp-mnt)
+                     (declare-function lm-version "lisp-mnt" nil)
+                     (lm-version)))
+                  (pkg (and (eval-and-compile (require 'package nil t))
+                            (cadr (assq 'editorconfig
+                                        package-alist))))
+                  (pkg-version (and pkg (package-version-join
+                                         (package-desc-version pkg)))))
+             (if (and pkg-version
+                      (not (string= version pkg-version)))
+                 (concat version "-" pkg-version)
+               version)))))
+    (when show-version
+      (message "EditorConfig Emacs v%s" version-full))
+    version-full))
+
+(provide 'editorconfig)
+;;; editorconfig.el ends here
+
+;; Local Variables:
+;; sentence-end-double-space: t
+;; End:

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 23:08           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-19  5:48             ` Rudolf Schlatte
  2024-06-19  6:01             ` Stefan Kangas
  2024-06-19 15:52             ` Ihor Radchenko
  2 siblings, 0 replies; 34+ messages in thread
From: Rudolf Schlatte @ 2024-06-19  5:48 UTC (permalink / raw)
  To: 70105

Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs@gnu.org> writes:

>> I'm still working on the actual metadata of that branch, as well as
>> etc/NEWS and doc, but in the mean time maybe you could look at the code to
>> see if you have any objections there.
>
> OK, I have a first cut at the doc done.
> So, here's what I'm proposing, presented as a single diff.
> Some commit messages still need to be improved (and I just noticed that
> the files' copyright lines also need to be fixed), but other than that,
> I think it's about ready.
>
> Comments?  Objections?
>
>
>         Stefan
>
> diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
> index 6bf4cbe00df..5287a90bb71 100644
> --- a/doc/emacs/custom.texi
> +++ b/doc/emacs/custom.texi
> @@ -1550,6 +1550,41 @@ Directory Variables
>  do not visit a file directly but perform work within a directory, such
>  as Dired buffers (@pxref{Dired}).
>  
> +@node EditorConfig support
> +@subsubsection Per-Directory Variables via EditorConfig
> +@cindex EditorConfig support
> +
> +The EditorConfig standard is an alternative to the @code{.dir-locals.el}
> +files, which can control only a very small number of variables, but
> +has the advantage of being editor-neutral.  Those settings are stored in
> +files named @code{.editorconfig}.
> +
> +If you want Emacs to obey those settings, you need to enable
> +the @code{editorconfig-mode} minor mode.  This is usually all that is
> +needed: when the mode is activated, Emacs will look for @code{.editorconfig}
> +files whenever a file is visited, just as it does for @code{.dir-locals.el}.
> +
> +When both @code{.editorconfig} and @code{.dir-locals.el} files are
> +encountered, the corresponding settings are combined, and in case there
> +is overlap, the settings coming from the nearest file take precedence.

What happens with both .dir-locals.el and .editorconfig present in the
current directory?  What would be the "nearest file" in that case?  (I'd
expect .dir-locals.el to override .editorconfig in that case, but there
are of course other possibilities.)






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 23:08           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19  5:48             ` Rudolf Schlatte
@ 2024-06-19  6:01             ` Stefan Kangas
  2024-06-19  8:18               ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 15:18               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 15:52             ` Ihor Radchenko
  2 siblings, 2 replies; 34+ messages in thread
From: Stefan Kangas @ 2024-06-19  6:01 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105

Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs@gnu.org> writes:

> OK, I have a first cut at the doc done.
> So, here's what I'm proposing, presented as a single diff.
> Some commit messages still need to be improved (and I just noticed that
> the files' copyright lines also need to be fixed), but other than that,
> I think it's about ready.
>
> Comments?  Objections?

Thanks, LGTM.  I have some comments and questions below.

> diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
> index 6bf4cbe00df..5287a90bb71 100644
> --- a/doc/emacs/custom.texi
> +++ b/doc/emacs/custom.texi
> @@ -1550,6 +1550,41 @@ Directory Variables
>  do not visit a file directly but perform work within a directory, such
>  as Dired buffers (@pxref{Dired}).
>
> +@node EditorConfig support
> +@subsubsection Per-Directory Variables via EditorConfig
> +@cindex EditorConfig support
> +
> +The EditorConfig standard is an alternative to the @code{.dir-locals.el}
> +files, which can control only a very small number of variables, but
> +has the advantage of being editor-neutral.  Those settings are stored in
> +files named @code{.editorconfig}.


> +If you want Emacs to obey those settings, you need to enable
> +the @code{editorconfig-mode} minor mode.  This is usually all that is
> +needed: when the mode is activated, Emacs will look for @code{.editorconfig}
> +files whenever a file is visited, just as it does for @code{.dir-locals.el}.

Is it ever dangerous to load settings from these files or is it always
safe?  Should that be documented somewhere, e.g.:

    In contrast to @code{.dir-locals.el}, it is always considered safe
    to load settings from @code{.editorconfig} files.  (See @xref{...})

> +When both @code{.editorconfig} and @code{.dir-locals.el} files are
> +encountered, the corresponding settings are combined, and in case there
   ^^^^^^^^^^^ a simpler word might suffice: "found"
> +is overlap, the settings coming from the nearest file take precedence.

I don't think I understand this:
- Does "overlap" mean "conflict"?
- What does "nearest" mean; which one is preferred?

> +The @code{indent_size} setting of the EditorConfig standard does not
> +correspond to a fixed variable in Emacs, but instead needs to set
> +different variables depending on the major mode.  Ideally all major
> +modes should set the corresponding @code{editorconfig-indent-size-vars},
> +but if you use a major mode in which @code{indent_size} does not take
> +effect because the major mode does not yet support it, you can customize
> +the @code{editorconfig-indentation-alist} variable to tell Emacs which
> +variables need to be set in that major mode.

Does this suggest that our in-tree major modes should set that variable,
IOW that we should spread the knowledge to those modes?  That should
also help encourage major mode authors elsewhere to do the same.

Should this be documented also in (info "(elisp) Major Mode Conventions")?

> +Similarly, there are several different ways to ``trim whitespace'' at
                                                  ^^               ^^
> +the end of lines.  When the EditorConfig @code{trim_trailing_whitespace}
> +setting is used, by default @code{editorconfig-mode} simply calls
> +@code{delete-trailing-whitespace} every time you save your file.
> +If you prefer some other behavior, You can customize
                                      ^^^ lowercase
> +@code{editorconfig-trim-whitespaces-mode} to the minor mode of
> +your preference, such as @code{ws-butler-mode}.

Why square quotes around "trim whitespace"?  I think they can be
removed.

>  @node Connection Variables
>  @subsection Per-Connection Local Variables
>  @cindex local variables, for all remote connections
> diff --git a/etc/NEWS b/etc/NEWS
> index b2fdbc4a88f..06742d24afe 100644
> --- a/etc/NEWS
> +++ b/etc/NEWS
> @@ -1964,6 +1964,14 @@ The following new XML schemas are now supported:
>  \f
>  * New Modes and Packages in Emacs 30.1
>
> +** New package EditorConfig.
> +This package provides support for the EditorConfig standard that
> +is an editor-neutral way to provide directory local settings.

Suggested:

    This package provides support for the EditorConfig standard, an
    editor-neutral way to provide directory local (project) settings.

> +It is enabled via a new global minor mode 'editorconfig-mode'
> +which makes Emacs obey the '.editorconfig' files.
> +And the package also comes with a new major mode 'editorconfig-conf-mode'
   ^^^
> +to edit those configuration files.

Suggest replacing "And the package also comes with a new major mode"
with "There is also a new major mode".

> new file mode 100644
> index 00000000000..2b4ddd4410f
> --- /dev/null
> +++ b/lisp/editorconfig-conf-mode.el
> @@ -0,0 +1,95 @@
> +;;; editorconfig-conf-mode.el --- Major mode for editing .editorconfig files  -*- lexical-binding: t -*-
> +
> +;; Copyright (C) 2011-2024 EditorConfig Team
> +
> +;; Author: EditorConfig Team <editorconfig@googlegroups.com>
> +
> +;; See
> +;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
> +;; or the CONTRIBUTORS file for the list of contributors.
         ^^^^^^^^^^^^^^^^^^^^^

Suggested:

    "the CONTRIBUTORS file in the linked git repository"

> +(defsubst editorconfig-core-handle--string-trim (str)
> +  "Remove leading and trailing whitespaces from STR."
> +  (replace-regexp-in-string "[[:space:]]+\\'"
> +                            ""
> +                            (replace-regexp-in-string "\\`[[:space:]]+"
> +                                                      ""
> +                                                      str)))

Could this be replaced by string-trim?  Also, is this defsubst unused?

> +(defun editorconfig-core-handle--parse-file (conf)
> +  "Parse EditorConfig file CONF.
> +
> +This function returns a `editorconfig-core-handle'.
> +If CONF is not found return nil."
> +  (when (file-readable-p conf)
> +    (with-temp-buffer
> +      ;; NOTE: Use this instead of insert-file-contents-literally to enable
> +      ;; code conversion
> +      (insert-file-contents conf)
> +      (goto-char (point-min))
> +      (let ((sections ())
> +            (top-props nil)
> +
> +            ;; nil when pattern not appeared yet, "" when pattern is empty ("[]")
> +            (pattern nil)
> +            ;; Alist of properties for current PATTERN
> +            (props ())
> +
> +            ;; Current line num
> +            (current-line-number 1))
> +        (while (not (eobp))
> +          (skip-chars-forward " \t\f")
> +          (cond
> +           ((looking-at "\\(?:[#;].*\\)?$")
> +            nil)
> +
> +           ;; Start of section
> +           ((looking-at "\\[\\(.*\\)\\][ \t]*$")
> +            (let ((newpattern (match-string 1)))
> +              (when pattern
> +                (push (make-editorconfig-core-handle-section
> +                       :name pattern
> +                       :props (nreverse props))
> +                      sections))
> +              (setq props nil)
> +              (setq pattern newpattern)))
> +
> +           ((looking-at "\\([^=: \t]+\\)[ \t]*[=:][ \t]*\\(.*?\\)[ \t]*$")
> +            (let ((key (downcase (match-string 1)))
> +                  (value (match-string 2)))
> +              (when (and (< (length key) 51)
> +                         (< (length value) 256))
> +                (if pattern
> +                    (when (< (length pattern) 4097) ;;FIXME: 4097?
> +                      (push `(,key . ,value)
> +                            props))
> +                  (push `(,key . ,value)
> +                        top-props)))))
> +
> +           (t (error "Error while reading config file: %s:%d:\n    %s\n"
> +                     conf current-line-number
> +                     (buffer-substring-no-properties (line-beginning-position)
> +                                                     (line-end-position)))))
> +          (setq current-line-number (1+ current-line-number))
> +          (goto-char (point-min))
> +          (forward-line (1- current-line-number)))
> +        (when pattern
> +          (push (make-editorconfig-core-handle-section
> +                 :name pattern
> +                 :props (nreverse props))
> +                sections))
> +        (make-editorconfig-core-handle
> +         :top-props (nreverse top-props)
> +         :sections (nreverse sections)
> +         :mtime (nth 5 (file-attributes conf))
> +         :path conf)))))
> +
> +(provide 'editorconfig-core-handle)
> +;;; editorconfig-core-handle.el ends here
> diff --git a/lisp/editorconfig-core.el b/lisp/editorconfig-core.el
> new file mode 100644
> index 00000000000..908d5db6f7e
> --- /dev/null
> +++ b/lisp/editorconfig-core.el
> @@ -0,0 +1,156 @@
> +;;; editorconfig-core.el --- EditorConfig Core library in Emacs Lisp  -*- lexical-binding: t -*-

Suggest scratching "in Emacs Lisp" as redundant

> +(defun editorconfig-version (&optional show-version)
> +  "Get EditorConfig version as string.
> +
> +If called interactively or if SHOW-VERSION is non-nil, show the
> +version in the echo area and the messages buffer."
> +  (interactive (list t))
> +  (let ((version-full
> +         (if (fboundp 'package-get-version)
> +             (package-get-version)
> +           (let* ((version
> +                   (with-temp-buffer
> +                     (require 'find-func)
> +                     (declare-function find-library-name "find-func" (library))
> +                     (insert-file-contents (find-library-name "editorconfig"))
> +                     (require 'lisp-mnt)
> +                     (declare-function lm-version "lisp-mnt" nil)
> +                     (lm-version)))
> +                  (pkg (and (eval-and-compile (require 'package nil t))
> +                            (cadr (assq 'editorconfig
> +                                        package-alist))))
> +                  (pkg-version (and pkg (package-version-join
> +                                         (package-desc-version pkg)))))
> +             (if (and pkg-version
> +                      (not (string= version pkg-version)))
> +                 (concat version "-" pkg-version)
> +               version)))))
> +    (when show-version
> +      (message "EditorConfig Emacs v%s" version-full))
> +    version-full))

Can this function be removed and/or obsoleted?  I would like us to
discourage such functions in favor of using standard functions
(e.g. `M-x list-packages' or `C-h p') to find out what version of a
package is installed.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19  6:01             ` Stefan Kangas
@ 2024-06-19  8:18               ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 15:18                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 15:18               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 34+ messages in thread
From: Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-19  8:18 UTC (permalink / raw)
  To: Stefan Kangas
  Cc: jcs090218, 8slashes+git, 70105, bjorn.bidar, Stefan Monnier,
	Eli Zaretskii

Stefan Kangas <stefankangas@gmail.com> writes:

>     In contrast to @code{.dir-locals.el}, it is always considered safe
>     to load settings from @code{.editorconfig} files.  (See @xref{...})

Minor nit: it should be @file{.editorconfig} and @file{.dir-locals.el},
respectively.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19  6:01             ` Stefan Kangas
  2024-06-19  8:18               ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-19 15:18               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 16:52                 ` Stefan Kangas
  1 sibling, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-19 15:18 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

>> +If you want Emacs to obey those settings, you need to enable
>> +the @code{editorconfig-mode} minor mode.  This is usually all that is
>> +needed: when the mode is activated, Emacs will look for @code{.editorconfig}
>> +files whenever a file is visited, just as it does for @code{.dir-locals.el}.
>
> Is it ever dangerous to load settings from these files or is it always
> safe?  Should that be documented somewhere, e.g.:
>
>     In contrast to @code{.dir-locals.el}, it is always considered safe
>     to load settings from @code{.editorconfig} files.  (See @xref{...})

They're passed through the same checks, i.e. editorconfig.el translates
them to their ELisp equivalent and then we check the result as if it
came from a `dir-locals.el` file.  Usually, the editorconfig.el code
makes sure those tests pass without prompting the user, tho.

>> +When both @code{.editorconfig} and @code{.dir-locals.el} files are
>> +encountered, the corresponding settings are combined, and in case there
>    ^^^^^^^^^^^ a simpler word might suffice: "found"
>> +is overlap, the settings coming from the nearest file take precedence.
>
> I don't think I understand this:
> - Does "overlap" mean "conflict"?

Your question suggests "conflict" is more clear, so I'll use
that, thanks.

> - What does "nearest" mean; which one is preferred?

The settings come from a `.editorconfig` or `.dir-locals.el` file and
apply to some other file.  "nearest" here is the distance between the
file where the settings were found and where they apply.

E.g. a setting from `/foo/bar/baz/.editorconfig` should take priority
over a setting from `/foo/bar/.dir-locals.el` because it's closer to
`/foo/bar/baz/mydir/myfile.agda`.

Not sure you state it more clearly (short of writing out a long
explanation like I've just done, which doesn't seem warranted).

>> +The @code{indent_size} setting of the EditorConfig standard does not
>> +correspond to a fixed variable in Emacs, but instead needs to set
>> +different variables depending on the major mode.  Ideally all major
>> +modes should set the corresponding @code{editorconfig-indent-size-vars},
>> +but if you use a major mode in which @code{indent_size} does not take
>> +effect because the major mode does not yet support it, you can customize
>> +the @code{editorconfig-indentation-alist} variable to tell Emacs which
>> +variables need to be set in that major mode.
> Does this suggest that our in-tree major modes should set that variable,
> IOW that we should spread the knowledge to those modes?

Yup.

> Should this be documented also in (info "(elisp) Major Mode Conventions")?

I have a pending bug-report for a discussion about that.  Basically,
I think `editorconfig-indent-size-vars` is a crutch because the need is
not specific to EditorConfig: we should harmonize the way the "basic
indentation step size" is set in the various major modes.
Users shouldn't need to guess which variable does that for each and
every mode.  Instead we should have one convention for where that
customization is done which applies uniformly to all modes.  But I'm not
completely sure what the convention should be.  E.g. maybe they should
all obey the same `indent-basic-offset` var (which would thus be set
buffer-locally when you want to affect a single mode), or maybe they
should all use a var whose name can be easily computed from the major
mode's name, ...

So, until we decide what the convention should be, I'd refrain from
adding anything about it to that Texinfo node.

>> +Similarly, there are several different ways to ``trim whitespace'' at
>                                                   ^^               ^^
>> +the end of lines.  When the EditorConfig @code{trim_trailing_whitespace}
>> +setting is used, by default @code{editorconfig-mode} simply calls
>> +@code{delete-trailing-whitespace} every time you save your file.
>> +If you prefer some other behavior, You can customize
>                                       ^^^ lowercase
>> +@code{editorconfig-trim-whitespaces-mode} to the minor mode of
>> +your preference, such as @code{ws-butler-mode}.
>
> Why square quotes around "trim whitespace"?  I think they can be
> removed.

Fair enough.

>>  @node Connection Variables
>>  @subsection Per-Connection Local Variables
>>  @cindex local variables, for all remote connections
>> diff --git a/etc/NEWS b/etc/NEWS
>> index b2fdbc4a88f..06742d24afe 100644
>> --- a/etc/NEWS
>> +++ b/etc/NEWS
>> @@ -1964,6 +1964,14 @@ The following new XML schemas are now supported:
>>  \f
>>  * New Modes and Packages in Emacs 30.1
>>
>> +** New package EditorConfig.
>> +This package provides support for the EditorConfig standard that
>> +is an editor-neutral way to provide directory local settings.
>
> Suggested:
>
>     This package provides support for the EditorConfig standard, an
>     editor-neutral way to provide directory local (project) settings.

Thanks.

>> +It is enabled via a new global minor mode 'editorconfig-mode'
>> +which makes Emacs obey the '.editorconfig' files.
>> +And the package also comes with a new major mode 'editorconfig-conf-mode'
>    ^^^
>> +to edit those configuration files.
>
> Suggest replacing "And the package also comes with a new major mode"
> with "There is also a new major mode".

OK.

>> new file mode 100644
>> index 00000000000..2b4ddd4410f
>> --- /dev/null
>> +++ b/lisp/editorconfig-conf-mode.el
>> @@ -0,0 +1,95 @@
>> +;;; editorconfig-conf-mode.el --- Major mode for editing .editorconfig
>> files  -*- lexical-binding: t -*-
>> +
>> +;; Copyright (C) 2011-2024 EditorConfig Team
>> +
>> +;; Author: EditorConfig Team <editorconfig@googlegroups.com>
>> +
>> +;; See
>> +;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors
>> +;; or the CONTRIBUTORS file for the list of contributors.
>          ^^^^^^^^^^^^^^^^^^^^^
>
> Suggested:
>
>     "the CONTRIBUTORS file in the linked git repository"

Hmm... good catch.

>> +(defsubst editorconfig-core-handle--string-trim (str)
>> +  "Remove leading and trailing whitespaces from STR."
>> +  (replace-regexp-in-string "[[:space:]]+\\'"
>> +                            ""
>> +                            (replace-regexp-in-string "\\`[[:space:]]+"
>> +                                                      ""
>> +                                                      str)))
>
> Could this be replaced by string-trim?

I never know *exactly* what is trimmed, and when I do it's usually not
*quite* the same so I usually assume that the answer is "probably, but
it would take more time to figure out than it's worth".

> Also, is this defsubst unused?

Oh, indeed, I removed all references to it, so it can be deleted, yay!

>> +(defun editorconfig-version (&optional show-version)
>> +  "Get EditorConfig version as string.
>> +
>> +If called interactively or if SHOW-VERSION is non-nil, show the
>> +version in the echo area and the messages buffer."
>> +  (interactive (list t))
>> +  (let ((version-full
>> +         (if (fboundp 'package-get-version)
>> +             (package-get-version)
>> +           (let* ((version
>> +                   (with-temp-buffer
>> +                     (require 'find-func)
>> +                     (declare-function find-library-name "find-func" (library))
>> +                     (insert-file-contents (find-library-name "editorconfig"))
>> +                     (require 'lisp-mnt)
>> +                     (declare-function lm-version "lisp-mnt" nil)
>> +                     (lm-version)))
>> +                  (pkg (and (eval-and-compile (require 'package nil t))
>> +                            (cadr (assq 'editorconfig
>> +                                        package-alist))))
>> +                  (pkg-version (and pkg (package-version-join
>> +                                         (package-desc-version pkg)))))
>> +             (if (and pkg-version
>> +                      (not (string= version pkg-version)))
>> +                 (concat version "-" pkg-version)
>> +               version)))))
>> +    (when show-version
>> +      (message "EditorConfig Emacs v%s" version-full))
>> +    version-full))
>
> Can this function be removed and/or obsoleted?  I would like us to
> discourage such functions in favor of using standard functions
> (e.g. `M-x list-packages' or `C-h p') to find out what version of a
> package is installed.

OK, I'll remove it (I fully agree with your goal).  But the upstream
maintainers may like it enough that when I later harmonize the code
between Emacs and upstream that function ends up coming back :-(


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19  8:18               ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-19 15:18                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-19 15:18 UTC (permalink / raw)
  To: Michael Albinus
  Cc: jcs090218, 8slashes+git, 70105, bjorn.bidar, Stefan Kangas,
	Eli Zaretskii

>>     In contrast to @code{.dir-locals.el}, it is always considered safe
>>     to load settings from @code{.editorconfig} files.  (See @xref{...})
>
> Minor nit: it should be @file{.editorconfig} and @file{.dir-locals.el},
> respectively.

Thanks!


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-18 23:08           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19  5:48             ` Rudolf Schlatte
  2024-06-19  6:01             ` Stefan Kangas
@ 2024-06-19 15:52             ` Ihor Radchenko
  2024-06-19 15:57               ` Eli Zaretskii
  2024-06-20 16:33               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2 siblings, 2 replies; 34+ messages in thread
From: Ihor Radchenko @ 2024-06-19 15:52 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs@gnu.org> writes:

> +The @code{indent_size} setting of the EditorConfig standard does not
> +correspond to a fixed variable in Emacs, but instead needs to set
> +different variables depending on the major mode.  Ideally all major
> +modes should set the corresponding @code{editorconfig-indent-size-vars},
> +but if you use a major mode in which @code{indent_size} does not take
> +effect because the major mode does not yet support it, you can customize
> +the @code{editorconfig-indentation-alist} variable to tell Emacs which
> +variables need to be set in that major mode.

Reading this as a major mode maintainer, I have not the slightest clue
about EditorConfig standard. So, I have no idea what indent_size is all
about and what I am supposed to do with it.

Maybe you can explain in more details what indent_size does and how it
should reflect on the indentation settings.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 15:52             ` Ihor Radchenko
@ 2024-06-19 15:57               ` Eli Zaretskii
  2024-06-20 16:33               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 0 replies; 34+ messages in thread
From: Eli Zaretskii @ 2024-06-19 15:57 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: jcs090218, bjorn.bidar, 8slashes+git, 70105, monnier

> From: Ihor Radchenko <yantar92@posteo.net>
> Cc: Eli Zaretskii <eliz@gnu.org>, jcs090218@gmail.com,
>  bjorn.bidar@thaodan.de, 8slashes+git@gmail.com, 70105@debbugs.gnu.org
> Date: Wed, 19 Jun 2024 15:52:29 +0000
> 
> Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
> text editors" <bug-gnu-emacs@gnu.org> writes:
> 
> > +The @code{indent_size} setting of the EditorConfig standard does not
> > +correspond to a fixed variable in Emacs, but instead needs to set
> > +different variables depending on the major mode.  Ideally all major
> > +modes should set the corresponding @code{editorconfig-indent-size-vars},
> > +but if you use a major mode in which @code{indent_size} does not take
> > +effect because the major mode does not yet support it, you can customize
> > +the @code{editorconfig-indentation-alist} variable to tell Emacs which
> > +variables need to be set in that major mode.
> 
> Reading this as a major mode maintainer, I have not the slightest clue
> about EditorConfig standard. So, I have no idea what indent_size is all
> about and what I am supposed to do with it.

This is from the Emacs user manual, not from the ELisp reference
manual.  So the intended audience is users, and in particular those
who have .editorconfig files and thus already know about indent_size.

Guidance and recommendations for mode developers are of course also
needed, but they will go into the other manual, and (AFIU) we don't
yet fully know what to write there, because this is still a moving
target.  When we figure that out, it would be good to document the
conventions and recommended practices.  But we are not there yet.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 15:18               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-19 16:52                 ` Stefan Kangas
  2024-06-19 17:26                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Kangas @ 2024-06-19 16:52 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> The settings come from a `.editorconfig` or `.dir-locals.el` file and
> apply to some other file.  "nearest" here is the distance between the
> file where the settings were found and where they apply.
>
> E.g. a setting from `/foo/bar/baz/.editorconfig` should take priority
> over a setting from `/foo/bar/.dir-locals.el` because it's closer to
> `/foo/bar/baz/mydir/myfile.agda`.
>
> Not sure you state it more clearly (short of writing out a long
> explanation like I've just done, which doesn't seem warranted).

Which one takes precedence if they are equally near?

In other words, when you have:

    /foo/bar/.dir-locals.el
    /foo/bar/.editorconfig





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 16:52                 ` Stefan Kangas
@ 2024-06-19 17:26                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 19:31                     ` Stefan Kangas
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-19 17:26 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

> In other words, when you have:
>
>     /foo/bar/.dir-locals.el
>     /foo/bar/.editorconfig

`.dir-locals.el` should take precedence in that case.


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 17:26                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-19 19:31                     ` Stefan Kangas
  2024-06-19 19:56                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Kangas @ 2024-06-19 19:31 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> In other words, when you have:
>>
>>     /foo/bar/.dir-locals.el
>>     /foo/bar/.editorconfig
>
> `.dir-locals.el` should take precedence in that case.

How does this read?

    When both @file{.editorconfig} and @code{.dir-locals.el} files are found
    and they both set the same settings, the nearest file take precedence.
    If they are equally close, @file{.dir-locals.el} takes precedence.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 19:31                     ` Stefan Kangas
@ 2024-06-19 19:56                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-06-19 20:51                         ` Stefan Kangas
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-19 19:56 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

>>> In other words, when you have:
>>>
>>>     /foo/bar/.dir-locals.el
>>>     /foo/bar/.editorconfig
>>
>> `.dir-locals.el` should take precedence in that case.
>
> How does this read?
>
>     When both @file{.editorconfig} and @code{.dir-locals.el} files are found
>     and they both set the same settings, the nearest file takes precedence.
>     If they are equally close, @file{.dir-locals.el} takes precedence.

Doesn't this risk suggesting that the settings from only one of the two
files will be used?

Here's my current text:

    When both @file{.editorconfig} and @file{.dir-locals.el} files are
    found, their settings are combined, and in case of a conflict, the
    setting coming from the closest file takes precedence.
    If they are equally close, @file{.dir-locals.el} takes precedence.


- Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 19:56                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-06-19 20:51                         ` Stefan Kangas
  2024-06-21 14:19                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 34+ messages in thread
From: Stefan Kangas @ 2024-06-19 20:51 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Here's my current text:
>
>     When both @file{.editorconfig} and @file{.dir-locals.el} files are
>     found, their settings are combined, and in case of a conflict, the
>     setting coming from the closest file takes precedence.
>     If they are equally close, @file{.dir-locals.el} takes precedence.

Looks good to me, thanks.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 15:52             ` Ihor Radchenko
  2024-06-19 15:57               ` Eli Zaretskii
@ 2024-06-20 16:33               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-20 16:33 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105

> Reading this as a major mode maintainer, I have not the slightest clue
> about EditorConfig standard. So, I have no idea what indent_size is all
> about and what I am supposed to do with it.

I think in Org it's called `org-indent-indentation-per-level`.

[ BTW, currently `editorconfig.el` comes with a list of 100 modes
  (including several I'd never heard of) with their corresponding "indent
  size variable(s)" but Org is not among those modes.  ]



        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#70105: 30.0.50; Emacs should support EditorConfig out of the box
  2024-06-19 20:51                         ` Stefan Kangas
@ 2024-06-21 14:19                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 34+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-06-21 14:19 UTC (permalink / raw)
  To: Stefan Kangas
  Cc: jcs090218, bjorn.bidar, Eli Zaretskii, 8slashes+git, 70105-done

Pushed to `master`, closing,


        Stefan






^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2024-06-21 14:19 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-31 13:44 bug#70105: 30.0.50; Emacs should support EditorConfig out of the box Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-31 14:25 ` Eli Zaretskii
2024-03-31 20:40   ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-31 22:26   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-06 23:51   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-08 12:50     ` Eli Zaretskii
2024-06-09  4:21       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18  6:01         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18  6:21           ` Ihor Radchenko
2024-06-18 13:17             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18 16:21               ` Ihor Radchenko
2024-06-18 19:37                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18 19:55                   ` Ihor Radchenko
2024-06-18 20:07                     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18  9:10           ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
     [not found]           ` <87v826hb13.fsf@>
2024-06-18 12:56             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18 19:26           ` Stefan Kangas
2024-06-18 19:47             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-18 23:08           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19  5:48             ` Rudolf Schlatte
2024-06-19  6:01             ` Stefan Kangas
2024-06-19  8:18               ` Michael Albinus via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19 15:18                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19 15:18               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19 16:52                 ` Stefan Kangas
2024-06-19 17:26                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19 19:31                     ` Stefan Kangas
2024-06-19 19:56                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19 20:51                         ` Stefan Kangas
2024-06-21 14:19                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-19 15:52             ` Ihor Radchenko
2024-06-19 15:57               ` Eli Zaretskii
2024-06-20 16:33               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-09 11:49     ` Stefan Kangas

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.