I'm using a python script to get my monthly bandwith usage shown as string on the terminal stdout. How can I display & update it periodically in the modeline?
There are many ways to add stuff to the mode line.
One way is to define a global minor-mode and a global string variable, register the variable in mode-line-format
when the minor mode is active.
Run your Python code with a timer and write the result to the string variable and call force-mode-line-update
for all windows afterwards.
The following Elisp code demonstrates that. The Python code is replaced by a (format-time-string " Seconds: %S")
from Elisp. Put in whatever you like there.
- Don't use the
(:eval ...)
construct ofmode-line-format
to run your heavy Python task. That eval may be run much more often than you want! - Instead of a simple string you can also use a
(:propertize ...)
construct to add fancy text properties. Since you can change these properties bymy-mode-line-update-handler
you can vary the text color from green to red depending on the network load.
;; mode-line-format
(defvar my-mode-line-update-interval 1
"Mode line update in seconds.")
(defvar my-mode-line-entry ""
"String holding my actual modeline add-on.
See `mode-line-format'.")
;; We need the following if we want to propertize the string:
(put 'my-mode-line-entry 'risky-local-variable t)
(defun my-mode-line-update-handler ()
"Mode line update running for `my-mode-line-mode'."
(setq my-mode-line-entry (format-time-string " Seconds: %S")) ;; here you run your Python code.
(force-mode-line-update t))
(defvar my-mode-line-timer nil
"Timer running my function and updating the modeline.")
(define-minor-mode my-mode-line-mode
"Demonstration of an updating modeline entry."
:global t
(when (timerp my-mode-line-timer)
(cancel-timer my-mode-line-timer))
(if my-mode-line-mode
(progn
(unless (memq 'my-mode-line-entry mode-line-format)
(setq mode-line-format (nconc mode-line-format (list 'my-mode-line-entry))))
(setq my-mode-line-timer (run-with-timer 0 my-mode-line-update-interval #'my-mode-line-update-handler)))
(setq mode-line-format (delq 'my-mode-line-entry mode-line-format))))
You want to append data to global-mode-string
1.
(add-to-list 'global-mode-string '(:eval (myfunc)))
The function:
(defun myfunc ()
(setq mystring (shell-command-to-string "myshellcommand")))
where myshellcommand
is your python script invocation returning your data string.
Now this might stress the system, so instead
(run-at-time 0 60 'myfunc)
(defun myfunc2() mystring)
(add-to-list 'global-mode-string '(:eval myfunc2))
So here myfunc
is called every minute to update mystring
. myfunc2
returns mystring
. We called myfunc2
rather than myfunc
in the mode string update thus not calling your script too often.
Edit:
You might want the call to myfunc2 to do some other work but if not, you can add the symbol directly:-
(add-to-list 'global-mode-string 'mystring)
-
1Instead of
(defun myfunc2() mystring)
and'(:eval myfunc2))
you can just use the mode line construct'mystring
directly. – phils Feb 25 '20 at 22:54 -
mode-line-format
and perhapsglobal-mode-string
andmode-line-misc-info
. – NickD Feb 25 '20 at 14:35