Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Fill gaps in dwim behavior #2995
One of Magit's most important meta-features, is that one usually has to press just one or two key to (1) show another representation/details of the thing at point in another buffer, or (2) perform some action on that thing at point.
In Magit buffers the "thing at point" is usually called the "current section", and it represents some entity or concept that is meaningful to Git. Examples of such entities include commits and files and examples of concepts include the lists (logs) of unpushed and unpulled commits.
Dwim behavior exists both for sections that represent entities as well as for those that represent concepts. For example
Knowing exactly what some section represents is another, closely related, meta-feature of Magit. This sounds rather obvious, but keep in mind that with Git, for example, a diff (and everything else) is basically just text. It is you who has to remember what command you typed to generate it, and what actions you can therefor perform on it (in Git e.g. by piping it into some other command). Magit on the other hand remembers this for you and if you invoke some command that actually performs different but closely related actions based on context, then that command automatically performs the appropriate variation.
In a sense every command (in every program) is a dwim command - if it doesn't do what you mean, than it is a command that either has a bug or that is insufficiently documented (or if you don't read documentation, a command that does not conform to your intuition).
In Magit I find it difficult to draw the line between dwim commands and other commands that just happen to do something useful and to have a mnemonic key binding. So maybe it is more useful when explaining what makes Magit different from other user interfaces, to not focus on it having many dwim commands, but to instead say that you can (1) act on everything that you can see, that you can (2) directly do (almost) everything you might wish to do, and (3) that you can do so using highly consistent and mnemonic key bindings.
To cut a long story short, there are gaps in the dwim behavior. I should have kept a list, but unfortunately I haven't. On the other hand I have in the past filled most gaps that were reported by users rather quickly, so there might not be that many after all.
To find the remaining gaps I should probably start by creating a list of all the "paths" that do make sense and then check which of those haven't actually been implemented yet.
Thinking of it, such a list would be very useful as documentation, not just to find gaps. And while a list is a good start, I should go further and create a visual guide, consisting of screenshots of the various Magit and related buffers and arrows connecting them (with associated key bindings etc). I could create a poster from that, and maybe sell it.
But for now, there's what I can find at this moment:
(Some of these might stretch the definition of "dwim behavior" a bit.)
The code that calculates position offsets by taking relevant diffs into account has to be refactored. It is unreadable and therefore hard to adjust for other use cases.
Turns out it wasn't that bad.
Thanks to #3860 to most glaring holes have been stuffed. And I am now going back to doing the same for new holes as they are being reported. Some linked diff-related topics listed above have not been taken care of yet, but I am closing this anyway because not closely enough related to what I had in mind when I originally opened this. The posters are not ready yet either.
thank you for all these improvements.
I couldn't find the implementation of #2968 in your
(defun magit-status-here () "Jump to hunk corresponding to current line in magit." (interactive) (let ((filename (file-truename (buffer-file-name))) (line (line-number-at-pos)) (col (current-column))) (call-interactively #'magit-status) (when filename ; Guard against non-file-visiting buffers. (let* ((filename (magit-file-relative-name filename)) (unstaged-section (magit-get-section '((unstaged) (status)))) (file-section (cl-find-if (lambda (subsection) (and (eq (oref subsection type) 'file) (equal (oref subsection value) filename))) (oref unstaged-section children)))) (when file-section (magit-section-show file-section) (let ((magit-root-section unstaged-section)) (magit-diff--goto-position filename line col)) (recenter))))))
The gross hack is binding