summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.woodpecker.yml (renamed from .drone.yml)5
-rw-r--r--changelog.md48
-rw-r--r--doc/compiling.org4
-rw-r--r--doc/plugins.org45
-rw-r--r--doc/quick-start.org501
-rw-r--r--doc/using-haskell.org22
-rw-r--r--readme.org110
-rw-r--r--src/Xmobar/App/Compile.hs30
-rw-r--r--src/Xmobar/App/Config.hs1
-rw-r--r--src/Xmobar/App/Opts.hs8
-rw-r--r--src/Xmobar/Config/Parse.hs16
-rw-r--r--src/Xmobar/Config/Template.hs188
-rw-r--r--src/Xmobar/Config/Types.hs141
-rw-r--r--src/Xmobar/Draw/Boxes.hs34
-rw-r--r--src/Xmobar/Draw/Cairo.hs65
-rw-r--r--src/Xmobar/Draw/Types.hs5
-rw-r--r--src/Xmobar/Plugins/EWMH.hs1
-rw-r--r--src/Xmobar/Plugins/Kbd.hs72
-rw-r--r--src/Xmobar/Plugins/Kraken.hs2
-rw-r--r--src/Xmobar/Plugins/Locks.hs58
-rw-r--r--src/Xmobar/Plugins/Monitors/Alsa.hs6
-rw-r--r--src/Xmobar/Plugins/Monitors/Batt/Common.hs6
-rw-r--r--src/Xmobar/Plugins/Monitors/Common/Output.hs22
-rw-r--r--src/Xmobar/Plugins/Monitors/Disk.hs8
-rw-r--r--src/Xmobar/Plugins/Monitors/Mem/Linux.hs10
-rw-r--r--src/Xmobar/Plugins/Monitors/Net/Linux.hs5
-rw-r--r--src/Xmobar/Run/Actions.hs6
-rw-r--r--src/Xmobar/Run/Parsers.hs244
-rw-r--r--src/Xmobar/Run/Template.hs3
-rw-r--r--src/Xmobar/System/DBus.hs10
-rw-r--r--src/Xmobar/System/Environment.hs9
-rw-r--r--src/Xmobar/Text/Loop.hs2
-rw-r--r--src/Xmobar/Text/Output.hs24
-rw-r--r--src/Xmobar/Text/Swaybar.hs20
-rw-r--r--src/Xmobar/X11/Bitmap.hs7
-rw-r--r--src/Xmobar/X11/Draw.hs10
-rw-r--r--src/Xmobar/X11/Events.hs19
-rw-r--r--src/Xmobar/X11/Loop.hs14
-rw-r--r--src/Xmobar/X11/Window.hs30
-rw-r--r--stack.yaml4
-rw-r--r--xmobar.cabal18
41 files changed, 1130 insertions, 703 deletions
diff --git a/.drone.yml b/.woodpecker.yml
index 4b6e816..f8aeae3 100644
--- a/.drone.yml
+++ b/.woodpecker.yml
@@ -1,9 +1,10 @@
matrix:
GHC_VERSION:
- - 9
+ - 9.6
+ - 9.4
- 8
-pipeline:
+steps:
test:
image: haskell:${GHC_VERSION}
commands:
diff --git a/changelog.md b/changelog.md
index b4f5009..6306c03 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,51 @@
+## Version 0.49 (unreleased)
+
+## Version 0.48 (April, 2024)
+
+- The `Kbd` monitor is now clickable (thanks, Enrico Maria)
+- Fix zombie processes left by `<action>` tag and low battery action (thanks,
+ Ulrik)
+- Fix plugins such as `Alsa` and `Com` not working when configuration is
+ recompiled (#657, ditto)
+- New `Lock'` monitor with configurable labels (thanks, Enrico Maria)
+
+## Version 0.47.4 (March, 2024)
+
+- Bug fixes (launching processes from self-compiled instances)
+
+## Version 0.47.3 (February, 2024)
+
+- New flag `with_shared` to use xmobar with dynamic linking (see PR #690)
+- Fix for actions invoked from recompiled xmobar instances (issue #688)
+- Maximum base version bumped to 4.20
+
+## Version 0.47.2 (November, 2023)
+
+- Compatibility with GHC 9.6
+
+## Version 0.47.1 (September, 2023)
+
+- Allow compilation with libmpd even with GHC > 9.4, by requesting it
+ explicitly with `with_mpd`. See #667 for further details.
+
+## Version 0.47 (August, 2023)
+
+- Fix: center middle section for templates of the for }M{
+- Documentation fixes and improvements
+- Better error handling in network connections
+- Dependency fixes (libmpd excluded for GHC > 9.2)
+
+## Version 0.46 (January, 2023)
+
+- New bar position specifiers TopHM, BottomHM.
+- New configuration option, `dpi`, to set the font scaling factor.
+- Fixes and extensions for section alignment behaviour (#650, #655).
+- Fix: honour fc/bg specs for icons (#663).
+
+## Version 0.45 (October, 2022)
+
+- New cairo/pango font drawing backend, substituting the direct X11/Xft one.
+
## Version 0.44.2 (August, 2022)
- Documentation improvements.
diff --git a/doc/compiling.org b/doc/compiling.org
index 4e0125e..977ef2b 100644
--- a/doc/compiling.org
+++ b/doc/compiling.org
@@ -85,7 +85,9 @@
enters a high-CPU regime right after starting.
- =with_xrender= Enables the main bar background alpha parameter. Requires
- the [[http://hackage.haskell.org/package/X11-xft/][X11-xft]] package.
+ the [[http://hackage.haskell.org/package/X11-xft/][X11-xft]] package. The Xrender extension is not compatible with 10-bit
+ colour modes, i.e., setting ~DefaultDepth~ to 30 in your Xorg
+ configuration. See discussion in [[https://codeberg.org/xmobar/xmobar/issues/651][issue 651]] for details.
- =with_xpm= Support for xpm image file format. This will allow loading
.xpm files in =<icon>=. Requires the [[http://cgit.freedesktop.org/xorg/lib/libXpm][libXpm]] C library.
diff --git a/doc/plugins.org b/doc/plugins.org
index 2199659..ebe5a5b 100644
--- a/doc/plugins.org
+++ b/doc/plugins.org
@@ -16,11 +16,11 @@
to a certain monitor.
All Monitors accept a common set of arguments, described below in
- [[Default Monitor Arguments]]. Some monitors also accept additional
+ [[#default-arguments][Default Monitor Arguments]]. Some monitors also accept additional
options that are specific to them. When specifying the list of
arguments in your configuration, the common options come first,
followed by =--=, followed by any monitor-specific options. For
- example, the following [[=Battery Args RefreshRate=][Battery]] configuration first sets the global
+ example, the following [[#batteryp-dirs-args-refreshrate][Battery]] configuration first sets the global
=template= and =Low= arguments and then specifies the battery-specific
=off= option.
@@ -60,6 +60,9 @@
brightness value.
** Default monitor arguments
+ :PROPERTIES:
+ :CUSTOM_ID: default-arguments
+ :END:
These are the options available for all monitors:
@@ -655,8 +658,9 @@
** Keyboard and screen monitors
*** =Kbd Opts=
- - Registers to XKB/X11-Events and output the currently active keyboard
- layout. Supports replacement of layout names.
+ - Registers to XKB/X11-Events, output the currently active keyboard
+ layout, and maps left and right clicks to switching to next and
+ previous layouts respectively. Supports replacement of layout names.
- Aliases to =kbd=
@@ -694,18 +698,37 @@
#+begin_src haskell
Run Brightness ["-t", "<bar>"] 60
#+end_src
+
*** =Locks=
- Displays the status of Caps Lock, Num Lock and Scroll Lock.
- Aliases to =locks=
+ - Contructors:
+
+ - =Locks= is nullary and uses the strings =CAPS=, =NUM=, =SCROLL= to signal
+ that a lock is enabled (and empty strings to signal it's disabled)
+
+ - =Locks'= allow customizing the strings for the enabled/disabled states
+ of the 3 locks by accepting an assoc list of type =[(String, (String, String))]=,
+ which is expected to contain exactly 3 elements with keys
+ ="CAPS"=, ="NUM"=, ="SCROLL"=.
+
- Example:
#+begin_src haskell
+ -- using default labels
Run Locks
#+end_src
+ #+begin_src haskell
+ -- using custom labels
+ Run $ Locks' [("CAPS" , ("<fc=#00ff00>\xf023</fc>", "<fc=#777777>\xf09c</fc>") )
+ ,("NUM" , ("<fc=#777777>\xf047</fc>", "<fc=#00ff00>\xf047</fc>" ) )
+ ,("SCROLL", ("SlOCK", "" ))]
+ #+end_src
+
** Load and Process monitors
*** =Load Args RefreshRate=
@@ -814,6 +837,9 @@
** Volume monitors
*** =Volume Mixer Element Args RefreshRate=
+ :PROPERTIES:
+ :CUSTOM_ID: volume
+ :END:
- Aliases to the mixer name and element name separated by a
colon. Thus, =Volume "default" "Master" [] 10= can be used as
@@ -889,7 +915,7 @@
*** =Alsa Mixer Element Args=
- Like [[=Volume Mixer Element Args RefreshRate=][Volume]] but with the following differences:
+ Like [[#volume][Volume]] but with the following differences:
- Uses event-based refreshing via =alsactl monitor= instead of polling,
so it will refresh instantly when there's a volume change, and won't
@@ -1355,6 +1381,9 @@
(re)start xmobar outside xmonad.
*** =UnsafeXMonadLog=
+ :PROPERTIES:
+ :CUSTOM_ID: UnsafeXMonadLog
+ :END:
- Aliases to UnsafeXMonadLog
- Displays any text received by xmobar on the =_XMONAD_LOG= atom.
@@ -1385,7 +1414,7 @@
- Aliases to =PropName=
- Reads the X property named by =PropName= (a string) and displays its
- value. The [[../etc/xmonadpropwrite.hs][etc/xmonadpropwrite.hs script]] in xmobar's distribution can be
+ value. The [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmonadpropwrite.hs][etc/xmonadpropwrite.hs script]] in xmobar's distribution can be
used to set the given property from the output of any other program or
script.
@@ -1421,7 +1450,7 @@
- Aliases to UnsafeStdinReader
- Displays any text received by xmobar on its standard input.
- - Similar to [[=UnsafeXMonadLog=][UnsafeXMonadLog]], in the sense that it does not strip any
+ - Similar to [[#UnsafeXMonadLog][UnsafeXMonadLog]], in the sense that it does not strip any
actions from the received text, only using =stdin= and not a property
atom of the root window. Please be equally carefully when using this
as when using =UnsafeXMonadLog=!
@@ -1480,7 +1509,7 @@
=/tmp/xmobar_status= will reveal xmonad for 1.5 seconds and
temporarily overwrite the window titles.
- - Take a look at [[../etc/status.sh][etc/status.sh]]
+ - Take a look at [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/status.sh][etc/status.sh]]
- Expands environment variables for the pipe path
diff --git a/doc/quick-start.org b/doc/quick-start.org
index d711138..fecd953 100644
--- a/doc/quick-start.org
+++ b/doc/quick-start.org
@@ -1,12 +1,12 @@
#+title: Quick start: using xmobar
-Xmobar can either be configured using the configuration language, or [[file:using-haskell.org][used as a
+Xmobar can either be configured using the configuration language, or [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/using-haskell.org][used as a
Haskell library]] (similar to xmonad) and compiled with your specific
configuration. For an example of a configuration file using the plain
-configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you can have a look at
-[[../etc/xmobar.hs][etc/xmobar.hs]] for an example of how to write your own xmobar using Haskell.
+configuration language, see [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.config][etc/xmobar.config]], and you can have a look at
+[[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.hs][etc/xmobar.hs]] for an example of how to write your own xmobar using Haskell.
-* Command Line Options
+* Command line options
xmobar can be either configured with a configuration file or with
command line options. In the second case, the command line options will
@@ -20,7 +20,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
This is the list of command line options (the output of =xmobar --help=):
- #+begin_src shell
+ #+begin_example
Usage: xmobar [OPTION...] [FILE]
Options:
-h, -? --help This help
@@ -38,187 +38,350 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
-o --top Place xmobar at the top of the screen
-b --bottom Place xmobar at the bottom of the screen
-d --dock Don't override redirect from WM and function as a dock
- -a alignsep --alignsep=alignsep Separators for left, center and right text
- alignment. Default: '}{'
- -s char --sepchar=char Character used to separate commands in
- the output template. Default '%'
- -t template --template=template Output template
- -c commands --commands=commands List of commands to be executed
- -C command --add-command=command Add to the list of commands to be executed
- -x screen --screen=screen On which X screen number to start
- -p position --position=position Specify position of xmobar. Same syntax as in config file
- -T [format] --text[=format] Write output to stdout
-
- Mail bug reports and suggestions to <mail@jao.io>
- #+end_src
-* Configuration Options
+ -a alignsep --alignsep=alignsep Separators for left, center and right text
+ alignment. Default: '}{'
+ -s char --sepchar=char Character used to separate commands in
+ the output template. Default '%'
+ -t template --template=template Output template
+ -c commands --commands=commands List of commands to be executed
+ -C command --add-command=command Add to the list of commands to be executed
+ -x screen --screen=screen On which X screen number to start
+ -p position --position=position Specify position of xmobar. Same syntax as in config file
+ -T [format] --text[=format] Write output to stdout
+ -D dpi --dpi=dpi The DPI scaling factor. Default 96.0
+
+ Mail bug reports and suggestions to <mail@jao.io>
+ #+end_example
+
+* Configuration options
:PROPERTIES:
:CUSTOM_ID: configuration-options
:END:
** Global options
- Here are all the global configuration options that you can set within
- the =Config= block in your configuration.
+ Here are all the global options that you can set within the =Config= block in
+ your configuration and will define the overall behaviour and looks of your
+ bar.
- - =font= Name of the font to be used.
+*** Fonts
+ :PROPERTIES:
+ :CUSTOM_ID: fonts
+ :END:
- - =additionalFonts= Haskell-style list of fonts to be used with the
- =fn=-template. See also =textOffsets= below. For example:
+ The following configuration options control the fonts used by xmobar:
- #+begin_src haskell
- additionalFonts = [iconFont, altIconFont]
- #+end_src
+ - =font= Name, as a string, of the default font to use.
- - =bgColor= Background color.
+ - =additionalFonts= Haskell-style list of fonts to us with the
+ =fn=-template. See also =textOffsets= below. For example:
- - =fgColor= Default font color.
+ #+begin_src haskell
+ additionalFonts = [iconFont, altIconFont]
+ #+end_src
+
+ - =dpi= The DPI scaling factor, as a decimal, to use. If 0, negative, or not
+ given, the default of 96 will be used, which corresponds to an average
+ screen. A 10pt font will therefore scale to 10pt * (1/72 pt/inch) * (96
+ pixel/inch) = 13.3 pixel. This is especially useful for HiDPI displays.
+
+ The global font is used by default when none of the others is specified
+ using the ~<fn=n>...</fn>~ markup, with ~n~ a 1-based index in the
+ ~additionalFonts~ array. So, for instance
+
+ #+begin_src
+ <fn=2>some text</fn>
+ #+end_src
- - =alpha= The transparency. 0 is transparent, 255 is opaque.
+ will use, in the configuration above, ~altIconFont~ to display "some text".
- - =position= Top, TopH, TopP, TopW, TopSize, Bottom, BottomH,
- BottomP, BottomW, BottomSize or Static (with x, y, width and height).
+ Font names use the [[https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html][Pango format]]. Here are a few simple examples:
- TopP and BottomP take 2 arguments: left padding and right padding.
+ #+begin_example
+ DejaVu Sans Mono 10
- TopW and BottomW take 2 arguments: an alignment parameter (L for left,
- C for centered, R for Right) and an integer for the percentage width
- xmobar window will have in respect to the screen width.
+ Iosevka Comfy Semi-Bold Italic 12
- TopSize and BottomSize take 3 arguments: an alignment parameter, an
- integer for the percentage width, and an integer for the minimum pixel
- height that the xmobar window will have.
+ Noto Color Emoji 10
+ #+end_example
- TopH and BottomH take one argument (Int) which adjusts the bar height.
+ We start with a family name (DejaVu Sans Mono, Iosevka Comfy, etc.),
+ followed by optional, space-separated /style options/ (Semi-Bold Italic in
+ the second example above), and ending with a size, in points.
- For example:
+ There are many possible style options (if your font supports them). They
+ can be
- #+begin_src haskell
- position = TopH 30
- #+end_src
+ - *Plain styles*: Normal, Roman, Oblique, Italic.
+ - *Variants*: Small-Caps, All-Small-Caps, Petite-Caps, All-Petite-Caps,
+ Unicase, Title-Caps.
+ - *Weights*: Thin, Ultra-Light, Extra-Light, Light, Semi-Ligh, Demi-Light,
+ Book, Regular, Medium, Semi-Bold, Demi-Bold, Bold, Ultra-Bold,
+ Extra-Bold, Heavy, Black, Ultra-Black, Extra-Black.
+ - *Strectch values:* Thin, Ultra-Light, Extra-Light, Light, Semi-Light,
+ Demi-Light, Book, Regular, Medium, Semi-Bold, Demi-Bold, Bold,
+ Ultra-Bold, Extra-Bold, Heavy, Black, Ultra-Black, Extra-Black.
+ - *Gravity values*: Not-Rotated, South, Upside-Down, North, Rotated-Left,
+ East, Rotated-Right, West.
- to make a 30 tall bar on the top, or
+ So you can add up to 5 style options per family:
- #+begin_src haskell
- position = BottomH 30
- #+end_src
+ #+begin_example
+ Monospace Italic All-Small-Caps Extra-Light Thin North 12
+ #+end_example
- to make a 30 tall bar on the bottom of the screen.
+ It's also possible to specify a list of fonts, separating them by commas,
+ so that they act as fallbacks when the preceding one is not able to display
+ a given glyph. A bit confusingly, the styles and sizes come in reverse
+ order after the families:
- #+begin_src haskell
- position = BottomW C 75
- #+end_src
+ #+begin_example
+ Family 1, Family 2 Styles 2 Size 2, Styles 1 Size 1
+ #+end_example
- to place xmobar at the bottom, centered with the 75% of the screen
- width. Or
+ For instance you could have:
- #+begin_src haskell
- position = BottomP 120 0
- #+end_src
+ #+begin_example
+ Souce Code Pro, Noto Color Emoji Regular 12, Semi-Bold 10
+ #+end_example
- to place xmobar at the bottom, with 120 pixel indent of the left. Or
+ to use Source Code Pro Semi-Bold 10 when possible, and fall back to Noto
+ Color Emoji Regular 12 for characters that the former cannot display.
- #+begin_src haskell
- position = Static { xpos = 0 , ypos = 0, width = 1024, height = 15 }
- #+end_src
+**** X11 Bitmap fonts
- or
+ If you want to use traditional, non-aliased X11 fonts, you can do so via
+ the [[https://www.cl.cam.ac.uk/~mgk25/ucs-fonts.html][Unicode fonts and tools for X11]] package, which provides bitmap
+ versions of them, with a specification of the stytle ~"Fixed 8"~ for what
+ in the old days would have been something like
+ ~-Misc-Fixed-Medium-R-Normal--13-120-75-75-C-70-ISO10646-1~. See also
+ discussion in [[https://codeberg.org/xmobar/xmobar/issues/658][issue #658]].
- #+begin_src haskell
- position = Top
- #+end_src
+*** Colors
- - =textOffset= The vertical offset, in pixels, for the text baseline. If
- negative or not given, xmobar will try to center text vertically.
+ - =bgColor= Background color.
- - =textOffsets= A list of vertical offsets, in pixels, for the text
- baseline, to be used with the each of the fonts in =additionalFonts=
- (if any). If negative or not given, xmobar will try to center text
- vertically for that font.
+ - =fgColor= Default font color.
- - =iconOffset= The vertical offset, in pixels, for icons bottom line. If
- negative or not given, xmobar will try to center icons vertically.
+ - =alpha= The transparency. 0 is transparent, 255 is opaque.
- - =lowerOnStart= When True the window is sent the bottom of the window
- stack initially.
+*** Vertical offsets
- - =hideOnStart= When set to True the window is initially not mapped,
- i.e. hidden. It then can be toggled manually (for example using the
- dbus interface) or automatically (by a plugin) to make it reappear.
+ By default, all text and icons in the bar will be vertically centered
+ according to the configured height of the bar. You can override that
+ behaviour with the following options:
- - =allDesktops= When set to True (the default), xmobar will tell the
- window manager explicitly to be shown in all desktops, by setting
- =_NET_WM_DESKTOP= to 0xffffffff.
+ - =textOffset= The vertical offset, in pixels, for the text baseline. If
+ negative or not given, xmobar will try to center text vertically.
- - =overrideRedirect= If you're running xmobar in a tiling window
- manager, you might need to set this option to =False= so that it
- behaves as a docked application. Defaults to =True=.
+ - =textOffsets= A list of vertical offsets, in pixels, for the text
+ baseline, to be used with the each of the fonts in =additionalFonts=
+ (if any). If negative or not given, xmobar will try to center text
+ vertically for that font.
- - =pickBroadest= When multiple displays are available, xmobar will
- choose by default the first one to place itself. With this flag set to
- =True= (the default is =False=) it will choose the broadest one
- instead.
+ - =iconOffset= The vertical offset, in pixels, for icons bottom line. If
+ negative or not given, xmobar will try to center icons vertically.
- - =persistent= When True the window status is fixed i.e. hiding or
- revealing is not possible. This option can be toggled at runtime.
- Defaults to False.
+*** Borders
+
+ - =border= TopB, TopBM, BottomB, BottomBM, FullB, FullBM or NoBorder
+ (default).
+
+ TopB, BottomB, FullB take no arguments, and request drawing a border
+ at the top, bottom or around xmobar's window, respectively.
+
+ TopBM, BottomBM, FullBM take an integer argument, which is the margin,
+ in pixels, between the border of the window and the drawn border.
+
+ - =borderColor= Border color.
+
+ - =borderWidth= Border width in pixels.
+
+ - =iconRoot= Root folder where icons are stored. For =<icon=path/>= if
+ path start with =/=, =./= or =../= it is interpreted as it is.
+ Otherwise it will have
+
+ #+begin_src haskell
+ iconRoot ++ "/"
+ #+end_src
- - =border= TopB, TopBM, BottomB, BottomBM, FullB, FullBM or NoBorder
- (default).
+ prepended to it. Default is =.=.
- TopB, BottomB, FullB take no arguments, and request drawing a border
- at the top, bottom or around xmobar's window, respectively.
+*** Bar position
- TopBM, BottomBM, FullBM take an integer argument, which is the margin,
- in pixels, between the border of the window and the drawn border.
+ - =position= Top, TopH, TopHM, TopP, TopW, TopSize, Bottom, BottomH, BottomHM,
+ BottomP, BottomW, BottomSize or Static (with x, y, width and height).
- - =borderColor= Border color.
+ TopP and BottomP take 2 arguments: left padding and right padding.
- - =borderWidth= Border width in pixels.
+ TopW and BottomW take 2 arguments: an alignment parameter (L for left,
+ C for centered, R for Right) and an integer for the percentage width
+ xmobar window will have in respect to the screen width.
- - =iconRoot= Root folder where icons are stored. For =<icon=path/>= if
- path start with =/=, =./= or =../= it is interpreted as it is.
- Otherwise it will have
+ TopSize and BottomSize take 3 arguments: an alignment parameter, an
+ integer for the percentage width, and an integer for the minimum pixel
+ height that the xmobar window will have.
- #+begin_src haskell
- iconRoot ++ "/"
- #+end_src
+ TopH and BottomH take one argument (Int) which adjusts the bar height.
- prepended to it. Default is =.=.
+ For example:
- - =commands= For setting the options of the programs to run (optional).
+ #+begin_src haskell
+ position = TopH 30
+ #+end_src
+
+ to make a 30 tall bar on the top, or
+
+ #+begin_src haskell
+ position = BottomH 30
+ #+end_src
+
+ to make a 30 tall bar on the bottom of the screen. The corresponding
+ variants ~TopHM~ and ~BottomHM~ allow you to specify, in addition to a
+ height, margins (in pixels) with the borders of the screen (left, right
+ top and bottom); so they take five integers as arguments. For instance,
+ if you one a margin of 2 pixels to the left of the top bar in the above
+ example and 4 to its right and top, you could use:
+
+ #+begin_src haskell
+ position = TopHM 30 2 4 4 0
+ #+end_src
+
+ and similarly for ~BottomHM~.
+
+ #+begin_src haskell
+ position = BottomW C 75
+ #+end_src
+
+ to place xmobar at the bottom, centered with the 75% of the screen
+ width. Or
+
+ #+begin_src haskell
+ position = BottomP 120 0
+ #+end_src
+
+ to place xmobar at the bottom, with 120 pixel indent of the left. Or
+
+ #+begin_src haskell
+ position = Static { xpos = 0 , ypos = 0, width = 1024, height = 15 }
+ #+end_src
- - =sepChar= The character to be used for indicating commands in the
- output template (default '%').
+ or
+
+ #+begin_src haskell
+ position = Top
+ #+end_src
+
+ - =lowerOnStart= When True the window is sent the bottom of the window
+ stack initially.
+
+ - =hideOnStart= When set to True the window is initially not mapped,
+ i.e. hidden. It then can be toggled manually (for example using the
+ dbus interface) or automatically (by a plugin) to make it reappear.
+
+ - =allDesktops= When set to True (the default), xmobar will tell the
+ window manager explicitly to be shown in all desktops, by setting
+ =_NET_WM_DESKTOP= to 0xffffffff.
+
+ - =overrideRedirect= If you're running xmobar in a tiling window
+ manager, you might need to set this option to =False= so that it
+ behaves as a docked application. Defaults to =True=.
+
+ - =pickBroadest= When multiple displays are available, xmobar will
+ choose by default the first one to place itself. With this flag set to
+ =True= (the default is =False=) it will choose the broadest one
+ instead.
+
+ - =persistent= When True the window status is fixed i.e. hiding or
+ revealing is not possible. This option can be toggled at runtime.
+ Defaults to False.
+
+ - =wmClass= The value for the window's X11 ~WM_CLASS~ property. Defaults
+ to "xmobar".
+
+ - =wmName= The value for the window's X11 ~WM_NAME~ property. Defaults to
+ "xmobar".
+
+*** Text output
+
+ - =textOutput= When True, instead of running as an X11 application,
+ write output to stdout, with optional color escape sequences. In
+ this mode, icon and action specifications are ignored. Default is
+ False.
+
+ - =textOutputFormat= Plain, Ansi or Pango, to emit, when in text
+ mode, escape color sequences using ANSI controls (for terminals) or
+ pango markup. Default is Plain.
+
+*** Commands and monitors
+
+ - =commands= The list of monitors and plugins to run, together with their
+ individual configurations. The [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][plugin documentation]] details all the
+ available monitors, and you can also create new ones using Haskell. See
+ the [[#commands-list][commands list section]] below for more.
+
+ - =sepChar= The character to be used for indicating commands in the
+ output template (defaults to '%').
+
+ - =alignSep= a 2-character string for aligning text in the output
+ template. See [[#bar-sections][this section]] for details.
+
+ - =template= The output template: a string telling xmobar how to display the
+ outputs of all the =commands= above. See [[#output-template][the next section]] for a full
+ description.
+
+** The =commands= list
+ :PROPERTIES:
+ :CUSTOM_ID: commands-list
+ :END:
+
+ The =commands= configuration option is a list of commands information
+ and arguments to be used by xmobar when parsing the output template.
+ Each member of the list consists in a command prefixed by the =Run=
+ keyword. Each command has arguments to control the way xmobar is going
+ to execute it.
+
+ The options consist in a list of commands separated by a comma and enclosed
+ by square parenthesis.
+
+ Example:
+
+ #+begin_src haskell
+ [Run Memory ["-t","Mem: <usedratio>%"] 10, Run Swap [] 10]
+ #+end_src
- - =alignSep= a 2 character string for aligning text in the output
- template. The text before the first character will be align to left,
- the text in between the 2 characters will be centered, and the text
- after the second character will be align to the right.
+ to run the Memory monitor plugin with the specified template, and the
+ swap monitor plugin, with default options, every second. And here's an
+ example of a template for the commands above using an icon:
- - =template= The output template.
+ #+begin_src haskell
+ template = "<icon=/home/jao/.xmobar/mem.xbm/><memory> <swap>"
+ #+end_src
- - =wmClass= The value for the window's X11 ~WM_CLASS~ property. Defaults
- to "xmobar".
+ This example will run "xclock" command when date is clicked:
- - =wmName= The value for the window's X11 ~WM_NAME~ property. Defaults to
- "xmobar".
+ #+begin_src haskell
+ template = "<action=`xclock`>%date%</action>"
+ #+end_src
- - =textOutput= When True, instead of running as an X11 application,
- write output to stdout, with optional color escape sequences. In
- this mode, icon and action specifications are ignored. Default is
- False.
+ The only internal available command is =Com= (see below Executing
+ External Commands). All other commands are provided by plugins. xmobar
+ comes with some plugins, providing a set of system monitors, a standard
+ input reader, an Unix named pipe reader, a configurable date plugin, and
+ much more: we list all available plugins below.
- - =textOutputFormat= Plain, Ansi or Pango, to emit, when in text
- mode, escape color sequences using ANSI controls (for terminals) or
- pango markup. Default is Plain.
+ Other commands can be created as plugins with the Plugin infrastructure.
+ See below.
** The output =template=
+ :PROPERTIES:
+ :CUSTOM_ID: output-template
+ :END:
The output template is how xmobar will end up printing all of your
configured commands. It must contain at least one command. Xmobar
will parse the template and search for the command to be executed
in the =commands= configuration option. First an =alias= will be
searched (some plugins, such as =Weather= or =Network=, have default
- aliases, see the [[./plugins.org][plugin documentation]]). After that, the command
+ aliases, see the [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][plugin documentation]]). After that, the command
name will be tried. If a command is found, the arguments specified
in the =commands= list will be used.
@@ -242,7 +405,8 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
opacity, with two additional hex digits (e.g. #FF00000aa).
- =<fn=1>string</fn>= will print =string= with the first font from
- =additionalFonts=. The index =0= corresponds to the standard font.
+ =additionalFonts=. The index =0= corresponds to the standard font. The
+ standard font is also used if the index is out of bounds.
- =<hspace=X/>= will insert a blank horizontal space of =X= pixels.
For example, to add a blank horizontal space of 123 pixels,
@@ -284,6 +448,37 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
See the subsections below for more information on ~<box/>~,
~<icon/>~ and ~<action/>~.
+ - The special characters =}= and ={= are used to delimit up to three sections
+ in the bar that are drawn and aligned independently. See [[#bar-sections][this section]]
+ for more.
+
+*** Bar sections
+ :PROPERTIES:
+ :CUSTOM_ID: bar-sections
+ :END:
+
+ You can use the special characters =}= and ={= are used to delimit up to three
+ sections in the bar, which are aligned and, if needed, overlapped
+ according to these rules:
+
+ - If the template has the form =L}M{R=, with L, R, M arbitrary specs, the
+ monitors in =L= are drawn first, aligned to the left, then =R=, aligned to
+ the right, and finally =M= is drawn centered in the bar. =R= is trimmed to
+ the space left by =L=, and =M= is trimmed to the space left by =L= and =R=. As
+ a particular case, =}M{= will draw a single segment centered in the bar.
+
+ - If the template has the form =L}{R=, =L= is drawn aligned to the left first
+ and then =R=, aligned to the right and trimmed if needed to fit in the
+ space left by =L=.
+
+ - If the template has the form =}L{R=, =R= is drawn first, aligned to the
+ right, and then =L=, aligned to the left and trimmed to the space left by
+ =R=.
+
+ When needed, sections are always trimmed on the right. The section
+ delimiters can be changed using the configuration option =alignSep,= a
+ two-character string.
+
*** Boxes around text
- =<box>string</box>= will print string surrounded by a box in the
@@ -319,7 +514,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
types, colors and widths are valid too, but margins and offsets
are ignored.
-*** Bitmap Icons
+*** Bitmap icons
It's possible to insert in the global templates icon directives of the
form:
@@ -344,7 +539,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
Icons are ignored when xmobar is run in text output mode.
-*** Action Directives
+*** Mouse actions
It's also possible to use action directives of the form:
@@ -359,46 +554,6 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
Actions work also when xmobar is run in text mode and used as
the status command of swaybar.
-** The =commands= configuration option
-
- The =commands= configuration option is a list of commands information
- and arguments to be used by xmobar when parsing the output template.
- Each member of the list consists in a command prefixed by the =Run=
- keyword. Each command has arguments to control the way xmobar is going
- to execute it.
-
- The option consists in a list of commands separated by a comma and
- enclosed by square parenthesis.
-
- Example:
-
- #+begin_src haskell
- [Run Memory ["-t","Mem: <usedratio>%"] 10, Run Swap [] 10]
- #+end_src
-
- to run the Memory monitor plugin with the specified template, and the
- swap monitor plugin, with default options, every second. And here's an
- example of a template for the commands above using an icon:
-
- #+begin_src haskell
- template = "<icon=/home/jao/.xmobar/mem.xbm/><memory> <swap>"
- #+end_src
-
- This example will run "xclock" command when date is clicked:
-
- #+begin_src haskell
- template = "<action=`xclock`>%date%</action>"
- #+end_src
-
- The only internal available command is =Com= (see below Executing
- External Commands). All other commands are provided by plugins. xmobar
- comes with some plugins, providing a set of system monitors, a standard
- input reader, an Unix named pipe reader, a configurable date plugin, and
- much more: we list all available plugins below.
-
- Other commands can be created as plugins with the Plugin infrastructure.
- See below.
-
* Runtime behaviour
** Running xmobar in text mode
:PROPERTIES:
@@ -430,7 +585,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
Other options are ~Ansi~, ~Pango~, and ~Swaybar~.
** Showing xmobar output in Emacs tab or mode line
Using xmobar's ANSI color text ouput, one can plug it inside Emacs, and
- display your monitors in the mode line or the tab bar. The [[../etc/xmobar.el][xmobar.el
+ display your monitors in the mode line or the tab bar. The [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.el][xmobar.el
package]] provides a simple way of doing it.
** Using xmobar in wayland with swaybar or waybar
:PROPERTIES:
@@ -474,7 +629,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
dynamically xmobar's size and run it alongside a system tray widget such
as trayer or stalonetray (although the idea is not limited to trays,
really). For your convenience, there is a version of Jonas' script in
- [[../etc/padding-icon.sh][etc/padding-icon.sh]].
+ [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/padding-icon.sh][etc/padding-icon.sh]].
** Signal handling
@@ -484,10 +639,10 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you
- After receiving ~SIGUSR2~ xmobar repositions itself on the current
screen.
-* The DBus Interface
+* The DBus interface
When compiled with the optional =with_dbus= flag, xmobar can be controlled
- over dbus. All signals defined in [[../src/Xmobar/System/Signal.hs][src/Signal.hs]] as =data SignalType= can now
+ over dbus. All signals defined in [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/System/Signal.hs][src/Signal.hs]] as =data SignalType= can now
be sent over dbus to xmobar.
Due to current limitations of the implementation only one process of xmobar
diff --git a/doc/using-haskell.org b/doc/using-haskell.org
index 4020557..9fd3d88 100644
--- a/doc/using-haskell.org
+++ b/doc/using-haskell.org
@@ -26,7 +26,7 @@
config :: Config
config =
defaultConfig
- { font = "xft:Terminus-8",
+ { font = "DejaVu Sans Mono 9",
allDesktops = True,
alpha = 200,
commands =
@@ -40,7 +40,7 @@
}
main :: IO ()
- main = xmobar config
+ main = xmobar config -- or: configFromArgs config >>= xmobar
#+end_src
You can then for instance run =ghc --make xmobar.hs= to create a new xmobar
@@ -49,6 +49,14 @@
system-wide xmobar, it will notice that you have your own implementation
and (re)compile and run it as needed.
+* Using dynamic linking
+
+ Setting the =with_shared= flag, which is off by default, enables (re)building
+ of xmobar with shared libraries. By default, =xmobar= rebuilds itself with
+ static linking, as is the common practice with Haskell programs, but some
+ distributions use dynamic linking in their packages, or you might also be so
+ inclined. If so, this is your flag.
+
* Writing a plugin
:PROPERTIES:
:CUSTOM_ID: writing-a-plugin
@@ -75,8 +83,8 @@
=run= can be used for simpler plugins. If you define only =run= the plugin
will be run every second. To overwrite this default you just need to
implement =rate=, which must return the number of tenth of seconds between
- every successive runs. See [[../etc/xmobar.hs][etc/xmobar.hs]] for an example of a plugin
- that runs just once, and [[../src/Xmobar/Plugins/Date.hs][src/Xmobar/Plugins/Date.hs]] for one that
+ every successive runs. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.hs][etc/xmobar.hs]] for an example of a plugin
+ that runs just once, and [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/Plugins/Date.hs][src/Xmobar/Plugins/Date.hs]] for one that
implements =rate=.
Notice that Date could be implemented as:
@@ -107,14 +115,14 @@
If your plugin only implements =alias= and =start=, then it is advisable to
put it into the =Xmobar/Plugins/Monitors= directory and use one of the many
- =run*= functions in [[../src/Xmobar/Plugins/Monitors/Common/Run.hs][Xmobar.Plugins.Monitors.Run]] in order to define
- =start=. The =Exec= instance should then live in [[../src/Xmobar/Plugins/Monitors.hs][Xmobar.Plugins.Monitors]].
+ =run*= functions in [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/Plugins/Monitors/Common/Run.hs][Xmobar.Plugins.Monitors.Run]] in order to define
+ =start=. The =Exec= instance should then live in [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/Plugins/Monitors.hs][Xmobar.Plugins.Monitors]].
* Using a plugin
To use your new plugin, you just need to use a pure Haskell configuration
for xmobar (as explained [[#xmobar-in-haskell][above]]) and load your definitions in your =xmobar.hs=
- file. You can see an example in [[../etc/xmobar.hs][etc/xmobar.hs]] showing you how to write
+ file. You can see an example in [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.hs][etc/xmobar.hs]] showing you how to write
a Haskell configuration that uses a new plugin, all in one file.
When xmobar runs with the full path to that Haskell file as its argument
diff --git a/readme.org b/readme.org
index f9226e9..0db5051 100644
--- a/readme.org
+++ b/readme.org
@@ -26,9 +26,27 @@ output, in a variety of formats.
[[file:doc/screenshots/xmobar-exwm.png]]
-Check [[./changelog.md][the change log]] for our release history. We also have an IRC
+Check [[https://codeberg.org/xmobar/xmobar/src/branch/master/changelog.md][the change log]] for our release history. We also have an IRC
channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]].
+* Breaking news
+
+ - Starting with version 0.47.1, we are excluding MPD from the extensions
+ included with ~all_extensions~ when GHC version is 9.4 or greater, because
+ that seems to break cabal compilation. However, it's been reported that
+ in some installations compilation with ~libmpd~ works fine: just add
+ explicitly the ~with_mpd~ flag to include MPD and check for yourself.
+ Compilation with stack has also been reported to work. Please see the
+ comments in issue #679 for details.
+ - Starting with version 0.45, we use cairo/pango as our drawing engine
+ (instead of plain X11/Xft). From a user's point of view, that change
+ should be mostly transparent, except for the facts that it's allowed
+ fixing quite a few bugs and that your /font names/ in your configuration, if
+ you used ~xft~ ones, might need to be adapted to Pango's syntax: please see
+ [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org#fonts][this section of the documentation]] for all the details. If you're
+ compiling your own xmobar, there's a new dependency on libpango (see
+ [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#c-libraries][C library dependencies]]).
+
* Installation
:PROPERTIES:
:CUSTOM_ID: installation
@@ -64,10 +82,15 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]].
emerge --ask xmobar
#+end_src
+ - FreeBSD
+ #+begin_src shell
+ pkg install hs-xmobar
+ #+end_src
+
** Using cabal or stack
Xmobar is available from [[http://hackage.haskell.org/package/xmobar/][Hackage]], and you can compile and install it using
- =cabal-install=, making sure the [[doc/compiling.org#c-libraries][required C libraries]] are in place. For a
+ =cabal-install=, making sure the [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#c-libraries][required C libraries]] are in place. For a
full build with all available extensions:
#+begin_src shell
@@ -82,10 +105,10 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]].
Starting with version 0.35.1, xmobar requires at least GHC version
8.4.x. to build. See [[https://codeberg.org/xmobar/xmobar/issues/461][this issue]] for more information.
- See [[file:doc/compiling.org#optional-features][here]] for a list of optional compilation flags that will enable some
+ See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#optional-features][here]] for a list of optional compilation flags that will enable some
optional plugins.
- See [[file:doc/compiling.org][compiling]] for full compilation instructions starting from source.
+ See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org][compiling]] for full compilation instructions starting from source.
* Running xmobar
** Running xmobar with a configuration file
@@ -106,7 +129,7 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]].
or =~/.xmobarrc=.
All the available command line switches and configuration parameters are
- described in [[file:quick-start.org][the quick start guide]] and [[file:doc/plugins.org][the plugins index]].
+ described in [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org][the quick start guide]] and [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][the plugins index]].
** Writing your own xmobar in Haskell
@@ -116,7 +139,7 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]].
Haskell instead of using a configuration file. (This is very similar to
how [[http://xmonad.org][xmonad]] works.) That gives you the ability of using Haskell and its
libraries to extend xmobar to your heart's content. If you are a
- programmer, take a look [[file:doc/using-haskell.org][here]] to learn more.
+ programmer, take a look [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/using-haskell.org][here]] to learn more.
** Running xmobar in text mode
@@ -124,63 +147,62 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]].
it is possible to redirect xmobar's output to the standard output,
optionally with color escape sequences. In this mode, xmobar can be run
inside a terminal o console, or its output piped to other applications, and
- there is no need for an X11 display. See [[./doc/quick-start.org#text-mode][Running xmobar in text mode]] for
- details. Using this mode, you could [[file:doc/quick-start.org#wayland][pipe xmobar's output to, say, swaybar]],
- and use it in wayland, or, with the [[./etc/xmobar.el][xmobar.el]] package, show it in Emacs's
+ there is no need for an X11 display. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org#text-mode][Running xmobar in text mode]] for
+ details. Using this mode, you could [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org#wayland][pipe xmobar's output to, say, swaybar]],
+ and use it in wayland, or, with the [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.el][xmobar.el]] package, show it in Emacs's
tab bar.
* Configuration and further documentation
- If you want to jump straight into running xmobar, head over to the
- [[./doc/quick-start.org][quick start guide]].
+ [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org][quick start guide]].
- If you want to get a detailed overview of all available plugins and
- monitors, visit the [[./doc/plugins.org][plugins index]].
+ monitors, visit the [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][plugins index]].
- For more information on how to use xmobar as a Haskell library see the
- [[file:doc/using-haskell.org][using Haskell guide]].
+ [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/using-haskell.org][using Haskell guide]].
- If you want to know how to contribute to the xmobar project, check out
- [[contributing.org][contributing]].
+ [[https://codeberg.org/xmobar/xmobar/src/branch/master/contributing.org][contributing]].
* Authors and credits
- Andrea Rossato originally designed and implemented xmobar up to
- version 0.11.1. Since then, it is maintained and developed by [[https://jao.io][jao]],
- with the help of the greater xmobar and Haskell communities.
-
- In particular, xmobar incorporates patches by Mohammed Alshiekh,
- Alex Ameen, Axel Angel, Dhananjay Balan, Claudio Bley, Dragos Boca,
- Ben Boeckel, Ivan Brennan, Duncan Burke, Roman Cheplyaka, Patrick
- Chilton, Antoine Eiche, Nathaniel Wesley Filardo, Guy Gastineau,
- John Goerzen, Patrick Günther, Reto Hablützel, Juraj Hercek, Tomáš
- Janoušek, Ada Joule, Spencer Janssen, Roman Joost, Pavel Kalugin,
- Jochen Keil, Sam Kirby, Lennart Kolmodin, Krzysztof Kosciuszkiewicz,
- Dmitry Kurochkin, Todd Lunter, Vanessa McHale, Robert J. Macomber,
- Dmitry Malikov, David McLean, Joan MIlev, Marcin Mikołajczyk, Dino
- Morelli, Tony Morris, Eric Mrak, Thiago Negri, Edward O'Callaghan,
- Svein Ove, Martin Perner, Jens Petersen, Alexander Polakov, Sibi
- Prabakaran, Pavan Rikhi, Petr Rockai, Andrew Emmanuel Rosa,
- Sackville-West, Amir Saeid, Markus Scherer, Daniel Schüssler,
- Olivier Schneider, Alexander Shabalin, Valentin Shirokov, Peter
- Simons, Alexander Solovyov, Will Song, John Soo, John Soros, Felix
- Springer, Travis Staton, Artem Tarasov, Samuli Thomasson, Edward
- Tjörnhammar, Sergei Trofimovich, Thomas Tuegel, John Tyree, Jan
- Vornberger, Anton Vorontsov, Daniel Wagner, Zev Weiss, Phil Xiaojun
- Hu, Nikolay Yakimov, Edward Z. Yang, Leo Zhang, Norbert Zeh, and
- Michał Zielonka.
-
- Andrea wants to thank Robert Manea and Spencer Janssen for their
- help in understanding how X works. They gave him suggestions on how
- to solve many problems with xmobar. He also thanks Claus Reinke for
- making him understand existential types (or at least for letting him
- think he grasps existential types...;-).
+ Andrea Rossato originally designed and implemented xmobar up to version
+ 0.11.1. Since then, it is maintained and developed by [[https://jao.io][jao]], with the help of
+ the greater xmobar and Haskell communities.
+
+ In particular, xmobar incorporates patches by Kostas Agnantis, Mohammed
+ Alshiekh, Alex Ameen, Axel Angel, Enrico Maria De Angelis, Dhananjay Balan,
+ Claudio Bley, Dragos Boca, Ben Boeckel, Ivan Brennan, Duncan Burke, Roman
+ Cheplyaka, Patrick Chilton, Antoine Eiche, Nathaniel Wesley Filardo, Guy
+ Gastineau, John Goerzen, Jonathan Grochowski, Patrick Günther, Reto
+ Hablützel, Corey Halpin, Juraj Hercek, Jaroslaw Jantura, Tomáš Janoušek, Ada
+ Joule, Spencer Janssen, Roman Joost, Pavel Kalugin, Jochen Keil, Sam Kirby,
+ Lennart Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry Kurochkin, Todd Lunter,
+ Vanessa McHale, Robert J. Macomber, Dmitry Malikov, David McLean, Ulrik de
+ Muelenaere, Joan Milev, Marcin Mikołajczyk, Dino Morelli, Tony Morris, Eric
+ Mrak, Thiago Negri, Edward O'Callaghan, Svein Ove, Martin Perner, Jens
+ Petersen, Alexander Polakov, Sibi Prabakaran, Pavan Rikhi, Petr Rockai,
+ Andrew Emmanuel Rosa, Sackville-West, Amir Saeid, Markus Scherer, Daniel
+ Schüssler, Olivier Schneider, Alexander Shabalin, Valentin Shirokov, Peter
+ Simons, Alexander Solovyov, Will Song, John Soo, John Soros, Felix Springer,
+ Travis Staton, Artem Tarasov, Samuli Thomasson, Edward Tjörnhammar, Sergei
+ Trofimovich, Thomas Tuegel, John Tyree, Jan Vornberger, Anton Vorontsov,
+ Daniel Wagner, Zev Weiss, Phil Xiaojun Hu, Nikolay Yakimov, Edward Z. Yang,
+ Leo Zhang, Norbert Zeh, and Michał Zielonka.
+
+ Andrea wants to thank Robert Manea and Spencer Janssen for their help in
+ understanding how X works. They gave him suggestions on how to solve many
+ problems with xmobar. He also thanks Claus Reinke for making him understand
+ existential types (or at least for letting him think he grasps existential
+ types...;-).
* License
This software is released under a BSD-style license. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/license][license]] for more
details.
- Copyright © 2010-2022 Jose Antonio Ortega Ruiz
+ Copyright © 2010-2024 Jose Antonio Ortega Ruiz
Copyright © 2007-2010 Andrea Rossato
diff --git a/src/Xmobar/App/Compile.hs b/src/Xmobar/App/Compile.hs
index 80dbac7..5d1f48d 100644
--- a/src/Xmobar/App/Compile.hs
+++ b/src/Xmobar/App/Compile.hs
@@ -20,20 +20,17 @@
module Xmobar.App.Compile(recompile, trace, xmessage) where
import Control.Monad.IO.Class
-import Control.Monad.Fix (fix)
-import Control.Exception.Extensible (try, bracket, SomeException(..))
+import Control.Exception.Extensible (bracket, SomeException(..))
import qualified Control.Exception.Extensible as E
import Control.Monad (filterM, when)
import Data.List ((\\))
-import Data.Maybe (isJust)
import System.FilePath((</>), takeExtension)
import System.IO
import System.Directory
import System.Process
import System.Exit
-import System.Posix.Process(executeFile, forkProcess, getAnyProcessStatus)
+import System.Posix.Process(executeFile, forkProcess)
import System.Posix.Types(ProcessID)
-import System.Posix.Signals
isExecutable :: FilePath -> IO Bool
isExecutable f =
@@ -144,14 +141,12 @@ recompile confDir dataDir execName force verb = liftIO $ do
else shouldRecompile verb src bin lib
if sc
then do
- uninstallSignalHandlers
status <- bracket (openFile err WriteMode) hClose $
\errHandle ->
waitForProcess =<<
if useScript
then runScript script bin confDir errHandle
else runGHC bin confDir errHandle
- installSignalHandlers
if status == ExitSuccess
then trace verb "Xmobar recompilation process exited with success!"
else do
@@ -168,24 +163,9 @@ recompile confDir dataDir execName force verb = liftIO $ do
#ifdef RTSOPTS
++ ["-rtsopts", "-with-rtsopts", "-V0"]
#endif
+#ifdef SHARED_LIBRARIES
+ ++ ["-dynamic"]
+#endif
++ ["-o", bin]
runGHC bin = runProc "ghc" (opts bin)
runScript script bin = runProc script [bin]
-
--- | Ignore SIGPIPE to avoid termination when a pipe is full, and SIGCHLD to
--- avoid zombie processes, and clean up any extant zombie processes.
-installSignalHandlers :: MonadIO m => m ()
-installSignalHandlers = liftIO $ do
- installHandler openEndedPipe Ignore Nothing
- installHandler sigCHLD Ignore Nothing
- (try :: IO a -> IO (Either SomeException a))
- $ fix $ \more -> do
- x <- getAnyProcessStatus False False
- when (isJust x) more
- return ()
-
-uninstallSignalHandlers :: MonadIO m => m ()
-uninstallSignalHandlers = liftIO $ do
- installHandler openEndedPipe Default Nothing
- installHandler sigCHLD Default Nothing
- return ()
diff --git a/src/Xmobar/App/Config.hs b/src/Xmobar/App/Config.hs
index a284973..5c2f362 100644
--- a/src/Xmobar/App/Config.hs
+++ b/src/Xmobar/App/Config.hs
@@ -67,6 +67,7 @@ defaultConfig =
, signal = SignalChan Nothing
, textOutput = False
, textOutputFormat = Plain
+ , dpi = 96.0
}
-- | Return the path to the xmobar data directory. This directory is
diff --git a/src/Xmobar/App/Opts.hs b/src/Xmobar/App/Opts.hs
index 3a6b4e7..36da745 100644
--- a/src/Xmobar/App/Opts.hs
+++ b/src/Xmobar/App/Opts.hs
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.App.Opts
--- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz
+-- Copyright: (c) 2018, 2019, 2020, 2022, 2023, 2024 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
@@ -52,6 +52,7 @@ data Opts = Help
| Position String
| WmClass String
| WmName String
+ | Dpi String
deriving (Show, Eq)
options :: [OptDescr Opts]
@@ -95,6 +96,8 @@ options =
"On which X screen number to start"
, Option "p" ["position"] (ReqArg Position "position")
"Specify position of xmobar. Same syntax as in config file"
+ , Option "D" ["dpi"] (ReqArg Dpi "dpi")
+ "The DPI scaling factor. Default 96.0"
]
getOpts :: [String] -> IO ([Opts], [String])
@@ -113,7 +116,7 @@ usage = usageInfo header options ++ footer
info :: String
info = "xmobar " ++ showVersion version
- ++ "\n (C) 2010 - 2022 Jose A Ortega Ruiz"
+ ++ "\n (C) 2010 - 2024 Jose A Ortega Ruiz"
++ "\n (C) 2007 - 2010 Andrea Rossato\n "
++ mail ++ "\n" ++ license ++ "\n"
@@ -161,6 +164,7 @@ doOpts conf (o:oo) =
Right x -> doOpts' (conf {commands = commands conf ++ x})
Left e -> putStr (e ++ usage) >> exitWith (ExitFailure 1)
Position s -> readPosition s
+ Dpi d -> doOpts' (conf {dpi = read d})
where readCom c str =
case readStr str of
[x] -> Right x
diff --git a/src/Xmobar/Config/Parse.hs b/src/Xmobar/Config/Parse.hs
index 16af3db..0b41267 100644
--- a/src/Xmobar/Config/Parse.hs
+++ b/src/Xmobar/Config/Parse.hs
@@ -19,7 +19,8 @@
module Xmobar.Config.Parse(readConfig
, parseConfig
, indexedFont
- , indexedOffset) where
+ , indexedOffset
+ , colorComponents) where
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Number (int)
@@ -31,6 +32,14 @@ import Xmobar.Config.Types
import qualified System.IO as S (readFile)
+-- | Splits a colors string into its two components
+colorComponents :: Config -> String -> (String, String)
+colorComponents conf c =
+ case break (==',') c of
+ (f,',':b) -> (f, b)
+ (f, _) -> (f, bgColor conf)
+
+
stripComments :: String -> String
stripComments =
unlines . map (drop 5 . strip False . (replicate 5 ' '++)) . lines
@@ -63,7 +72,7 @@ parseConfig defaultConfig =
<|?> pAllDesktops <|?> pOverrideRedirect <|?> pPickBroadest
<|?> pLowerOnStart <|?> pPersistent <|?> pIconRoot
<|?> pCommands <|?> pSepChar <|?> pAlignSep <|?> pTemplate
- <|?> pVerbose <|?> pSignal
+ <|?> pVerbose <|?> pSignal <|?> pDpi
fields = [ "font", "additionalFonts", "bgColor", "fgColor"
, "wmClass", "wmName", "sepChar"
@@ -72,7 +81,7 @@ parseConfig defaultConfig =
, "allDesktops", "overrideRedirect", "pickBroadest"
, "hideOnStart", "lowerOnStart", "persistent", "iconRoot"
, "alpha", "commands", "verbose", "signal", "textOutput"
- , "textOutputFormat"
+ , "textOutputFormat", "dpi"
]
pTextOutput = readField textOutput "textOutput"
@@ -103,6 +112,7 @@ parseConfig defaultConfig =
pIconRoot = readField iconRoot "iconRoot"
pAlpha = readField alpha "alpha"
pVerbose = readField verbose "verbose"
+ pDpi = readField dpi "dpi"
pSignal = field signal "signal" $
fail "signal is meant for use with Xmobar as a library.\n It is not meant for use in the configuration file."
diff --git a/src/Xmobar/Config/Template.hs b/src/Xmobar/Config/Template.hs
new file mode 100644
index 0000000..ad30c3d
--- /dev/null
+++ b/src/Xmobar/Config/Template.hs
@@ -0,0 +1,188 @@
+------------------------------------------------------------------------------
+-- |
+-- Module: Xmobar.Config.Template
+-- Copyright: (c) 2022 jao
+-- License: BSD3-style (see LICENSE)
+--
+-- Maintainer: mail@jao.io
+-- Stability: unstable
+-- Portability: portable
+-- Created: Fri Sep 30, 2022 06:33
+--
+--
+-- Parsing template strings
+--
+------------------------------------------------------------------------------
+
+
+module Xmobar.Config.Template (parseString) where
+
+import Data.Maybe (fromMaybe)
+import qualified Control.Monad as CM
+
+import Text.Parsec ((<|>))
+import Text.Read (readMaybe)
+
+import qualified Text.Parsec as P
+import qualified Text.Parsec.Combinator as C
+
+import Text.ParserCombinators.Parsec (Parser)
+
+import qualified Xmobar.Config.Types as T
+
+type Context = (T.TextRenderInfo, T.FontIndex, Maybe [T.Action])
+
+retSegment :: Context -> T.Widget -> Parser [T.Segment]
+retSegment (i, idx, as) widget = return [(widget, i, idx, as)]
+
+-- | Run the template string parser for the given config, producing a list of
+-- drawable segment specifications.
+parseString :: T.Config -> String -> [T.Segment]
+parseString c s =
+ case P.parse (stringParser ci) "" s of
+ Left _ -> [(T.Text $ "Could not parse string: " ++ s, ti, 0, Nothing)]
+ Right x -> concat x
+ where ci = (ti , 0, Nothing)
+ ti = T.TextRenderInfo (T.fgColor c) 0 0 []
+
+-- Top level parser reading the full template string
+stringParser :: Context -> Parser [[T.Segment]]
+stringParser c = C.manyTill (allParsers c) C.eof
+
+allParsers :: Context -> Parser [T.Segment]
+allParsers c = C.choice (textParser c:map (\f -> P.try (f c)) parsers)
+ where parsers = [ iconParser, hspaceParser, rawParser, actionParser
+ , fontParser, boxParser, colorParser ]
+
+-- Wrapper for notFollowedBy that returns the result of the first parser.
+-- Also works around the issue that, at least in Parsec 3.0.0, notFollowedBy
+-- accepts only parsers with return type Char.
+notFollowedBy' :: Parser a -> Parser b -> Parser a
+notFollowedBy' p e = do x <- p
+ C.notFollowedBy $ P.try (e >> return '*')
+ return x
+
+-- Parse a maximal string without markup
+textParser :: Context -> Parser [T.Segment]
+textParser c =
+ C.many1 (P.noneOf "<" <|> P.try (notFollowedBy' (P.char '<') suffixes))
+ >>= retSegment c . T.Text
+ where suffixes = C.choice $ map (P.try . P.string)
+ [ "icon=" , "hspace=", "raw="
+ , "action=", "/action>", "fn=", "/fn>"
+ , "box", "/box>", "fc=", "/fc>" ]
+
+-- Parse a "raw" tag, which we use to prevent other tags from creeping in.
+-- The format here is net-string-esque: a literal "<raw=" followed by a string
+-- of digits (base 10) denoting the length of the raw string, a literal ":" as
+-- digit-string-terminator, the raw string itself, and then a literal "/>".
+rawParser :: Context -> Parser [T.Segment]
+rawParser c = do
+ P.string "<raw="
+ lenstr <- C.many1 P.digit
+ P.char ':'
+ case reads lenstr of
+ [(len,[])] -> do
+ CM.guard ((len :: Integer) <= fromIntegral (maxBound :: Int))
+ s <- C.count (fromIntegral len) P.anyChar
+ P.string "/>"
+ retSegment c (T.Text s)
+ _ -> CM.mzero
+
+iconParser :: Context -> Parser [T.Segment]
+iconParser c = do
+ P.string "<icon="
+ i <- C.manyTill (P.noneOf ">") (P.try (P.string "/>"))
+ retSegment c (T.Icon i)
+
+hspaceParser :: Context -> Parser [T.Segment]
+hspaceParser c = do
+ P.string "<hspace="
+ pVal <- C.manyTill P.digit (P.try (P.string "/>"))
+ retSegment c (T.Hspace (fromMaybe 0 $ readMaybe pVal))
+
+actionParser :: Context -> Parser [T.Segment]
+actionParser (ti, fi, act) = do
+ P.string "<action="
+ command <- C.between (P.char '`') (P.char '`') (C.many1 (P.noneOf "`"))
+ <|> C.many1 (P.noneOf ">")
+ buttons <- (P.char '>' >> return "1") <|> (P.space >> P.spaces >>
+ C.between (P.string "button=") (P.string ">") (C.many1 (P.oneOf "12345")))
+ let a = T.Spawn (toButtons buttons) command
+ a' = case act of
+ Nothing -> Just [a]
+ Just act' -> Just $ a : act'
+ s <- C.manyTill (allParsers (ti, fi, a')) (P.try $ P.string "</action>")
+ return (concat s)
+
+toButtons :: String -> [T.Button]
+toButtons = map (\x -> read [x])
+
+colorParser :: Context -> Parser [T.Segment]
+colorParser (T.TextRenderInfo _ _ _ bs, fidx, a) = do
+ c <- C.between (P.string "<fc=") (P.string ">") (C.many1 colorc)
+ let colorParts = break (==':') c
+ let (ot,ob) = case break (==',') (drop 1 $ snd colorParts) of
+ (top,',':btm) -> (top, btm)
+ (top, _) -> (top, top)
+ tri = T.TextRenderInfo (fst colorParts)
+ (fromMaybe (-1) $ readMaybe ot)
+ (fromMaybe (-1) $ readMaybe ob)
+ bs
+ s <- C.manyTill (allParsers (tri, fidx, a)) (P.try $ P.string "</fc>")
+ return (concat s)
+ where colorc = P.alphaNum <|> P.oneOf ",:#"
+
+boxParser :: Context -> Parser [T.Segment]
+boxParser (T.TextRenderInfo cs ot ob bs, f, a) = do
+ c <- C.between (P.string "<box") (P.string ">")
+ (C.option "" (C.many1 (P.alphaNum <|> P.oneOf "= #,")))
+ let b = T.Box T.BBFull (T.BoxOffset T.C 0) 1 cs (T.BoxMargins 0 0 0 0)
+ let g = boxReader b (words c)
+ s <- C.manyTill
+ (allParsers (T.TextRenderInfo cs ot ob (g : bs), f, a))
+ (P.try $ P.string "</box>")
+ return (concat s)
+
+boxReader :: T.Box -> [String] -> T.Box
+boxReader b [] = b
+boxReader b (x:xs) = boxReader (boxParamReader b param val) xs
+ where (param,val) = case break (=='=') x of
+ (p,'=':v) -> (p, v)
+ (p, _) -> (p, "")
+
+boxParamReader :: T.Box -> String -> String -> T.Box
+boxParamReader b _ "" = b
+
+boxParamReader (T.Box bb off lw fc mgs) "type" val =
+ T.Box (fromMaybe bb $ readMaybe ("BB" ++ val)) off lw fc mgs
+
+boxParamReader (T.Box bb (T.BoxOffset alg off) lw fc mgs) "offset" (a:o) =
+ T.Box bb (T.BoxOffset align offset) lw fc mgs
+ where offset = fromMaybe off $ readMaybe o
+ align = fromMaybe alg $ readMaybe [a]
+
+boxParamReader (T.Box bb off lw fc mgs) "width" val =
+ T.Box bb off (fromMaybe lw $ readMaybe val) fc mgs
+
+boxParamReader (T.Box bb off lw _ mgs) "color" val =
+ T.Box bb off lw val mgs
+
+boxParamReader (T.Box bb off lw fc mgs@(T.BoxMargins mt mr mb ml)) ('m':pos) v =
+ let mgs' = case pos of
+ "t" -> T.BoxMargins (maybeVal mt) mr mb ml
+ "r" -> T.BoxMargins mt (maybeVal mr) mb ml
+ "b" -> T.BoxMargins mt mr (maybeVal mb) ml
+ "l" -> T.BoxMargins mt mr mb (maybeVal ml)
+ _ -> mgs
+ maybeVal d = fromMaybe d (readMaybe v)
+ in T.Box bb off lw fc mgs'
+
+boxParamReader b _ _ = b
+
+fontParser :: Context -> Parser [T.Segment]
+fontParser (i, _, a) = do
+ f <- C.between (P.string "<fn=") (P.string ">") (C.many1 P.digit)
+ s <- C.manyTill (allParsers (i, fromMaybe 0 $ readMaybe f, a))
+ (P.try $ P.string "</fn>")
+ return (concat s)
diff --git a/src/Xmobar/Config/Types.hs b/src/Xmobar/Config/Types.hs
index 4959aa1..785b55b 100644
--- a/src/Xmobar/Config/Types.hs
+++ b/src/Xmobar/Config/Types.hs
@@ -15,14 +15,28 @@
module Xmobar.Config.Types
( Config (..)
, XPosition (..), Align (..), Border (..), TextOutputFormat (..)
+ , Segment
, FontIndex
+ , Box(..)
+ , BoxBorder(..)
+ , BoxOffset(..)
+ , BoxMargins(..)
+ , TextRenderInfo(..)
+ , Widget(..)
, SignalChan (..)
+ , Action (..)
+ , Button
) where
import qualified Control.Concurrent.STM as STM
import qualified Xmobar.Run.Runnable as R
import qualified Xmobar.System.Signal as S
+import Data.Int (Int32)
+import Foreign.C.Types (CInt)
+
+import Xmobar.Run.Actions (Action (..), Button)
+
-- $config
-- Configuration data type
@@ -71,20 +85,94 @@ data Config =
, template :: String -- ^ The output template
, verbose :: Bool -- ^ Emit additional debug messages
, signal :: SignalChan -- ^ Channel to send signals to xmobar
+ , dpi :: Double -- ^ DPI scaling factor for fonts
} deriving (Read, Show)
-data XPosition = Top
- | TopH Int
- | TopW Align Int
- | TopSize Align Int Int
- | TopP Int Int
+-- | The position datatype
+data XPosition = Top -- ^ Top of the screen, full width, auto height
+
+ | TopH -- ^ Top of the screen, full width with
+ -- specific height
+ Int -- ^ Height (in pixels)
+
+ -- | Top of the screen, full width with
+ -- specific height and margins
+ | TopHM
+ Int -- ^ Height (in pixels)
+ Int -- ^ Left margin (in pixels)
+ Int -- ^ Right margin (in pixels)
+ Int -- ^ Top margin (in pixels)
+ Int -- ^ Bottom margin (in pixels)
+
+ -- | Top of the screen with specific width
+ -- (as screen percentage) and alignment
+ | TopW
+ Align -- ^ Alignement (L|C|R)
+ Int -- ^ Width as screen percentage (0-100)
+
+ -- | Top of the screen with specific width
+ -- (as screen percentage), height and
+ -- alignment
+ | TopSize
+ Align -- ^ Alignement (L|C|R)
+ Int -- ^ Width as screen percentage (0-100)
+ Int -- ^ Height (in pixels)
+
+ -- | Top of the screen with specific left/right
+ -- margins
+ | TopP
+ Int -- ^ Left margin (in pixels)
+ Int -- ^ Right margin (in pixels)
+
+ -- | Bottom of the screen, full width, auto height
| Bottom
- | BottomH Int
- | BottomP Int Int
- | BottomW Align Int
- | BottomSize Align Int Int
- | Static {xpos, ypos, width, height :: Int}
- | OnScreen Int XPosition
+
+ | BottomH -- ^ Bottom of the screen, full width, with
+ -- specific height
+ Int -- ^ Height (in pixels)
+
+ -- | Bottom of the screen with specific height
+ -- and margins
+ | BottomHM
+ Int -- ^ Height (in pixels)
+ Int -- ^ Left margin (in pixels)
+ Int -- ^ Right margin (in pixels)
+ Int -- ^ Top margin (in pixels)
+ Int -- ^ Bottom margin (in pixels)
+
+ -- | Bottom of the screen with specific
+ -- left/right margins
+ | BottomP
+ Int -- ^ Left margin (in pixels)
+ Int -- ^ Bottom margin (in pixels)
+
+ -- | Bottom of the screen with specific width
+ -- (as screen percentage) and alignment
+ -- and alignment
+ | BottomW
+ Align -- ^ Alignement (L|C|R)
+ Int -- ^ Width as screen percentage (0-100)
+
+ -- | Bottom of the screen with specific width
+ -- (as screen percentage), height
+ -- and alignment
+ | BottomSize
+ Align -- ^ Alignement (L|C|R)
+ Int -- ^ Width as screen percentage (0-100)
+ Int -- ^ Height (in pixels)
+
+ -- | Static position and specific size
+ | Static { xpos :: Int -- ^ Position X (in pixels)
+ , ypos :: Int -- ^ Position Y (in pixels)
+ , width :: Int -- ^ Width (in pixels)
+ , height :: Int -- ^ Height (in pixels)
+ }
+
+ -- | Along with the position characteristics
+ -- specify the screen to display the bar
+ | OnScreen
+ Int -- ^ Screen id (primary is 0)
+ XPosition -- ^ Position
deriving ( Read, Show, Eq )
data Align = L | R | C deriving ( Read, Show, Eq )
@@ -110,3 +198,34 @@ instance Read SignalChan where
instance Show SignalChan where
show (SignalChan (Just _)) = "SignalChan (Just <tmvar>)"
show (SignalChan Nothing) = "SignalChan Nothing"
+
+data Widget = Icon String | Text String | Hspace Int32 deriving Show
+
+data BoxOffset = BoxOffset Align Int32 deriving (Eq, Show)
+
+-- margins: Top, Right, Bottom, Left
+data BoxMargins = BoxMargins Int32 Int32 Int32 Int32 deriving (Eq, Show)
+
+data BoxBorder = BBTop
+ | BBBottom
+ | BBVBoth
+ | BBLeft
+ | BBRight
+ | BBHBoth
+ | BBFull
+ deriving (Read, Eq, Show)
+
+data Box = Box { bBorder :: BoxBorder
+ , bOffset :: BoxOffset
+ , bWidth :: CInt
+ , bColor :: String
+ , bMargins :: BoxMargins
+ } deriving (Eq, Show)
+
+data TextRenderInfo = TextRenderInfo { tColorsString :: String
+ , tBgTopOffset :: Int32
+ , tBgBottomOffset :: Int32
+ , tBoxes :: [Box]
+ } deriving Show
+
+type Segment = (Widget, TextRenderInfo, FontIndex, Maybe [Action])
diff --git a/src/Xmobar/Draw/Boxes.hs b/src/Xmobar/Draw/Boxes.hs
index 1358805..ff55ab3 100644
--- a/src/Xmobar/Draw/Boxes.hs
+++ b/src/Xmobar/Draw/Boxes.hs
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.X11.Boxes
--- Copyright: (c) 2022 Jose Antonio Ortega Ruiz
+-- Copyright: (c) 2022, 2024 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
@@ -16,7 +16,6 @@
module Xmobar.Draw.Boxes (Line, boxLines, BoxRect, borderRect) where
import qualified Xmobar.Config.Types as T
-import qualified Xmobar.Run.Parsers as P
type Line = (Double, Double, Double, Double)
type BoxRect = (Double, Double, Double, Double)
@@ -25,30 +24,29 @@ type BoxRect = (Double, Double, Double, Double)
-- The Box is to be positioned between x0 and x1, with height ht, and drawn
-- with line width lw. The returned lists are coordinates of the beginning
-- and end of each line.
-boxLines :: P.Box -> Double -> Double -> Double -> [Line]
-boxLines (P.Box bd offset lw _ margins) ht x0 x1 =
+boxLines :: T.Box -> Double -> Double -> Double -> [Line]
+boxLines (T.Box bd offset lw _ margins) ht x0 x1 =
case bd of
- P.BBTop -> [rtop]
- P.BBBottom -> [rbot]
- P.BBVBoth -> [rtop, rbot]
- P.BBLeft -> [rleft]
- P.BBRight -> [rright]
- P.BBHBoth -> [rleft, rright]
- P.BBFull -> [rtop, rbot, rleft, rright]
+ T.BBTop -> [rtop]
+ T.BBBottom -> [rbot]
+ T.BBVBoth -> [rtop, rbot]
+ T.BBLeft -> [rleft]
+ T.BBRight -> [rright]
+ T.BBHBoth -> [rleft, rright]
+ T.BBFull -> [rtop, rbot, rleft, rright]
where
- (P.BoxMargins top right bot left) = margins
- (P.BoxOffset align m) = offset
+ (T.BoxMargins top right bot left) = margins
+ (T.BoxOffset align m) = offset
ma = fromIntegral m
(p0, p1) = case align of
T.L -> (0, -ma)
T.C -> (ma, -ma)
T.R -> (ma, 0)
lc = fromIntegral lw / 2
- [mt, mr, mb, ml] = map fromIntegral [top, right, bot, left]
- xmin = x0 - ml - lc
- xmax = x1 + mr + lc
- ymin = mt + lc
- ymax = ht - mb - lc
+ xmin = x0 - fromIntegral left - lc
+ xmax = x1 + fromIntegral right + lc
+ ymin = fromIntegral top + lc
+ ymax = ht - fromIntegral bot - lc
rtop = (xmin + p0, ymin, xmax + p1, ymin)
rbot = (xmin + p0, ymax, xmax + p1, ymax)
rleft = (xmin, ymin + p0, xmin, ymax + p1)
diff --git a/src/Xmobar/Draw/Cairo.hs b/src/Xmobar/Draw/Cairo.hs
index 7e22df4..2338b10 100644
--- a/src/Xmobar/Draw/Cairo.hs
+++ b/src/Xmobar/Draw/Cairo.hs
@@ -2,7 +2,7 @@
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.X11.Cairo
--- Copyright: (c) 2022 Jose Antonio Ortega Ruiz
+-- Copyright: (c) 2022, 2023, 2024 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
@@ -29,14 +29,13 @@ import Graphics.Rendering.Cairo.Types(Surface)
import qualified Xmobar.Config.Types as C
import qualified Xmobar.Config.Parse as ConfigParse
-import qualified Xmobar.Run.Parsers as P
import qualified Xmobar.Text.Pango as TextPango
import qualified Xmobar.Draw.Boxes as Boxes
import qualified Xmobar.Draw.Types as T
-type Renderinfo = (P.Segment, Surface -> Double -> Double -> IO (), Double)
-type BoundedBox = (Double, Double, [P.Box])
+type Renderinfo = (C.Segment, Surface -> Double -> Double -> IO (), Double)
+type BoundedBox = (Double, Double, [C.Box])
type Acc = (Double, T.Actions, [BoundedBox])
readColourName :: String -> (SRGB.Colour Double, Double)
@@ -63,10 +62,10 @@ renderLines color wd lns = do
mapM_ (\(x0, y0, x1, y1) ->
Cairo.moveTo x0 y0 >> Cairo.lineTo x1 y1 >> Cairo.stroke) lns
-segmentMarkup :: C.Config -> P.Segment -> String
-segmentMarkup conf (P.Text txt, info, idx, _actions) =
+segmentMarkup :: C.Config -> C.Segment -> String
+segmentMarkup conf (C.Text txt, info, idx, _actions) =
let fnt = TextPango.fixXft $ ConfigParse.indexedFont conf idx
- (fg, bg) = P.colorComponents conf (P.tColorsString info)
+ (fg, bg) = ConfigParse.colorComponents conf (C.tColorsString info)
attrs = [Pango.FontDescr fnt, Pango.FontForeground fg]
attrs' = if bg == C.bgColor conf
then attrs
@@ -74,8 +73,8 @@ segmentMarkup conf (P.Text txt, info, idx, _actions) =
in Pango.markSpan attrs' $ Pango.escapeMarkup txt
segmentMarkup _ _ = ""
-withRenderinfo :: Pango.PangoContext -> T.DrawContext -> P.Segment -> IO Renderinfo
-withRenderinfo ctx dctx seg@(P.Text _, inf, idx, a) = do
+withRenderinfo :: Pango.PangoContext -> T.DrawContext -> C.Segment -> IO Renderinfo
+withRenderinfo ctx dctx seg@(C.Text _, inf, idx, a) = do
let conf = T.dcConfig dctx
lyt <- Pango.layoutEmpty ctx
mk <- Pango.layoutSetMarkup lyt (segmentMarkup conf seg) :: IO String
@@ -88,25 +87,28 @@ withRenderinfo ctx dctx seg@(P.Text _, inf, idx, a) = do
Pango.layoutSetEllipsize lyt Pango.EllipsizeEnd
Pango.layoutSetWidth lyt (Just $ mx - off)
Cairo.renderWith s $ Cairo.moveTo off voff >> Pango.showLayout lyt
- return ((P.Text mk, inf, idx, a), slyt, wd)
+ return ((C.Text mk, inf, idx, a), slyt, wd)
-withRenderinfo _ _ seg@(P.Hspace w, _, _, _) =
+withRenderinfo _ _ seg@(C.Hspace w, _, _, _) =
return (seg, \_ _ _ -> return (), fromIntegral w)
-withRenderinfo _ dctx seg@(P.Icon p, _, _, _) = do
+withRenderinfo _ dctx seg@(C.Icon p, info, _, _) = do
let (wd, _) = T.dcIconLookup dctx p
ioff = C.iconOffset (T.dcConfig dctx)
vpos = T.dcHeight dctx / 2 + fromIntegral ioff
- render _ off mx = when (off + wd <= mx) $ T.dcIconDrawer dctx off vpos p
+ conf = T.dcConfig dctx
+ (fg, bg) = ConfigParse.colorComponents conf (C.tColorsString info)
+ render _ off mx = when (off + wd <= mx) $
+ T.dcIconDrawer dctx off vpos p fg bg
return (seg, render, wd)
-drawBox :: T.DrawContext -> Surface -> Double -> Double -> P.Box -> IO ()
-drawBox dctx surf x0 x1 box@(P.Box _ _ w color _) =
+drawBox :: T.DrawContext -> Surface -> Double -> Double -> C.Box -> IO ()
+drawBox dctx surf x0 x1 box@(C.Box _ _ w color _) =
Cairo.renderWith surf $
renderLines color (fromIntegral w) (Boxes.boxLines box (T.dcHeight dctx) x0 x1)
drawSegmentBackground ::
- T.DrawContext -> Surface -> P.TextRenderInfo -> Double -> Double -> IO ()
+ T.DrawContext -> Surface -> C.TextRenderInfo -> Double -> Double -> IO ()
drawSegmentBackground dctx surf info x0 x1 =
when (bg /= C.bgColor conf && (top >= 0 || bot >= 0)) $
Cairo.renderWith surf $ do
@@ -114,19 +116,20 @@ drawSegmentBackground dctx surf info x0 x1 =
Cairo.rectangle x0 top (x1 - x0) (T.dcHeight dctx - bot - top)
Cairo.fillPreserve
where conf = T.dcConfig dctx
- (_, bg) = P.colorComponents conf (P.tColorsString info)
- top = fromIntegral $ P.tBgTopOffset info
- bot = fromIntegral $ P.tBgBottomOffset info
+ (_, bg) = ConfigParse.colorComponents conf (C.tColorsString info)
+ top = fromIntegral $ C.tBgTopOffset info
+ bot = fromIntegral $ C.tBgBottomOffset info
drawSegment :: T.DrawContext -> Surface -> Double -> Acc -> Renderinfo -> IO Acc
drawSegment dctx surface maxoff (off, acts, boxs) (segment, render, lwidth) = do
let end = min maxoff (off + lwidth)
(_, info, _, a) = segment
acts' = case a of Just as -> (as, off, end):acts; _ -> acts
- bs = P.tBoxes info
+ bs = C.tBoxes info
boxs' = if null bs then boxs else (off, end, bs):boxs
- drawSegmentBackground dctx surface info off end
- render surface off maxoff
+ when (end > off) $ do
+ drawSegmentBackground dctx surface info off end
+ render surface off maxoff
return (off + lwidth, acts', boxs')
renderOuterBorder :: C.Config -> Double -> Double -> Cairo.Render ()
@@ -166,25 +169,27 @@ drawCairoBackground dctx surf = do
drawSegments :: T.DrawContext -> Surface -> IO T.Actions
drawSegments dctx surf = do
- let [left, center, right] = take 3 $ T.dcSegments dctx ++ repeat []
+ let segs = take 3 $ T.dcSegments dctx ++ repeat []
dh = T.dcHeight dctx
dw = T.dcWidth dctx
conf = T.dcConfig dctx
sWidth = foldl (\a (_,_,w) -> a + w) 0
ctx <- Pango.cairoCreateContext Nothing
- llyts <- mapM (withRenderinfo ctx dctx) left
- rlyts <- mapM (withRenderinfo ctx dctx) right
- clyts <- mapM (withRenderinfo ctx dctx) center
+ Pango.cairoContextSetResolution ctx $ C.dpi conf
+ llyts <- mapM (withRenderinfo ctx dctx) (head segs)
+ rlyts <- mapM (withRenderinfo ctx dctx) (segs !! 2)
+ clyts <- mapM (withRenderinfo ctx dctx) (segs !! 1)
#ifndef XRENDER
drawCairoBackground dctx surf
#endif
(lend, as, bx) <- foldM (drawSegment dctx surf dw) (0, [], []) llyts
let rw = sWidth rlyts
- rstart = max (lend + 1) (dw - rw - 1)
- cmax = rstart - 1
cw = sWidth clyts
- cstart = lend + 1 + max 0 (dw - rw - lend - cw) / 2.0
- (_, as', bx') <- foldM (drawSegment dctx surf cmax) (cstart, as, bx) clyts
+ rstart = max lend (dw - rw)
+ cstart = if lend > 1 || rw == 0 then max lend ((dw - cw) / 2.0) else lend
+ (_, as', bx') <- if cw > 0
+ then foldM (drawSegment dctx surf rstart) (cstart, as, bx) clyts
+ else return (0, as, bx)
(_, as'', bx'') <- foldM (drawSegment dctx surf dw) (rstart, as', bx') rlyts
drawBoxes dctx surf (reverse bx'')
when (C.borderWidth conf > 0) (drawBorder conf dw dh surf)
diff --git a/src/Xmobar/Draw/Types.hs b/src/Xmobar/Draw/Types.hs
index 75dd714..1a076b3 100644
--- a/src/Xmobar/Draw/Types.hs
+++ b/src/Xmobar/Draw/Types.hs
@@ -17,16 +17,15 @@
module Xmobar.Draw.Types where
-import Xmobar.Config.Types (Config)
+import Xmobar.Config.Types (Config, Segment)
import Xmobar.Run.Actions (Action)
-import Xmobar.Run.Parsers (Segment)
type Position = Double
type ActionPos = ([Action], Position, Position)
type Actions = [ActionPos]
type IconLookup = String -> (Double, Double)
-type IconDrawer = Double -> Double -> String -> IO ()
+type IconDrawer = Double -> Double -> String -> String -> String -> IO ()
data DrawContext = DC { dcIconDrawer :: IconDrawer
, dcIconLookup :: IconLookup
diff --git a/src/Xmobar/Plugins/EWMH.hs b/src/Xmobar/Plugins/EWMH.hs
index 94fd7d7..78f1cc0 100644
--- a/src/Xmobar/Plugins/EWMH.hs
+++ b/src/Xmobar/Plugins/EWMH.hs
@@ -19,6 +19,7 @@ module Xmobar.Plugins.EWMH (EWMH(..)) where
import Control.Applicative (Applicative(..))
import Control.Monad.State
+import Control.Monad
import Control.Monad.Reader
import Graphics.X11 hiding (Modifier, Color)
import Graphics.X11.Xlib.Extras
diff --git a/src/Xmobar/Plugins/Kbd.hs b/src/Xmobar/Plugins/Kbd.hs
index 2214628..3871ca8 100644
--- a/src/Xmobar/Plugins/Kbd.hs
+++ b/src/Xmobar/Plugins/Kbd.hs
@@ -14,9 +14,11 @@
module Xmobar.Plugins.Kbd(Kbd(..)) where
-import Data.List (isPrefixOf)
+import Data.Bifunctor (bimap)
+import Data.List (find, tails, isPrefixOf)
import Data.Maybe (fromMaybe)
-import Data.Char (toLower)
+import Data.Char (toLower, isLetter)
+import Data.Function ((&))
import Control.Monad (forever)
import Control.Applicative ((<|>))
import Graphics.X11.Xlib
@@ -26,6 +28,13 @@ import Xmobar.Run.Exec
import Xmobar.X11.Events (nextEvent')
import Xmobar.System.Kbd
+-- some strong typing
+newtype Lay = Lay String deriving (Eq)
+newtype Sym = Sym String
+instance Show Sym where show (Sym s) = s
+type KbdOpts' = [(Lay, Sym)]
+typed :: [(String, String)] -> [(Lay, Sym)]
+typed = map (bimap Lay Sym)
-- 'Bad' prefixes of layouts
noLaySymbols :: [String]
@@ -49,15 +58,22 @@ split p s = case break p s of
(pref, "") -> [pref]
-- replaces input string if on search list (exact match) with corresponding
--- element on replacement list.
+-- element on replacement list, and returns it paired with the following item
--
--- if not found, return string unchanged
-searchReplaceLayout :: KbdOpts -> String -> String
-searchReplaceLayout opts s = fromMaybe s $ lookup s opts
-
--- returns the active layout
-getKbdLay :: Display -> KbdOpts -> IO String
-getKbdLay dpy opts = do
+-- if not found, return string unchanged, paired with empty string
+searchReplaceLayout :: KbdOpts' -> String -> (Lay, Lay, Sym)
+searchReplaceLayout opts curr
+ = maybe (Lay "", Lay "", Sym curr)
+ pickSymWithAdjLays
+ (find currLayout (tails $ cycle opts))
+ where
+ pickSymWithAdjLays ((l1, _):(_, s):(l2, _):_) = (l1, l2, s)
+ pickSymWithAdjLays _ = error "This should never happen"
+ currLayout = (Lay curr ==) . (!! 1) . map fst
+
+-- returns the active layout and the following one
+getCurAndNextKbdLays :: Display -> KbdOpts' -> IO (Lay, Lay, Sym)
+getCurAndNextKbdLays dpy opts = do
lay <- splitLayout <$> getLayoutStr dpy
grps <- map (map toLower . take 2) <$> getGrpNames dpy
curLay <- getKbdLayout dpy
@@ -73,6 +89,37 @@ getKbdLay dpy opts = do
newtype Kbd = Kbd [(String, String)]
deriving (Read, Show)
+attachClickAction :: (Lay, Lay, Sym) -> Sym
+attachClickAction (Lay prv, Lay nxt, txt) = txt & linkTo nxt `onKey` "1"
+ & linkTo prv `onKey` "3"
+ where
+ splitLayParensPhon :: String -> (String, String, String)
+ splitLayParensPhon = (\(a, (b, c)) -> (a, b, c))
+ . second (second (drop 1) . break (== ')') . drop 1)
+ . break (== '(')
+ parseLayPhon :: String -> (Maybe String, Maybe String)
+ parseLayPhon s = let (l, p, i) = splitLayParensPhon s
+ l' = if all isLetter l
+ then Just ("-layout " ++ l)
+ else Nothing
+ p' = if (p, i) == ("phonetic", "")
+ then Just "-variant phonetic"
+ else Nothing
+ in (l', p')
+ linkTo :: String -> String -> Sym -> Sym
+ linkTo linked button currLay = Sym $ case parseLayPhon linked of
+ (Nothing, _) -> "??"
+ (Just linkedLay, phon) -> wrapIn setxkbmap button currLay
+ where
+ setxkbmap = unwords ["setxkbmap", linkedLay, fromMaybe "" phon]
+ wrapIn :: String -> String -> Sym -> String
+ wrapIn action buttons (Sym sym) = openingTag ++ sym ++ closingTag
+ where
+ openingTag = "<action=`" ++ action ++ "` button=" ++ buttons ++ ">"
+ closingTag = "</action>"
+ onKey = ($)
+ second = fmap
+
instance Exec Kbd where
alias (Kbd _) = "kbd"
start (Kbd opts) cb = do
@@ -80,7 +127,7 @@ instance Exec Kbd where
dpy <- openDisplay ""
-- initial set of layout
- cb =<< getKbdLay dpy opts
+ cb . show . attachClickAction =<< getCurAndNextKbdLays dpy (typed opts)
-- enable listing for
-- group changes
@@ -91,7 +138,6 @@ instance Exec Kbd where
allocaXEvent $ \e -> forever $ do
nextEvent' dpy e
_ <- getEvent e
- cb =<< getKbdLay dpy opts
+ cb . show . attachClickAction =<< getCurAndNextKbdLays dpy (typed opts)
closeDisplay dpy
- return ()
diff --git a/src/Xmobar/Plugins/Kraken.hs b/src/Xmobar/Plugins/Kraken.hs
index 2345b3d..5d565e0 100644
--- a/src/Xmobar/Plugins/Kraken.hs
+++ b/src/Xmobar/Plugins/Kraken.hs
@@ -36,7 +36,7 @@ instance Exec Kraken where
cb (display g)
loop mv g
- loop mvar (Map.fromList $ zip ps (repeat 0.0))
+ loop mvar (Map.fromList $ map (, 0.0) ps)
where
display :: Map.Map String Double -> String
diff --git a/src/Xmobar/Plugins/Locks.hs b/src/Xmobar/Plugins/Locks.hs
index 9176312..35a3f97 100644
--- a/src/Xmobar/Plugins/Locks.hs
+++ b/src/Xmobar/Plugins/Locks.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TupleSections #-}
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Locks
@@ -16,45 +17,70 @@ module Xmobar.Plugins.Locks(Locks(..)) where
import Graphics.X11
import Data.List
+import Data.List.Extra (trim)
import Data.Bits
+import Data.Maybe (fromJust)
import Control.Monad
+import Control.Monad.Extra (ifM)
import Graphics.X11.Xlib.Extras
import Xmobar.Run.Exec
import Xmobar.System.Kbd
import Xmobar.X11.Events (nextEvent')
-data Locks = Locks
+data Locks = Locks | Locks' [(String, (String, String))]
deriving (Read, Show)
locks :: [ ( KeySym, String )]
-locks = [ ( xK_Caps_Lock, "CAPS" )
- , ( xK_Num_Lock, "NUM" )
+locks = [ ( xK_Caps_Lock, "CAPS" )
+ , ( xK_Num_Lock, "NUM" )
, ( xK_Scroll_Lock, "SCROLL" )
]
-run' :: Display -> Window -> IO String
-run' d root = do
+type Labels = [ ( String, (String, String) )]
+defaultLabels :: Labels
+defaultLabels = let nms = map snd locks
+ in zip nms (map (, mempty) nms)
+
+type LabelledLock = (KeySym, String, String, String)
+
+attach :: (KeySym, String) -> Labels -> LabelledLock
+(key, lock) `attach` lbls = let (enb, dis) = fromJust $ lookup lock lbls
+ in (key, lock, enb, dis)
+
+enabled :: (a, b, c, d) -> c
+enabled (_, _, c, _) = c
+disabled :: (a, b, c, d) -> d
+disabled (_, _, _, d) = d
+
+isEnabled :: (Bits a1, Foldable t, Foldable t1, Integral a)
+ => Display -> t (a, t1 KeyCode) -> a1 -> (KeySym, b, c, d) -> IO Bool
+isEnabled d modMap m ( ks, _, _, _ ) = do
+ kc <- keysymToKeycode d ks
+ return $ case find (elem kc . snd) modMap of
+ Nothing -> False
+ Just ( i, _ ) -> testBit m (fromIntegral i)
+
+run' :: Display -> Window -> Labels -> IO String
+run' d root labels = do
modMap <- getModifierMapping d
( _, _, _, _, _, _, _, m ) <- queryPointer d root
- ls <- filterM ( \( ks, _ ) -> do
- kc <- keysymToKeycode d ks
- return $ case find (elem kc . snd) modMap of
- Nothing -> False
- Just ( i, _ ) -> testBit m (fromIntegral i)
- ) locks
-
- return $ unwords $ map snd ls
+ ls' <- forM (map (`attach` labels) locks)
+ (\l -> ifM (isEnabled d modMap m l)
+ (return (enabled l))
+ (return (disabled l)))
+ return $ trim $ unwords ls'
instance Exec Locks where
- alias Locks = "locks"
- start Locks cb = do
+ alias _ = "locks"
+ start Locks cb = start (Locks' defaultLabels) cb
+ start (Locks' labels) cb = do
d <- openDisplay ""
root <- rootWindow d (defaultScreen d)
_ <- xkbSelectEventDetails d xkbUseCoreKbd xkbIndicatorStateNotify m m
allocaXEvent $ \ep -> forever $ do
- cb =<< run' d root
+ cb =<< run' d root labels
nextEvent' d ep
getEvent ep
diff --git a/src/Xmobar/Plugins/Monitors/Alsa.hs b/src/Xmobar/Plugins/Monitors/Alsa.hs
index dfc7329..8d02931 100644
--- a/src/Xmobar/Plugins/Monitors/Alsa.hs
+++ b/src/Xmobar/Plugins/Monitors/Alsa.hs
@@ -1,7 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Monitors.Alsa
--- Copyright : (c) 2018 Daniel Schüssler
+-- Copyright : (c) 2018, 2024 Daniel Schüssler
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>
@@ -25,6 +25,7 @@ import Control.Concurrent.Async
import Control.Exception
import Control.Monad
import Data.IORef
+import Data.Maybe (fromJust)
import Data.Time.Clock
import Xmobar.Plugins.Monitors.Common
import qualified Xmobar.Plugins.Monitors.Volume as Volume;
@@ -129,7 +130,8 @@ alsaReaderThread mixerName alsaCtlPath outputCallback mvar =
{std_out = CreatePipe}
runAlsaOnce =
- withCreateProcess createProc $ \_ (Just alsaOut) _ _ -> do
+ withCreateProcess createProc $ \_ out _ _ -> do
+ let alsaOut = fromJust out
hSetBuffering alsaOut LineBuffering
tryPutMVar mvar () -- Refresh immediately after restarting alsactl
diff --git a/src/Xmobar/Plugins/Monitors/Batt/Common.hs b/src/Xmobar/Plugins/Monitors/Batt/Common.hs
index 3262b78..ddb2b8c 100644
--- a/src/Xmobar/Plugins/Monitors/Batt/Common.hs
+++ b/src/Xmobar/Plugins/Monitors/Batt/Common.hs
@@ -1,7 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Monitors.Batt.Common
--- Copyright : (c) 2010, 2011, 2012, 2013, 2015, 2016, 2018, 2019 Jose A Ortega
+-- Copyright : (c) 2010-2016, 2018, 2019, 2024 Jose A Ortega
-- (c) 2010 Andrea Rossato, Petr Rockai
-- License : BSD-style (see LICENSE)
--
@@ -18,7 +18,7 @@ module Xmobar.Plugins.Monitors.Batt.Common (BattOpts(..)
, Status(..)
, maybeAlert) where
-import System.Process (system)
+import System.Process (spawnCommand, waitForProcess)
import Control.Monad (unless, void)
import Xmobar.Plugins.Monitors.Common
@@ -54,4 +54,4 @@ maybeAlert opts left =
case onLowAction opts of
Nothing -> return ()
Just x -> unless (isNaN left || actionThreshold opts < 100 * left)
- $ void $ system x
+ $ void $ spawnCommand (x ++ " &") >>= waitForProcess
diff --git a/src/Xmobar/Plugins/Monitors/Common/Output.hs b/src/Xmobar/Plugins/Monitors/Common/Output.hs
index bd60710..c0a00ab 100644
--- a/src/Xmobar/Plugins/Monitors/Common/Output.hs
+++ b/src/Xmobar/Plugins/Monitors/Common/Output.hs
@@ -3,7 +3,7 @@
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.Plugins.Monitors.Strings
--- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz
+-- Copyright: (c) 2018, 2019, 2020, 2022, 2024 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
@@ -88,9 +88,9 @@ pShowWithColors p f x = do
pColorizeString :: (Num a, Ord a, MonadIO m) => MonitorConfig -> a -> String -> m String
pColorizeString p x s = do
let col = pSetColor p s
- [ll,hh] = map fromIntegral $ sort [pLow p, pHigh p] -- consider high < low
- pure $ head $ [col pHighColor | x > hh ] ++
- [col pNormalColor | x > ll ] ++
+ cols = map fromIntegral $ sort [pLow p, pHigh p] -- consider high < low
+ pure $ head $ [col pHighColor | x > (cols !! 1) ] ++
+ [col pNormalColor | x > head cols ] ++
[col pLowColor | True]
pSetColor :: MonitorConfig -> String -> PSelector (Maybe String) -> String
@@ -140,7 +140,7 @@ showWithUnits d n x
padString :: Int -> Int -> String -> Bool -> String -> String -> String
padString mnw mxw pad pr ellipsis s =
let len = length s
- rmin = if mnw < 0 then 0 else mnw
+ rmin = max mnw 0
rmax = if mxw <= 0 then max len rmin else mxw
(rmn, rmx) = if rmin <= rmax then (rmin, rmax) else (rmax, rmin)
rlen = min (max rmn len) rmx
@@ -197,9 +197,9 @@ colorizeString x s = do
h <- getConfigValue high
l <- getConfigValue low
let col = setColor s
- [ll,hh] = map fromIntegral $ sort [l, h] -- consider high < low
- head $ [col highColor | x > hh ] ++
- [col normalColor | x > ll ] ++
+ cols = map fromIntegral $ sort [l, h] -- consider high < low
+ head $ [col highColor | x > cols !! 1 ] ++
+ [col normalColor | x > head cols ] ++
[col lowColor | True]
showWithColors :: (Num a, Ord a) => (a -> String) -> a -> Monitor String
@@ -260,11 +260,11 @@ logScaling f v = do
h <- fromIntegral `fmap` getConfigValue high
l <- fromIntegral `fmap` getConfigValue low
bw <- fromIntegral `fmap` getConfigValue barWidth
- let [ll, hh] = sort [l, h]
+ let ws = sort [l, h]
bw' = if bw > 0 then bw else 10
scaled x | x == 0.0 = 0
- | x <= ll = 1 / bw'
- | otherwise = f + logBase 2 (x / hh) / bw'
+ | x <= head ws = 1 / bw'
+ | otherwise = f + logBase 2 (x / ws !! 1) / bw'
return $ scaled v
showLogBar :: Float -> Float -> Monitor String
diff --git a/src/Xmobar/Plugins/Monitors/Disk.hs b/src/Xmobar/Plugins/Monitors/Disk.hs
index 47d1eac..95bcff6 100644
--- a/src/Xmobar/Plugins/Monitors/Disk.hs
+++ b/src/Xmobar/Plugins/Monitors/Disk.hs
@@ -1,7 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Monitors.Disk
--- Copyright : (c) 2010, 2011, 2012, 2014, 2018, 2019 Jose A Ortega Ruiz
+-- Copyright : (c) 2010-2012, 2014, 2018, 2019, 2024 Jose A Ortega Ruiz
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Jose A Ortega Ruiz <jao@gnu.org>
@@ -131,10 +131,9 @@ startDiskIO disks args rate cb = do
runM args diskIOConfig (runDiskIO dref disks) rate cb
runDiskU' :: DiskUOpts -> String -> [Integer] -> Monitor String
-runDiskU' opts tmp stat = do
+runDiskU' opts tmp (total:free:diff:_) = do
setConfigValue tmp template
- let [total, free, diff] = stat
- strs = map sizeToStr [free, diff]
+ let strs = map sizeToStr [free, diff]
freep = if total > 0 then free * 100 `div` total else 0
fr = fromIntegral freep / 100
s <- zipWithM showWithColors' strs [freep, 100 - freep]
@@ -146,6 +145,7 @@ runDiskU' opts tmp stat = do
uvb <- showVerticalBar (fromIntegral $ 100 - freep) (1 - fr)
uipat <- showIconPattern (usedIconPattern opts) (1 - fr)
parseTemplate $ [sizeToStr total] ++ s ++ sp ++ [fb,fvb,fipat,ub,uvb,uipat]
+runDiskU' _ _ _ = return ""
runDiskU :: [(String, String)] -> [String] -> Monitor String
runDiskU disks argv = do
diff --git a/src/Xmobar/Plugins/Monitors/Mem/Linux.hs b/src/Xmobar/Plugins/Monitors/Mem/Linux.hs
index 79dcc9d..7a81c6d 100644
--- a/src/Xmobar/Plugins/Monitors/Mem/Linux.hs
+++ b/src/Xmobar/Plugins/Monitors/Mem/Linux.hs
@@ -25,9 +25,13 @@ parseMEM =
let content = map words $ take 8 $ lines file
info = M.fromList $ map (
\line -> (head line, (read $ line !! 1 :: Float) / 1024)) content
- [total, free, buffer, cache] =
- map (info M.!) ["MemTotal:", "MemFree:", "Buffers:", "Cached:"]
- available = M.findWithDefault (free + buffer + cache) "MemAvailable:" info
+ info' x = info M.! (x ++ ":")
+ total = info' "MemTotal"
+ free = info' "MemFree"
+ buffer = info' "Buffers"
+ cache = info' "Cached"
+ available =
+ M.findWithDefault (free + buffer + cache) "MemAvailable:" info
used = total - available
usedratio = used / total
freeratio = free / total
diff --git a/src/Xmobar/Plugins/Monitors/Net/Linux.hs b/src/Xmobar/Plugins/Monitors/Net/Linux.hs
index 9306497..f9cbc28 100644
--- a/src/Xmobar/Plugins/Monitors/Net/Linux.hs
+++ b/src/Xmobar/Plugins/Monitors/Net/Linux.hs
@@ -47,7 +47,10 @@ isUp d = flip catchIOError (const $ return False) $ do
return $! (head . B.lines) operstate `elem` ["up", "unknown"]
readNetDev :: [String] -> IO NetDevRawTotal
-readNetDev ~[d, x, y] = do
+readNetDev ds = do
+ let (d, x, y) = case ds of
+ d':x':y':_ -> (d', x', y')
+ _ -> ("", "", "")
up <- unsafeInterleaveIO $ isUp d
return $ N d (if up then ND (r x) (r y) else NI)
where r s | s == "" = 0
diff --git a/src/Xmobar/Run/Actions.hs b/src/Xmobar/Run/Actions.hs
index 2a49312..cbc10c5 100644
--- a/src/Xmobar/Run/Actions.hs
+++ b/src/Xmobar/Run/Actions.hs
@@ -16,7 +16,7 @@ module Xmobar.Run.Actions ( Button
, runAction'
, stripActions) where
-import System.Process (system)
+import System.Process (spawnCommand, waitForProcess)
import Control.Monad (void)
import Text.Regex (Regex, subRegex, mkRegex, matchRegex)
import Data.Word (Word32)
@@ -26,11 +26,11 @@ type Button = Word32
data Action = Spawn [Button] String deriving (Eq, Read, Show)
runAction :: Action -> IO ()
-runAction (Spawn _ s) = void $ system (s ++ "&")
+runAction (Spawn _ s) = void $ spawnCommand (s ++ " &") >>= waitForProcess
-- | Run action with stdout redirected to stderr
runAction' :: Action -> IO ()
-runAction' (Spawn _ s) = void $ system (s ++ " 1>&2 &")
+runAction' (Spawn _ s) = void $ spawnCommand (s ++ " 1>&2 &") >>= waitForProcess
stripActions :: String -> String
stripActions s = case matchRegex actionRegex s of
diff --git a/src/Xmobar/Run/Parsers.hs b/src/Xmobar/Run/Parsers.hs
deleted file mode 100644
index 9b36786..0000000
--- a/src/Xmobar/Run/Parsers.hs
+++ /dev/null
@@ -1,244 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-
------------------------------------------------------------------------------
--- |
--- Module : Xmobar.Run.Parsers
--- Copyright : (c) Andrea Rossato
--- License : BSD-style (see LICENSE)
---
--- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>
--- Stability : unstable
--- Portability : portable
---
--- Parsing for template substrings
---
------------------------------------------------------------------------------
-
-module Xmobar.Run.Parsers ( parseString
- , colorComponents
- , Segment
- , FontIndex
- , Box(..)
- , BoxBorder(..)
- , BoxOffset(..)
- , BoxMargins(..)
- , TextRenderInfo(..)
- , Widget(..)) where
-
-import Control.Monad (guard, mzero)
-import Data.Maybe (fromMaybe)
-import Data.Int (Int32)
-import Text.ParserCombinators.Parsec
-import Text.Read (readMaybe)
-import Foreign.C.Types (CInt)
-
-import Xmobar.Config.Types
-import Xmobar.Run.Actions
-
-data Widget = Icon String | Text String | Hspace Int32 deriving Show
-
-data BoxOffset = BoxOffset Align Int32 deriving (Eq, Show)
-
--- margins: Top, Right, Bottom, Left
-data BoxMargins = BoxMargins Int32 Int32 Int32 Int32 deriving (Eq, Show)
-
-data BoxBorder = BBTop
- | BBBottom
- | BBVBoth
- | BBLeft
- | BBRight
- | BBHBoth
- | BBFull
- deriving (Read, Eq, Show)
-
-data Box = Box { bBorder :: BoxBorder
- , bOffset :: BoxOffset
- , bWidth :: CInt
- , bColor :: String
- , bMargins :: BoxMargins
- } deriving (Eq, Show)
-
-data TextRenderInfo = TextRenderInfo { tColorsString :: String
- , tBgTopOffset :: Int32
- , tBgBottomOffset :: Int32
- , tBoxes :: [Box]
- } deriving Show
-
-type Segment = (Widget, TextRenderInfo, FontIndex, Maybe [Action])
-
--- | Runs the string parser
-parseString :: Config -> String -> IO [Segment]
-parseString c s =
- case parse (stringParser ci 0 Nothing) "" s of
- Left _ -> return [(Text $ "Could not parse string: " ++ s
- , ci
- , 0
- , Nothing)]
- Right x -> return (concat x)
- where ci = TextRenderInfo (fgColor c) 0 0 []
-
--- | Splits a colors string into its two components
-colorComponents :: Config -> String -> (String, String)
-colorComponents conf c =
- case break (==',') c of
- (f,',':b) -> (f, b)
- (f, _) -> (f, bgColor conf)
-
-allParsers :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-allParsers c f a = textParser c f a
- <|> try (iconParser c f a)
- <|> try (hspaceParser c f a)
- <|> try (rawParser c f a)
- <|> try (actionParser c f a)
- <|> try (fontParser c a)
- <|> try (boxParser c f a)
- <|> colorParser c f a
-
--- | Gets the string and combines the needed parsers
-stringParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [[Segment]]
-stringParser c f a = manyTill (allParsers c f a) eof
-
--- | Parses a maximal string without markup.
-textParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-textParser c f a = do s <- many1 $
- noneOf "<" <|>
- try (notFollowedBy' (char '<')
- (try (string "fc=") <|>
- try (string "box") <|>
- try (string "fn=") <|>
- try (string "action=") <|>
- try (string "/action>") <|>
- try (string "icon=") <|>
- try (string "hspace=") <|>
- try (string "raw=") <|>
- try (string "/fn>") <|>
- try (string "/box>") <|>
- string "/fc>"))
- return [(Text s, c, f, a)]
-
--- | Parse a "raw" tag, which we use to prevent other tags from creeping in.
--- The format here is net-string-esque: a literal "<raw=" followed by a
--- string of digits (base 10) denoting the length of the raw string,
--- a literal ":" as digit-string-terminator, the raw string itself, and
--- then a literal "/>".
-rawParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-rawParser c f a = do
- string "<raw="
- lenstr <- many1 digit
- char ':'
- case reads lenstr of
- [(len,[])] -> do
- guard ((len :: Integer) <= fromIntegral (maxBound :: Int))
- s <- count (fromIntegral len) anyChar
- string "/>"
- return [(Text s, c, f, a)]
- _ -> mzero
-
--- | Wrapper for notFollowedBy that returns the result of the first parser.
--- Also works around the issue that, at least in Parsec 3.0.0, notFollowedBy
--- accepts only parsers with return type Char.
-notFollowedBy' :: Parser a -> Parser b -> Parser a
-notFollowedBy' p e = do x <- p
- notFollowedBy $ try (e >> return '*')
- return x
-
-iconParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-iconParser c f a = do
- string "<icon="
- i <- manyTill (noneOf ">") (try (string "/>"))
- return [(Icon i, c, f, a)]
-
-hspaceParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-hspaceParser c f a = do
- string "<hspace="
- pVal <- manyTill digit (try (string "/>"))
- return [(Hspace (fromMaybe 0 $ readMaybe pVal), c, f, a)]
-
-actionParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-actionParser c f act = do
- string "<action="
- command <- choice [between (char '`') (char '`') (many1 (noneOf "`")),
- many1 (noneOf ">")]
- buttons <- (char '>' >> return "1") <|> (space >> spaces >>
- between (string "button=") (string ">") (many1 (oneOf "12345")))
- let a = Spawn (toButtons buttons) command
- a' = case act of
- Nothing -> Just [a]
- Just act' -> Just $ a : act'
- s <- manyTill (allParsers c f a') (try $ string "</action>")
- return (concat s)
-
-toButtons :: String -> [Button]
-toButtons = map (\x -> read [x])
-
--- | Parsers a string wrapped in a color specification.
-colorParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-colorParser (TextRenderInfo _ _ _ bs) fidx a = do
- c <- between (string "<fc=") (string ">") colors
- let colorParts = break (==':') c
- let (ot,ob) = case break (==',') (Prelude.drop 1 $ snd colorParts) of
- (top,',':btm) -> (top, btm)
- (top, _) -> (top, top)
- tri = TextRenderInfo (fst colorParts)
- (fromMaybe (-1) $ readMaybe ot)
- (fromMaybe (-1) $ readMaybe ob)
- bs
- s <- manyTill (allParsers tri fidx a) (try $ string "</fc>")
- return (concat s)
-
--- | Parses a string wrapped in a box specification.
-boxParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment]
-boxParser (TextRenderInfo cs ot ob bs) f a = do
- c <- between (string "<box") (string ">")
- (option "" (many1 (alphaNum
- <|> char '='
- <|> char ' '
- <|> char '#'
- <|> char ',')))
- let b = Box BBFull (BoxOffset C 0) 1 cs (BoxMargins 0 0 0 0)
- let g = boxReader b (words c)
- s <- manyTill
- (allParsers (TextRenderInfo cs ot ob (g : bs)) f a)
- (try $ string "</box>")
- return (concat s)
-
-boxReader :: Box -> [String] -> Box
-boxReader b [] = b
-boxReader b (x:xs) = do
- let (param,val) = case break (=='=') x of
- (p,'=':v) -> (p, v)
- (p, _) -> (p, "")
- boxReader (boxParamReader b param val) xs
-
-boxParamReader :: Box -> String -> String -> Box
-boxParamReader b _ "" = b
-boxParamReader (Box bb off lw fc mgs) "type" val =
- Box (fromMaybe bb $ readMaybe ("BB" ++ val)) off lw fc mgs
-boxParamReader (Box bb (BoxOffset alg off) lw fc mgs) "offset" (a:o) =
- Box bb (BoxOffset align offset) lw fc mgs
- where offset = fromMaybe off $ readMaybe o
- align = fromMaybe alg $ readMaybe [a]
-boxParamReader (Box bb off lw fc mgs) "width" val =
- Box bb off (fromMaybe lw $ readMaybe val) fc mgs
-boxParamReader (Box bb off lw _ mgs) "color" val =
- Box bb off lw val mgs
-boxParamReader (Box bb off lw fc mgs@(BoxMargins mt mr mb ml)) ('m':pos) val = do
- let mgs' = case pos of
- "t" -> BoxMargins (fromMaybe mt $ readMaybe val) mr mb ml
- "r" -> BoxMargins mt (fromMaybe mr $ readMaybe val) mb ml
- "b" -> BoxMargins mt mr (fromMaybe mb $ readMaybe val) ml
- "l" -> BoxMargins mt mr mb (fromMaybe ml $ readMaybe val)
- _ -> mgs
- Box bb off lw fc mgs'
-boxParamReader b _ _ = b
-
--- | Parsers a string wrapped in a font specification.
-fontParser :: TextRenderInfo -> Maybe [Action] -> Parser [Segment]
-fontParser c a = do
- f <- between (string "<fn=") (string ">") colors
- s <- manyTill (allParsers c (fromMaybe 0 $ readMaybe f) a) (try $ string "</fn>")
- return (concat s)
-
--- | Parses a color specification (hex or named)
-colors :: Parser String
-colors = many1 (alphaNum <|> char ',' <|> char ':' <|> char '#')
diff --git a/src/Xmobar/Run/Template.hs b/src/Xmobar/Run/Template.hs
index 87c84d3..68feacb 100644
--- a/src/Xmobar/Run/Template.hs
+++ b/src/Xmobar/Run/Template.hs
@@ -77,5 +77,6 @@ splitTemplate alignSep template =
(ce,_:ri) -> [le, ce, ri]
_ -> def
_ -> def
- where [l, r] = if length alignSep == 2 then alignSep else defaultAlign
+ where sep = if length alignSep == 2 then alignSep else defaultAlign
+ (l, r) = (head sep, sep !! 1)
def = [template, "", ""]
diff --git a/src/Xmobar/System/DBus.hs b/src/Xmobar/System/DBus.hs
index 103a5a9..90bee2a 100644
--- a/src/Xmobar/System/DBus.hs
+++ b/src/Xmobar/System/DBus.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
-----------------------------------------------------------------------------
-- |
-- Module : DBus
@@ -17,9 +18,10 @@ module Xmobar.System.DBus (runIPC) where
import DBus
import DBus.Client hiding (interfaceName)
import qualified DBus.Client as DC
+import DBus.Socket
import Data.Maybe (isNothing)
import Control.Concurrent.STM
-import Control.Exception (handle)
+import Control.Exception
import System.IO (stderr, hPutStrLn)
import Control.Monad.IO.Class (liftIO)
@@ -35,10 +37,10 @@ interfaceName :: InterfaceName
interfaceName = interfaceName_ "org.Xmobar.Control"
runIPC :: TMVar SignalType -> IO ()
-runIPC mvst = handle printException exportConnection
+runIPC mvst = exportConnection `catches` [
+ Handler(\ (ex :: ClientError) -> hPutStrLn stderr (clientErrorMessage ex)),
+ Handler(\ (ex :: SocketError) -> hPutStrLn stderr (socketErrorMessage ex))]
where
- printException :: ClientError -> IO ()
- printException = hPutStrLn stderr . clientErrorMessage
exportConnection = do
client <- connectSession
requestName client busName [ nameDoNotQueue ]
diff --git a/src/Xmobar/System/Environment.hs b/src/Xmobar/System/Environment.hs
index 25802fe..0491bcc 100644
--- a/src/Xmobar/System/Environment.hs
+++ b/src/Xmobar/System/Environment.hs
@@ -13,14 +13,14 @@
-----------------------------------------------------------------------------
module Xmobar.System.Environment(expandEnv) where
-import Data.Maybe (fromMaybe)
-import System.Environment (lookupEnv)
+import qualified Data.Maybe as M
+import qualified System.Environment as E
expandEnv :: String -> IO String
expandEnv "" = return ""
expandEnv (c:s) = case c of
'$' -> do
- envVar <- fromMaybe "" <$> lookupEnv e
+ envVar <- M.fromMaybe "" <$> E.lookupEnv e
remainder <- expandEnv s'
return $ envVar ++ remainder
where (e, s') = getVar s
@@ -36,12 +36,13 @@ expandEnv (c:s) = case c of
False -> do
remainder <- expandEnv $ drop 1 s
return $ escString s ++ remainder
- where escString s' = let (cc:_) = s' in
+ where escString (cc:_) =
case cc of
't' -> "\t"
'n' -> "\n"
'$' -> "$"
_ -> [cc]
+ escString [] = ""
_ -> do
remainder <- expandEnv s
diff --git a/src/Xmobar/Text/Loop.hs b/src/Xmobar/Text/Loop.hs
index 05379cd..5d2c43f 100644
--- a/src/Xmobar/Text/Loop.hs
+++ b/src/Xmobar/Text/Loop.hs
@@ -45,4 +45,4 @@ eventLoop cfg signal tv = do
updateString :: Config -> TVar [String] -> IO String
updateString conf v = do
s <- readTVarIO v
- format conf (concat s)
+ return $ format conf (concat s)
diff --git a/src/Xmobar/Text/Output.hs b/src/Xmobar/Text/Output.hs
index 783a5bb..677b6d2 100644
--- a/src/Xmobar/Text/Output.hs
+++ b/src/Xmobar/Text/Output.hs
@@ -15,13 +15,15 @@
module Xmobar.Text.Output (initLoop, format) where
-import Xmobar.Config.Types (Config(textOutputFormat, additionalFonts, font)
- , TextOutputFormat(..))
-import Xmobar.Run.Parsers ( Segment
- , Widget(..)
- , parseString
- , tColorsString
- , colorComponents)
+import Xmobar.Config.Types ( Config (..)
+ , TextOutputFormat (..)
+ , Segment
+ , Widget (..)
+ , tColorsString)
+
+
+import Xmobar.Config.Parse (colorComponents)
+import Xmobar.Config.Template (parseString)
import Xmobar.Text.Ansi (withAnsiColor)
import Xmobar.Text.Pango (withPangoMarkup)
@@ -47,9 +49,9 @@ formatWithColor conf (Hspace n, i, x, y) =
formatWithColor conf (Text $ replicate (fromIntegral n) ' ', i, x, y)
formatWithColor _ _ = ""
-format :: Config -> String -> IO String
+format :: Config -> String -> String
format conf s = do
- segments <- parseString conf s
+ let segments = parseString conf s
case textOutputFormat conf of
- Swaybar -> return $ formatSwaybar conf segments
- _ -> return (concatMap (formatWithColor conf) segments)
+ Swaybar -> formatSwaybar conf segments
+ _ -> concatMap (formatWithColor conf) segments
diff --git a/src/Xmobar/Text/Swaybar.hs b/src/Xmobar/Text/Swaybar.hs
index a2fc585..355de06 100644
--- a/src/Xmobar/Text/Swaybar.hs
+++ b/src/Xmobar/Text/Swaybar.hs
@@ -24,16 +24,16 @@ import Data.ByteString.Lazy.UTF8 (toString)
import GHC.Generics
-import Xmobar.Config.Types (Config (additionalFonts))
-
-import Xmobar.Run.Parsers ( Segment
- , Widget(..)
- , Box(..)
- , BoxBorder(..)
- , FontIndex
- , tBoxes
- , tColorsString
- , colorComponents)
+import Xmobar.Config.Types ( Config (additionalFonts)
+ , Segment
+ , Widget(..)
+ , Box(..)
+ , BoxBorder(..)
+ , FontIndex
+ , tBoxes
+ , tColorsString)
+
+import Xmobar.Config.Parse (colorComponents)
import Xmobar.Text.SwaybarClicks (startHandler)
import Xmobar.Text.Pango (withPangoFont)
diff --git a/src/Xmobar/X11/Bitmap.hs b/src/Xmobar/X11/Bitmap.hs
index b14356f..c5304d9 100644
--- a/src/Xmobar/X11/Bitmap.hs
+++ b/src/Xmobar/X11/Bitmap.hs
@@ -2,7 +2,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : X11.Bitmap
--- Copyright : (C) 2013, 2015, 2017, 2018, 2022 Alexander Polakov
+-- Copyright : (C) 2013, 2015, 2017, 2018, 2022, 2024 Alexander Polakov
-- License : BSD3
--
-- Maintainer : jao@gnu.org
@@ -116,8 +116,9 @@ loadBitmap d w p = do
drawBitmap :: Display -> Drawable -> GC -> String -> String
-> Position -> Position -> Bitmap -> IO ()
drawBitmap d p gc fc bc x y i =
- withColors d [fc, bc] $ \[fc', bc'] -> do
- let w = width i
+ withColors d [fc, bc] $ \cs -> do
+ let (fc', bc') = (head cs, cs !! 1)
+ w = width i
h = height i
y' = 1 + y - fromIntegral h `div` 2
setForeground d gc fc'
diff --git a/src/Xmobar/X11/Draw.hs b/src/Xmobar/X11/Draw.hs
index a056136..a1ec901 100644
--- a/src/Xmobar/X11/Draw.hs
+++ b/src/Xmobar/X11/Draw.hs
@@ -25,7 +25,6 @@ import Foreign.C.Types as FT
import qualified Graphics.X11.Xlib as X11
import qualified Xmobar.Config.Types as C
-import qualified Xmobar.Run.Parsers as P
import qualified Xmobar.Draw.Types as D
import qualified Xmobar.Draw.Cairo as DC
@@ -38,11 +37,8 @@ import qualified Xmobar.X11.XRender as XRender
#endif
drawXBitmap :: T.XConf -> X11.GC -> X11.Pixmap -> D.IconDrawer
-drawXBitmap xconf gc p h v path = do
+drawXBitmap xconf gc p h v path fc bc = do
let disp = T.display xconf
- conf = T.config xconf
- fc = C.fgColor conf
- bc = C.bgColor conf
case M.lookup path (T.iconCache xconf) of
Just bm -> liftIO $ B.drawBitmap disp p gc fc bc (round h) (round v) bm
Nothing -> return ()
@@ -69,7 +65,7 @@ withPixmap disp win (X11.Rectangle _ _ w h) depth action = do
X11.sync disp True
return res
-draw :: [[P.Segment]] -> T.X [D.ActionPos]
+draw :: [[C.Segment]] -> T.X [D.ActionPos]
draw segments = do
xconf <- ask
let disp = T.display xconf
@@ -89,7 +85,7 @@ draw segments = do
#ifdef XRENDER
color = C.bgColor conf
alph = C.alpha conf
- XRender.drawBackground disp p color alph (X11.Rectangle 0 0 w h)
+ XRender.drawBackground disp p color alph rect
#endif
CS.withXlibSurface disp p vis (fromIntegral w) (fromIntegral h) render
diff --git a/src/Xmobar/X11/Events.hs b/src/Xmobar/X11/Events.hs
index 4334f6b..fbd2bd0 100644
--- a/src/Xmobar/X11/Events.hs
+++ b/src/Xmobar/X11/Events.hs
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.X11.Events
--- Copyright: (c) 2018 Jose Antonio Ortega Ruiz
+-- Copyright: (c) 2018, 2022 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
@@ -17,20 +17,19 @@
module Xmobar.X11.Events(nextEvent') where
-import Control.Concurrent
-import System.Posix.Types (Fd(..))
+import qualified Control.Concurrent as C
+import qualified System.Posix.Types as T
-import Graphics.X11.Xlib (
- Display(..), XEventPtr, nextEvent, pending, connectionNumber)
+import qualified Graphics.X11.Xlib as X
-- | A version of nextEvent that does not block in foreign calls.
-nextEvent' :: Display -> XEventPtr -> IO ()
+nextEvent' :: X.Display -> X.XEventPtr -> IO ()
nextEvent' d p = do
- pend <- pending d
+ pend <- X.pending d
if pend /= 0
- then nextEvent d p
+ then X.nextEvent d p
else do
- threadWaitRead (Fd fd)
+ C.threadWaitRead (T.Fd fd)
nextEvent' d p
where
- fd = connectionNumber d
+ fd = X.connectionNumber d
diff --git a/src/Xmobar/X11/Loop.hs b/src/Xmobar/X11/Loop.hs
index 599e680..2dfb34d 100644
--- a/src/Xmobar/X11/Loop.hs
+++ b/src/Xmobar/X11/Loop.hs
@@ -3,7 +3,7 @@
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.App.X11EventLoop
--- Copyright: (c) 2018, 2020, 2022 Jose Antonio Ortega Ruiz
+-- Copyright: (c) 2018, 2020, 2022, 2023, 2024 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
@@ -22,6 +22,7 @@ import Prelude hiding (lookup)
import Control.Concurrent as Concurrent
import Control.Concurrent.STM as STM
+import Control.Monad as MR
import Control.Monad.Reader as MR
import Data.Bits (Bits((.|.)))
@@ -35,10 +36,10 @@ import qualified Graphics.X11.Xinerama as Xinerama
import qualified Graphics.X11.Xrandr as Xrandr
import qualified Xmobar.Config.Types as C
+import qualified Xmobar.Config.Template as CT
import qualified Xmobar.Run.Actions as A
import qualified Xmobar.Run.Loop as L
-import qualified Xmobar.Run.Parsers as P
import qualified Xmobar.System.Utils as U
import qualified Xmobar.System.Signal as S
@@ -145,15 +146,14 @@ signalLoop xc@(T.XConf d r w fs is cfg) actions signalv strs = do
r' <- W.repositionWin d w (NE.head fs) rcfg
signalLoop (T.XConf d r' w fs is rcfg) actions signalv strs
-parseSegments :: C.Config -> STM.TVar [String] -> IO [[P.Segment]]
+parseSegments :: C.Config -> STM.TVar [String] -> IO [[C.Segment]]
parseSegments conf v = do
s <- STM.readTVarIO v
- let l:c:r:_ = s ++ repeat ""
- MR.liftIO $ mapM (P.parseString conf) [l, c, r]
+ return $ map (CT.parseString conf) (take 3 $ s ++ repeat "")
-updateIconCache :: T.XConf -> [[P.Segment]] -> IO T.XConf
+updateIconCache :: T.XConf -> [[C.Segment]] -> IO T.XConf
updateIconCache xc@(T.XConf d _ w _ c cfg) segs = do
- let paths = [p | (P.Icon p, _, _, _) <- concat segs]
+ let paths = [p | (C.Icon p, _, _, _) <- concat segs]
c' <- Bitmap.updateCache d w c (C.iconRoot cfg) paths
return $ xc {T.iconCache = c'}
diff --git a/src/Xmobar/X11/Window.hs b/src/Xmobar/X11/Window.hs
index ad7ebf7..87d56f4 100644
--- a/src/Xmobar/X11/Window.hs
+++ b/src/Xmobar/X11/Window.hs
@@ -86,10 +86,14 @@ setPosition c p rs ht =
T.Top -> X.Rectangle rx ry rw h
T.TopP l r -> X.Rectangle (rx + fi l) ry (rw - fi l - fi r) h
T.TopH ch -> X.Rectangle rx ry rw (mh ch)
+ T.TopHM ch l r t _ ->
+ X.Rectangle (rx + fi l) (ry + fi t) (rw - fi l - fi r) (mh ch)
T.TopW a i -> X.Rectangle (ax a i) ry (nw i) h
T.TopSize a i ch -> X.Rectangle (ax a i) ry (nw i) (mh ch)
T.Bottom -> X.Rectangle rx ny rw h
T.BottomH ch -> X.Rectangle rx (ny' ch) rw (mh ch)
+ T.BottomHM ch l r _ b ->
+ X.Rectangle (rx + fi l) (ry + fi rh - fi b - fi (mh ch)) (rw - fi l - fi r) (mh ch)
T.BottomW a i -> X.Rectangle (ax a i) ny (nw i) h
T.BottomP l r -> X.Rectangle (rx + fi l) ny (rw - fi l - fi r) h
T.BottomSize a i ch -> X.Rectangle (ax a i) (ny' ch) (nw i) (mh ch)
@@ -160,18 +164,20 @@ getRootWindowHeight srs = maximum (map getMaxScreenYCoord srs)
getStrutValues :: X.Rectangle -> T.XPosition -> Int -> [Int]
getStrutValues r@(X.Rectangle x y w h) p rwh =
case p of
- T.OnScreen _ p' -> getStrutValues r p' rwh
- T.Top -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- T.TopH _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- T.TopP _ _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- T.TopW _ _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- T.TopSize {} -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- T.Bottom -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- T.BottomH _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- T.BottomP _ _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- T.BottomW _ _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- T.BottomSize {} -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- T.Static {} -> getStaticStrutValues p rwh
+ T.OnScreen _ p' -> getStrutValues r p' rwh
+ T.Top -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ]
+ T.TopH _ -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ]
+ T.TopHM _ _ _ _ b -> [0, 0, st+b, 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ]
+ T.TopP _ _ -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ]
+ T.TopW _ _ -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ]
+ T.TopSize {} -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ]
+ T.Bottom -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw]
+ T.BottomH _ -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw]
+ T.BottomHM _ _ _ t _ -> [0, 0, 0 , sb+t, 0, 0, 0, 0, 0 , 0 , nx, nw]
+ T.BottomP _ _ -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw]
+ T.BottomW _ _ -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw]
+ T.BottomSize {} -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw]
+ T.Static {} -> getStaticStrutValues p rwh
where st = fi y + fi h
sb = rwh - fi y
nx = fi x
diff --git a/stack.yaml b/stack.yaml
index 8021bad..0b8ecb4 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -12,6 +12,10 @@ flags:
extra-deps:
- netlink-1.1.1.0
- libmpd-0.9.2.0
+ - cairo-0.13.8.2
+ - pango-0.13.8.2
+ - glib-0.13.8.2
+ - gtk2hs-buildtools-0.13.8.3
nix:
packages:
- alsaLib
diff --git a/xmobar.cabal b/xmobar.cabal
index 8b331f5..e6de840 100644
--- a/xmobar.cabal
+++ b/xmobar.cabal
@@ -1,5 +1,5 @@
name: xmobar
-version: 0.45
+version: 0.49
homepage: https://codeberg.org/xmobar/xmobar
synopsis: A Minimalistic Text Based Status Bar
description: Xmobar is a minimalistic text based status bar.
@@ -84,6 +84,10 @@ flag with_rtsopts
description: Use -with-rtsopts=-V0 to reduce wakeups.
default: True
+flag with_shared
+ description: Use shared libraries. Required when dependencies are built as shared libraries.
+ default: False
+
flag with_weather
description: Enable weather plugin.
default: True
@@ -109,13 +113,13 @@ library
other-modules: Paths_xmobar,
Xmobar.Config.Types,
Xmobar.Config.Parse,
+ Xmobar.Config.Template,
Xmobar.Run.Types,
Xmobar.Run.Timer,
Xmobar.Run.Template,
Xmobar.Run.Exec,
Xmobar.Run.Runnable
Xmobar.Run.Actions,
- Xmobar.Run.Parsers,
Xmobar.Run.Loop,
Xmobar.Draw.Boxes,
Xmobar.Draw.Cairo,
@@ -194,15 +198,16 @@ library
build-depends:
aeson >= 1.4.7.1,
async,
- base >= 4.11.0 && < 4.17,
+ base >= 4.11.0 && < 4.20,
bytestring >= 0.10.8.2,
cairo >= 0.13,
colour >= 2.3.6,
containers,
directory,
+ extra,
extensible-exceptions == 0.1.*,
filepath,
- mtl >= 2.1 && < 2.3,
+ mtl >= 2.1 && < 2.4,
old-locale,
pango >= 0.13,
parsec == 3.1.*,
@@ -232,6 +237,9 @@ library
if flag(with_rtsopts)
cpp-options: -DRTSOPTS
+ if flag(with_shared)
+ cpp-options: -DSHARED_LIBRARIES
+
if flag(with_xrender)
build-depends: X11-xft >= 0.2
other-modules: Xmobar.X11.XRender
@@ -255,7 +263,7 @@ library
cereal >= 0.5.8.1
cpp-options: -DUSE_NL80211
- if flag(with_mpd) || flag(all_extensions)
+ if flag(with_mpd) || (flag(all_extensions) && impl(ghc < 9.4))
build-depends: libmpd >= 0.9.2.0
other-modules: Xmobar.Plugins.Monitors.MPD
cpp-options: -DLIBMPD