0

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?

jjk
  • 734
  • 4
  • 18

2 Answers2

2

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)
RichieHH
  • 873
  • 4
  • 9
2

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 of mode-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 by my-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))))
Tobias
  • 33,167
  • 1
  • 37
  • 77