Timer on modeline: how to update modeline every second?
As part of my custom mode-line, I've included a feature that displays a countdown timer (timers are created using the chronos package) when it recognises that there is one running.
Works great, but the problem I have is that the mode-line only refreshes when I enter keypresses into Emacs. It will not update in the background (say I work in the browser for a bit but Emacs is still visible).
Is there any good way to force the mode-line to redisplay each second, so that the timer display stays up to date?
Screenshot of mode-line
Relevant code
This is appended to the format-mode-line
list:
(if (>= (length chronos--timers-list) 2)
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")
"")
The my-timer-display
decides whether or not to show the timer. I think this might be the best place to get Emacs to start forcing redisplays.
(defun my-timer-display ()
"Return the lowest timer, avoiding the --now-- time, in the chronos timers list"
(if (string= (chronos--message (nth 0 (chronos--sort-by-expiry))) chronos-now-message)
(my-print-timer 1)
(my-print-timer 0)))
The my-print-timer
function referenced just returns the xth timer in the chronos timers list. I won't include it as I don't think it's relevant to the question.
mode-line timers
add a comment |
As part of my custom mode-line, I've included a feature that displays a countdown timer (timers are created using the chronos package) when it recognises that there is one running.
Works great, but the problem I have is that the mode-line only refreshes when I enter keypresses into Emacs. It will not update in the background (say I work in the browser for a bit but Emacs is still visible).
Is there any good way to force the mode-line to redisplay each second, so that the timer display stays up to date?
Screenshot of mode-line
Relevant code
This is appended to the format-mode-line
list:
(if (>= (length chronos--timers-list) 2)
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")
"")
The my-timer-display
decides whether or not to show the timer. I think this might be the best place to get Emacs to start forcing redisplays.
(defun my-timer-display ()
"Return the lowest timer, avoiding the --now-- time, in the chronos timers list"
(if (string= (chronos--message (nth 0 (chronos--sort-by-expiry))) chronos-now-message)
(my-print-timer 1)
(my-print-timer 0)))
The my-print-timer
function referenced just returns the xth timer in the chronos timers list. I won't include it as I don't think it's relevant to the question.
mode-line timers
add a comment |
As part of my custom mode-line, I've included a feature that displays a countdown timer (timers are created using the chronos package) when it recognises that there is one running.
Works great, but the problem I have is that the mode-line only refreshes when I enter keypresses into Emacs. It will not update in the background (say I work in the browser for a bit but Emacs is still visible).
Is there any good way to force the mode-line to redisplay each second, so that the timer display stays up to date?
Screenshot of mode-line
Relevant code
This is appended to the format-mode-line
list:
(if (>= (length chronos--timers-list) 2)
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")
"")
The my-timer-display
decides whether or not to show the timer. I think this might be the best place to get Emacs to start forcing redisplays.
(defun my-timer-display ()
"Return the lowest timer, avoiding the --now-- time, in the chronos timers list"
(if (string= (chronos--message (nth 0 (chronos--sort-by-expiry))) chronos-now-message)
(my-print-timer 1)
(my-print-timer 0)))
The my-print-timer
function referenced just returns the xth timer in the chronos timers list. I won't include it as I don't think it's relevant to the question.
mode-line timers
As part of my custom mode-line, I've included a feature that displays a countdown timer (timers are created using the chronos package) when it recognises that there is one running.
Works great, but the problem I have is that the mode-line only refreshes when I enter keypresses into Emacs. It will not update in the background (say I work in the browser for a bit but Emacs is still visible).
Is there any good way to force the mode-line to redisplay each second, so that the timer display stays up to date?
Screenshot of mode-line
Relevant code
This is appended to the format-mode-line
list:
(if (>= (length chronos--timers-list) 2)
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")
"")
The my-timer-display
decides whether or not to show the timer. I think this might be the best place to get Emacs to start forcing redisplays.
(defun my-timer-display ()
"Return the lowest timer, avoiding the --now-- time, in the chronos timers list"
(if (string= (chronos--message (nth 0 (chronos--sort-by-expiry))) chronos-now-message)
(my-print-timer 1)
(my-print-timer 0)))
The my-print-timer
function referenced just returns the xth timer in the chronos timers list. I won't include it as I don't think it's relevant to the question.
mode-line timers
mode-line timers
edited Jan 2 at 15:26
Drew
47.3k462104
47.3k462104
asked Jan 2 at 2:02
jamesmajjamesmaj
485
485
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
I try not to use standard timers that repeat because they can affect performance while typing or scrolling. An idle-timer only fires once each time an idle occurs. Therefore, I would suggest setting up a system that runs an idle timer while Emacs has focus and a standard timer when Emacs loses focus. Since that is outside the scope of the question, I will leave that to the O.P. to investigate ...
To try out the following example, start with emacs -Q
, open two or more windows and evaluate the following two lines of code. E.g., place both lines of code in the *scratch*
buffer and type M-x eval-buffer
.
The extra set of parentheses used in the example as part of the mode-line-format
is not necessary for this example, but is helpful to remind us that we can include additional components of the mode-line (as elements of the list) if so desired.
Note that this example uses the optional argument for force-mode-line-update
to operate on all visible windows.
(setq-default mode-line-format '((:eval (format-time-string "%m/%d/%Y @ %1I:%M:%S %p"))))
(run-with-timer 0 1 #'(lambda () (force-mode-line-update t)))
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for themode-line-format
list.
– jamesmaj
Jan 2 at 4:58
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
add a comment |
Thanks to @lawlist for directing me to timer.el
. A solution I implemented uses timer.el
's run-at-time
.
I replaced the format-line-list
item with:
(if (< (length chronos--timers-list) 2)
""
(cancel-function-timers 'force-mode-line-update)
(run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")))
This means that if a timer is running, I ask Emacs to update the mode-line in another 0.5s. This sets a timer. To prevent timers building up if I trigger multiple mode-line refreshes within the 0.5s interval I delete any previous timers first (cancel-function-timers
).
I found that if I used a 1s interval, it would sometimes skip a second if I was typing in Emacs. Reducing to 0.5s makes it act/feel smoother.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "583"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2femacs.stackexchange.com%2fquestions%2f46846%2ftimer-on-modeline-how-to-update-modeline-every-second%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I try not to use standard timers that repeat because they can affect performance while typing or scrolling. An idle-timer only fires once each time an idle occurs. Therefore, I would suggest setting up a system that runs an idle timer while Emacs has focus and a standard timer when Emacs loses focus. Since that is outside the scope of the question, I will leave that to the O.P. to investigate ...
To try out the following example, start with emacs -Q
, open two or more windows and evaluate the following two lines of code. E.g., place both lines of code in the *scratch*
buffer and type M-x eval-buffer
.
The extra set of parentheses used in the example as part of the mode-line-format
is not necessary for this example, but is helpful to remind us that we can include additional components of the mode-line (as elements of the list) if so desired.
Note that this example uses the optional argument for force-mode-line-update
to operate on all visible windows.
(setq-default mode-line-format '((:eval (format-time-string "%m/%d/%Y @ %1I:%M:%S %p"))))
(run-with-timer 0 1 #'(lambda () (force-mode-line-update t)))
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for themode-line-format
list.
– jamesmaj
Jan 2 at 4:58
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
add a comment |
I try not to use standard timers that repeat because they can affect performance while typing or scrolling. An idle-timer only fires once each time an idle occurs. Therefore, I would suggest setting up a system that runs an idle timer while Emacs has focus and a standard timer when Emacs loses focus. Since that is outside the scope of the question, I will leave that to the O.P. to investigate ...
To try out the following example, start with emacs -Q
, open two or more windows and evaluate the following two lines of code. E.g., place both lines of code in the *scratch*
buffer and type M-x eval-buffer
.
The extra set of parentheses used in the example as part of the mode-line-format
is not necessary for this example, but is helpful to remind us that we can include additional components of the mode-line (as elements of the list) if so desired.
Note that this example uses the optional argument for force-mode-line-update
to operate on all visible windows.
(setq-default mode-line-format '((:eval (format-time-string "%m/%d/%Y @ %1I:%M:%S %p"))))
(run-with-timer 0 1 #'(lambda () (force-mode-line-update t)))
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for themode-line-format
list.
– jamesmaj
Jan 2 at 4:58
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
add a comment |
I try not to use standard timers that repeat because they can affect performance while typing or scrolling. An idle-timer only fires once each time an idle occurs. Therefore, I would suggest setting up a system that runs an idle timer while Emacs has focus and a standard timer when Emacs loses focus. Since that is outside the scope of the question, I will leave that to the O.P. to investigate ...
To try out the following example, start with emacs -Q
, open two or more windows and evaluate the following two lines of code. E.g., place both lines of code in the *scratch*
buffer and type M-x eval-buffer
.
The extra set of parentheses used in the example as part of the mode-line-format
is not necessary for this example, but is helpful to remind us that we can include additional components of the mode-line (as elements of the list) if so desired.
Note that this example uses the optional argument for force-mode-line-update
to operate on all visible windows.
(setq-default mode-line-format '((:eval (format-time-string "%m/%d/%Y @ %1I:%M:%S %p"))))
(run-with-timer 0 1 #'(lambda () (force-mode-line-update t)))
I try not to use standard timers that repeat because they can affect performance while typing or scrolling. An idle-timer only fires once each time an idle occurs. Therefore, I would suggest setting up a system that runs an idle timer while Emacs has focus and a standard timer when Emacs loses focus. Since that is outside the scope of the question, I will leave that to the O.P. to investigate ...
To try out the following example, start with emacs -Q
, open two or more windows and evaluate the following two lines of code. E.g., place both lines of code in the *scratch*
buffer and type M-x eval-buffer
.
The extra set of parentheses used in the example as part of the mode-line-format
is not necessary for this example, but is helpful to remind us that we can include additional components of the mode-line (as elements of the list) if so desired.
Note that this example uses the optional argument for force-mode-line-update
to operate on all visible windows.
(setq-default mode-line-format '((:eval (format-time-string "%m/%d/%Y @ %1I:%M:%S %p"))))
(run-with-timer 0 1 #'(lambda () (force-mode-line-update t)))
answered Jan 2 at 2:34
lawlistlawlist
10.5k11062
10.5k11062
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for themode-line-format
list.
– jamesmaj
Jan 2 at 4:58
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
add a comment |
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for themode-line-format
list.
– jamesmaj
Jan 2 at 4:58
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for the
mode-line-format
list.– jamesmaj
Jan 2 at 4:58
After learning about timer.el from this answer decided to implement a solution like so: ` (progn` ` (cancel-function-timers 'force-mode-line-update)` ` (run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))` ` (list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| "))` This fits in the true condition for the
mode-line-format
list.– jamesmaj
Jan 2 at 4:58
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
Unsure on stackoverflow ettiquite. Should I mark this as the answer, or should I create my own detailed answer and give credit to this answer?
– jamesmaj
Jan 2 at 5:06
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
I will not be saddened if you write-up your own alternative answer. If you think that the question title and/or body need to be clarified so that this thread helps future forum searches, then please feel free to do so.
– lawlist
Jan 2 at 5:07
add a comment |
Thanks to @lawlist for directing me to timer.el
. A solution I implemented uses timer.el
's run-at-time
.
I replaced the format-line-list
item with:
(if (< (length chronos--timers-list) 2)
""
(cancel-function-timers 'force-mode-line-update)
(run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")))
This means that if a timer is running, I ask Emacs to update the mode-line in another 0.5s. This sets a timer. To prevent timers building up if I trigger multiple mode-line refreshes within the 0.5s interval I delete any previous timers first (cancel-function-timers
).
I found that if I used a 1s interval, it would sometimes skip a second if I was typing in Emacs. Reducing to 0.5s makes it act/feel smoother.
add a comment |
Thanks to @lawlist for directing me to timer.el
. A solution I implemented uses timer.el
's run-at-time
.
I replaced the format-line-list
item with:
(if (< (length chronos--timers-list) 2)
""
(cancel-function-timers 'force-mode-line-update)
(run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")))
This means that if a timer is running, I ask Emacs to update the mode-line in another 0.5s. This sets a timer. To prevent timers building up if I trigger multiple mode-line refreshes within the 0.5s interval I delete any previous timers first (cancel-function-timers
).
I found that if I used a 1s interval, it would sometimes skip a second if I was typing in Emacs. Reducing to 0.5s makes it act/feel smoother.
add a comment |
Thanks to @lawlist for directing me to timer.el
. A solution I implemented uses timer.el
's run-at-time
.
I replaced the format-line-list
item with:
(if (< (length chronos--timers-list) 2)
""
(cancel-function-timers 'force-mode-line-update)
(run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")))
This means that if a timer is running, I ask Emacs to update the mode-line in another 0.5s. This sets a timer. To prevent timers building up if I trigger multiple mode-line refreshes within the 0.5s interval I delete any previous timers first (cancel-function-timers
).
I found that if I used a 1s interval, it would sometimes skip a second if I was typing in Emacs. Reducing to 0.5s makes it act/feel smoother.
Thanks to @lawlist for directing me to timer.el
. A solution I implemented uses timer.el
's run-at-time
.
I replaced the format-line-list
item with:
(if (< (length chronos--timers-list) 2)
""
(cancel-function-timers 'force-mode-line-update)
(run-at-time 0.5 nil '(lambda () (force-mode-line-update t)))
(list " timer|" (propertize (my-timer-display) 'face 'my-red-face) "| ")))
This means that if a timer is running, I ask Emacs to update the mode-line in another 0.5s. This sets a timer. To prevent timers building up if I trigger multiple mode-line refreshes within the 0.5s interval I delete any previous timers first (cancel-function-timers
).
I found that if I used a 1s interval, it would sometimes skip a second if I was typing in Emacs. Reducing to 0.5s makes it act/feel smoother.
edited Jan 2 at 15:28
Drew
47.3k462104
47.3k462104
answered Jan 2 at 5:25
jamesmajjamesmaj
485
485
add a comment |
add a comment |
Thanks for contributing an answer to Emacs Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2femacs.stackexchange.com%2fquestions%2f46846%2ftimer-on-modeline-how-to-update-modeline-every-second%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown