Skip to content

Conversation

@snan
Copy link

@snan snan commented Oct 13, 2022

It's often been the case that I'll hit the god-mode key and it does nothing, because god-global-mode and god-local-mode is out of sync.

Either I wanna turn on god-mode, because it's off locally, but it's on globally (and there's no indication to show that), so the key (seemingly) does nothing. It only affects background buffers (and sometimes in ways I don't even want).

Or, I wanna turn off god-mode, but unbeknownst to me it's already off globally, it's just off locally. So again the key does nothing in the active buffer, only weirds up the background buffers.

With this patch, if god-global-mode and god-local-mode has gotten out of sync, this key syncs them up by changing the local-buffer which is always what I want. If they are already in sync, it toggles them (i.e. the old behavior, which is exactly what you want when they are in sync).

=================================================================
Use a dedicated feature branch

Please use a dedicated feature branch for your feature request, instead of asking us to merge "your-fork/master" into the "origin/master". The use of dedicated branches makes it much more convenient to deal with pull-requests, especially when using Magit to do so.

If you were about to open a pull-request asking us to merge your version of "master", then see 1 for instructions on how to quickly fix that and some information on why we ask you to do so.

Additionally we ask you to allow us to push to the branch you want us to merge. We might want to push additional commits and/or make minor changes. Please make sure the box next to "Allow edits from maintainers" is checked before creating the pull-request.

=================================================================
Do NOT use Github to edit files and create commit messages

Unless you are aware of all the pitfalls and take great care to avoid them, the use of Github results in many small defects, including but not limited to trailing whitespace, commit messages containing overlong lines and no newline at the very end, and "GitHub [email protected]" being used as the committer. The last one cannot even be avoided, which I consider as an affront.

Github is an insufficient interface for editing files and creating commits. Please don't do it when contributing to this project.

=================================================================
What you should write here

Please summarize the changes made in the commits. Explain why you are making these changes, not just what changes you are making. This also applies to the commit messages.

=================================================================
How to update the manual

If this project has a manual and you make changes to that, then edit only "PROJECT.org". Do not manually edit "PROJECT.texi". The latter has to be generated from the former. If you want to do that yourself, then follow the instructions at 2. Otherwise a maintainer will do it and amend that to your commit.

It's often been the case that I'll hit the `god-mode` key and it does nothing, because `god-global-mode` and `god-local-mode` is out of sync.

Either I wanna turn on god-mode, because it's off locally, but it's on globally (and there's no indication to show that), so the key (seemingly) does nothing. It only affects background buffers (and sometimes in ways I don't even want).

Or, I wanna turn off god-mode, but unbeknownst to me it's already off globally, it's just off locally. So again the key does nothing in the active buffer, only weirds up the background buffers.

With this patch, if `god-global-mode` and `god-local-mode` has gotten out of sync, this key syncs them up by changing the local-buffer which is always what I want. If they are already in sync, it toggles them (i.e. the old behavior, which is exactly what you want when they are in sync).
@snan
Copy link
Author

snan commented Oct 13, 2022

OK, I'll redo this pull request normally in a separate branch.

@snan snan closed this Oct 13, 2022
@darth10
Copy link
Collaborator

darth10 commented Oct 13, 2022

What's god-global-mode?

If you're worried about god-mode (global) and god-local-mode getting out of sync, just use god-mode instead of god-local-mode.
Allowing them to go out of sync is intended behaviour as the user will likely be editing multiple buffers, and syncing them is a bit of a breaking change.

@darth10
Copy link
Collaborator

darth10 commented Oct 13, 2022

there's no indication to show that

Have you looked at Visual indicators for God mode in the README?
Cursor shape and/or color are great indicators of whether god-mode is enabled in the current buffer.

@snan snan deleted the patch-1 branch October 13, 2022 09:33
@snan
Copy link
Author

snan commented Oct 13, 2022

What's god-global-mode?

It's a variable that god-mode uses internally in order to determine what to toggle.

If you're worried about god-mode (global) and god-local-mode getting out of sync,

That's not the issue. I'll try to explain again down below.

Allowing them to go out of sync is intended behaviour

Yes, I agree with that.

as the user will likely be editing multiple buffers, and syncing them is a bit of a breaking change.

That's not what this patch does. The patch is not about always keeping global in sync with local. If that was the take-away, I was being unclear in my initial explanation about what the problem is.

Cursor shape and/or color are great indicators of whether god-mode is enabled in the current buffer.

Yes, cursor shape, color, and mode-line indicator are all great to see whether god-mode is enabled in the current buffer. It doesn't show what's going on globally.

So without the patch (I'll refer to running god-mode as a function as "the key" below, whether it's <ESC> or whatever):

  • If god-mode-local is off and god-mode-global is off, the key turns both on. Good.
  • If god-mode-local is on and god-mode-global is on, the key turns both off. Good.
  • If god-mode-local is on but god-mode-global is off, the key does nothing locally. It only affects background buffers. Confusing and makes me wonder if I even hit the key correctly. Not good.
  • If god-mode-local is off but god-mode-global is on, same confusing thing happens. Not good.

It's been something that has been going on for years and I've been like "oh, god-mode just sometimes doesn't work, or maybe it's that I'm inputting the key command incorrectly" and now when I read the source code I realized why the key had been so unreliable all this time and often needed to be hit twice. (Which, while typing quickly, even though there are visual indicators, is not good; we don't pause to look after every key press.)

With the patch:

  • If god-mode-local is off and god-mode-global is off, the key turns both on. Good.
  • If god-mode-local is on and god-mode-global is on, the key turns both off. Good.
  • If god-mode-local is on but god-mode-global is off, the key turns god-mode-local off too. Good.
  • If god-mode-local is off but god-mode-global is on, the key turns god-mode-local on too. Good.

When we run the god-mode function when the global state is counter to the local state, it's because we don't realize that the global state is counter to the local state, because what we're the most concerned with is the local state.

Put differently, the intended semantics when hitting the key when god-mode is off locally is that we want to turn it on both globally and locally, and when hitting the key when god-mode is on locally is that we want to turn it off both globally and locally. That's what this patch does.

The current semantics, without this patch, which I believe are not good, is that the key ignores the local state (even though the local state is the only state the user is aware of [through cursors, colors, modeline indicators, maybe even other theme changes]), toggles the global state (even though the user has no indication of the global state), and only then sets the local state to match the global state (even if they were already matching so hitting the key did nothing locally).

@darth10
Copy link
Collaborator

darth10 commented Oct 13, 2022

Thanks for the detailed explanation, @snan!
Sorry, I was being silly and didn't realise you were referring the variable god-global-mode.
For some reason, I always think of *-mode symbols as functions 😄

I get the use case now, but I want to understand more.

  • If god-mode-local is off and god-mode-global is off, the key turns both on. Good.
  • If god-mode-local is on and god-mode-global is on, the key turns both off. Good.
  • If god-mode-local is on but god-mode-global is off, the key does nothing locally. It only affects background buffers. Confusing and makes me wonder if I even hit the key correctly. Not good.
  • If god-mode-local is off but god-mode-global is on, same confusing thing happens. Not good.

If I try these steps with god-local-mode and god-mode-all, I can't reproduce the issue.
However, I can recreate the issue by calling the god-mode function interactively.

I'll refer to running god-mode as a function as "the key" below

Let's assume you have bound god-local-mode and god-mode-all to keys.
Do you have a key binding for the god-mode function too?
That's interesting, because I thought most people would have key bindings for just god-local-mode and god-mode-all.

@snan
Copy link
Author

snan commented Oct 13, 2022

Interesting! Yeah, I have one god-mode and then I have specific circumstances that can temporarily toggle god-mode-local (such as when opening parenthesis).

I thought most people had god-mode set to <ESC>.

I've actually never used god-mode-all 💁🏻‍♀️

@darth10
Copy link
Collaborator

darth10 commented Oct 14, 2022

Would it be possible for you to try using god-local-mode and god-mode-all i.e. bind god-mode-all to ESC, and try to recreate the issue?

Your change makes sense, but this is starting to sound more like a documentation (docstring and README) inconsistency to me.

@snan
Copy link
Author

snan commented Oct 14, 2022

The problem with god-mode-all is that it toggles and changes all the background buffers too (mapc over buffer-list). Messing with people's carefully made god-mode-local settings.

It's not only a documentation issue; god-mode often seemingly does nothing making it kind of useless.

One alternative is to name the god-mode I submitted something new and then keep the old god-mode but… that makes the old god-mode useless and confusing for new people who might, like me, go for years just not really trusting the key and thinking that "sometimes it just doesn't work".

@darth10
Copy link
Collaborator

darth10 commented Oct 14, 2022

Your change doesn't fix this case:

If god-mode-local is on but god-mode-global is off, the key does nothing locally.

I did the following steps with your change:

  1. Set god-global-mode to nil but calling god-mode-all.
  2. Enable god-local-mode minor mode in a buffer (god-local-mode is set to t).
  3. Call god-mode. It does nothing, which is incorrect.

I might have set some other state while I was testing calls to god-mode, god-local-mode and god-mode-all.

I'll try to dig deeper soon, but the intended behaviour of the setq form in the god-mode function is not clear to me.
Setting god-global-mode based on the state of god-local-mode in the current buffer seems wrong.
The converse is also incorrect i.e. setting god-local-mode based on god-global-mode.

The right thing to do here would be to remove the setq call entirely so that god-global-mode is not modified by god-mode, similar to how god-local-mode works.
The god-mode function has been around since the first commit to this repo (a5d1bb6), so I'm just a bit cautious to change it.

@snan
Copy link
Author

snan commented Oct 14, 2022

The idea that I want is:

If I am in a buffer with god-mode locally off, make sure god-local-mode and god-global-mode is on, and
if I am in a buffer with god-mode locally on, make sure god-local-mode and god-global-mode is off,

without mapc' ing every buffer because I already have god-mode-all for that, and I also have god-local-mode for when I only want to change the local god-mode.

I did the following steps with your change:

  1. Set god-global-mode to nil but calling god-mode-all.
  2. Enable god-local-mode minor mode in a buffer (god-local-mode is set to t).
  3. Call god-mode. It does nothing, which is incorrect.

If that's really with my version of god-mode (could you double check that? because that sounds like the old behavior), then I've made a bug.

The code I wrote compares god-global-mode and god-local-mode.
If they are unequal, which they should be in your example, it runs (god-local-mode) as a function.
If they are equal, which they should not be in your example, it runs the old version of (god-mode), which is where the setq originated.

@snan
Copy link
Author

snan commented Oct 14, 2022

Ah you'e right! Investigating it now

@snan
Copy link
Author

snan commented Oct 14, 2022

Found it! Last line needs to be (god-local-mode 'toggle) not (god-local-mode). I pushed that change to the repo I emailed.

@darth10
Copy link
Collaborator

darth10 commented Oct 14, 2022

(god-local-mode 'toggle) is interpreted as (god-local-mode 1) i.e. 'toggle isn't a special symbol AFAIK.
Even it was, I'd stick to using positive/negative arguments to explicitly enable/disable a minor mode.

I'll clean that up and test it out soon, but I think the function should end up looking something like this:

(defun god-mode ()
  (interactive)
  (god-local-mode (if (bound-and-true-p god-local-mode) -1 1)))

@snan
Copy link
Author

snan commented Oct 14, 2022

(god-local-mode 'toggle) is interpreted as (god-local-mode 1) i.e. 'toggle isn't a special symbol AFAIK.

That's not correct, (god-local-mode 1) means turn on, toggle symbol is special, means toggle.

@darth10
Copy link
Collaborator

darth10 commented Oct 14, 2022

Sigh, yes I forgot about toggle.
Sorry about that @snan!

I'll try that out again using (god-local-mode 'toggle) and push a commit soon.
I still want to try and remove the dependency on god-global-mode, but if there's no other way I'll use what you've described.

@darth10
Copy link
Collaborator

darth10 commented Oct 17, 2022

@snan Just an update...

I've committed the changes you sent via email on the fix/god-mode-function branch.
There's a failing test which is closely related to the scope of this this change, so it needs a bit more work.
I'll take a closer look soon.

@darth10
Copy link
Collaborator

darth10 commented Oct 17, 2022

After a brief look (and sorry if I'm going back in circles here), I really think this is a configuration/documentation issue.
You should be calling:

  • The god-mode function once after loading the god-mode package to allow the god-local-mode minor mode to be enabled in new and existing buffers,
  • god-mode-all to toggle God mode in all buffers, and
  • god-local-mode to toggle God mode in the current buffer.

If you configure Emacs with the above guidelines, god-global-mode and god-local-mode will not be "out of sync".

The god-mode function is not designed to toggle God mode the the current buffer, while respecting the god-global-mode variable.
It's meant to be called once after loading the god-mode package.

I'll update the README with this information.

@snan
Copy link
Author

snan commented Oct 17, 2022

In that case, I'll have to make a fourth function with a new name to do what my version of (god-mode) does.

Because god-mode-all isn't what I want, I don't wanna mapc over every single other buffer in case they're already set up perfectly.

Let's say I have god mode on in most buffers but I turned it off on one (probably in an rcirc bot query since god-mode can sometimes be good, sometimes bad in those) and then I'm in a text file and god-mode-local gets turned off. I don't wanna call god-mode-all in that situation since it'd also turn god-mode on in those backgrounded buffers where I have previously turned it off.

@darth10
Copy link
Collaborator

darth10 commented Oct 17, 2022

In that case, I'll have to make a fourth function with a new name to do what my version of (god-mode) does.

That's a good approach if that works for you.
You can also look at the god-mode-activate and god-mode-maybe-activate functions.
I'm more than happy to accept that new function as a contribution, as other users might find it useful.

Let's say I have god mode on in most buffers but I turned it off on one (probably in an rcirc bot query since god-mode can sometimes be good, sometimes bad in those) and then I'm in a text file and god-mode-local gets turned off. I don't wanna call god-mode-all in that situation since it'd also turn god-mode on in those backgrounded buffers where I have previously turned it off.

This is the use case that I don't entirely understand.
If you've turned off God mode using god-local-mode, god-global-mode will not be affected, which is why you should only be using god-local-mode to toggle God mode in the current buffer.

The condition "God mode is on in most buffers" is not 100% clear, as it doesn't describe the state of god-global-mode.
If you call god-mode once on package load and never use god-mode-all, god-global-mode will be set to t, which means God mode will always be enabled in new buffers.
Using god-local-mode in the current buffer doesn't affect that, which is what the original author intended.

@snan
Copy link
Author

snan commented Oct 17, 2022

I'll try to explain it in two ways.

\1. The use-case:
Buffers are in one of three states: explicitly set to god-mode on, explicitly off, or not set (for example, buffers that don't exist yet, newly created). I wanna toggle local and I wanna toggle "default", i.e. buffers yet to be created. I don't want what god-mode-all does, go in and mess with buffers where I've already turned it on or off.

It's more of a super version of local (that also changes future buffers) than a weak version of -all.

\2. The semantics:

The original behavior for (god-mode) was:

If local & global is the same, toggle both. Otherwise, do nothing in the local buffer but toggle global (secretly, invisibly, in the background) so they match. As user, not even sure something happened or if I even hit the key correctly.

But with my style:
If local & global is the same, toggle both. So far, the same as the original. Otherwise, toggle the local buffer which has an immediate and local and visible effect. Key is reliable and direct: Every hit of the key alternates between on, off, on, off and makes sure global and local is synced up.

But with the original, every hit of the key alternates between on, off, on, off and makes sure global and local is synced up except that first hit of the key, which only syncs up with no immediately noticable effect.

@darth10
Copy link
Collaborator

darth10 commented Oct 18, 2022

It's more of a super version of local (that also changes future buffers) than a weak version of -all.

That makes sense.
You want to toggle God mode, while also toggling God mode in future buffers.
But that's not what the god-mode function is meant for, as I mentioned earlier.

If local & global is the same, toggle both. Otherwise, do nothing in the local buffer but toggle global (secretly, invisibly, in the background) so they match. As user, not even sure something happened or if I even hit the key correctly.

That's right, but the god-mode function is not intended to have a key binding 😄
I'll add this fine print to the documentation soon.

Thanks for the details though!
Now that I understand the use case much better, I'm more certain that a new function is the right way forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants