Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Derive from prog-mode #93

Closed
lunaryorn opened this Issue · 10 comments

3 participants

@lunaryorn

Beginning with Emacs 24, modes for programming languages are supposed to derived from prog-mode.

@jart
Collaborator

Does prog-mode exist in emacs 23?

@lunaryorn

@jart No, but where is the problem? You can easily choose the base mode dynamically based on the result of use (fboundp #'prog-mode). Haskell Mode does that to provide compatibility with Emacs 23.

And then, who in his right mind is still using Emacs 23 anyway?

@jart jart closed this in 659a9f8
@lunaryorn lunaryorn referenced this issue from a commit in lunaryorn/.emacs.d
@lunaryorn lunaryorn Do not run prog-mode hook manually in `coffee-mode`
Coffee Mode now properly derives from `prog-mode`, see
defunkt/coffee-mode#93.
705e0f9
@dgutov

Small problem: derived-mode-p doesn't handle aliases. When in a coffee-mode buffer:

(derived-mode-p 'prog-mode) => nil
(derived-mode-p 'coffee-parent-mode) => t

Here's what other modes do:

prolog.el:

(unless (fboundp 'prog-mode)
  (defalias 'prog-mode 'fundamental-mode))

verilog-mode.el:

(unless (fboundp 'prog-mode)
  (define-derived-mode prog-mode fundamental-mode "Prog"))
@lunaryorn

@dgutov See this comment for why Haskell mode deliberately chose not to alias prog-mode.

Basically, what other modes do, makes false promises, namely that prog-mode is fully available and integrated while it is not.

Also, isn't this rather an upstream issue in derived-mode-p? Shouldn't this function not only test the derived-mode-parent property itself, but also its symbol-function to take aliases into account?

@lunaryorn

What about the following workaround:

(if (fboundp 'prog-mode)
    (define-derived-mode coffee-parent-mode prog-mode "Coffee Parent")
  (define-derived-mode coffee-parent-mode fundamental-mode "Coffee Parent"))

(define-derived-mode coffee-mode coffee-parent-mode "Coffee" "Coffee"
  ;; …
  )

This definition avoids a global alias on prog-mode, but (derived-mode-p 'prog-mode) would still return t with this definition, because derived-mode-p checks all parents of the current mode recursively.

@dgutov

Haskell guys make a theoretical argument about some hypothetical code that could make a wrong assumption, whereas checking inheritance from prog-mode is a real pattern used in practice (not in Emacs codebase, but in third-party code).

Also, isn't this rather an upstream issue in derived-mode-p

Maybe, maybe not. Even if it's fixed now, the problem will remain in 24.[1-3].
Considering that any buffer in coffee-parent-mode would still have the value of major-mode as prog-mode, (derived-mode-p 'coffee-parent-mode) should return nil, so maybe we should conclude instead that major modes aren't made to be aliased.

Here's an XEmacs topic discussing which option to take (they ended up defining prog-mode in their codebase instead).

And here's Stefan suggesting to just use defalias.

What about the following workaround:

Too heavy-weight for my taste: define-derived-mode expands into a lot of code. Defining an alias for fundamental-mode and setting derived-mode-parent property on it should work just as well, though.

@lunaryorn

@dgutov I doubt that this is merely theoretical. Anyway, neither of us knows, whether it is just theoretical, in fact, we cannot know.

But what we know is that aliasing to prog-mode breaks some of the implicit assumptions about prog-mode, namely that prog-mode-hook will run in derived modes. Consider the following code:

(add-hook 'prog-mode-hook 'my-cool-minor-mode)

(unless (derived-mode-p 'prog-mode)
    (run-hooks 'prog-mode-hook))

With (defalias 'prog-mode 'fundamental-mode) this code is broken, because prog-mode-hook is never run and my-cool-minor-mode is never enabled.

While I agree, that an additional mode is rather heavy-weight, I doubt that this has any practical implication. Don't make theoretical arguments yourself, if you've criticized others for doing so.

Edit: Aliasing prog-mode also goes against the Coding conventions documented in the Emacs Lisp manual, as noted in a reply to Stefan's suggestion.

@dgutov

neither of us knows, whether it is just theoretical, in fact, we cannot know

It's theoretical because it tries to anticipate the problem in practice. I'm not aware of it being an actual problem. And as long as any other packages alias prog-mode to fundamental-mode, you can never be certain that (fboundp 'prog-mode) implies working prog-mode-hook anyway.

Don't make theoretical arguments yourself, if you've criticized others for doing so.

I believe I used the word "taste". :) Your suggestion would work better than what we have now, obviously,

because prog-mode-hook is never run and my-cool-minor-mode is never enabled

Well, do what verilog-mode.el does, then. It also takes just one line.

Btw, aliasing prog-mode also goes against the Coding conventions documented in the Emacs Lisp manual

Sure, I've read that. AFAICT, this reply hasn't resulted in any changes in Emacs codebase.

@lunaryorn

@dgutov I would uphold the assumption that (fboundp 'prog-mode) implies a working prog-mode-hook, and I consider any package broken that violates this assumption. Essentially, I consider prolog-mode buggy in this regard.

Also, I do not think that questionable code in other packages can serve as a justification and reason to use the same code in your own packages. By the same argument, I do not consider the Emacs codebase as gold standard for Emacs Lisp style and coding. I read my share of it, and found more than one piece of arguably dubious code and design. The Emacs codebase not complying to a specific convention does definitely not invalidate that convention in my eyes.

But be that as it may, I agree that the code from Verilog Mode is acceptable, and can be used as a proper workaround.

@dgutov

The Emacs codebase not complying to a specific convention does definitely not invalidate that convention in my eyes.

While Emacs codebase is not perfect (obviously: it's huge), I think that the fact that nobody has fixed it, or even filed a bug, speaks to the value of that convention.

But anyway, I don't ever use Emacs 23, so my opinion on how the packages should work with it is mostly irrelevant. My concern here is only about coffee-mode in Emacs 24, where it breaks derived-mode-p, hence the suggestion to have as small a fix as possible.

I agree that the code from Verilog Mode is acceptable, and can be used as a proper workaround.

I'm glad that we can agree on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.