xmobar 0.41 → 0.42
raw patch · 40 files changed
+3352/−2968 lines, 40 filesdep ~aeson
Dependency ranges changed: aeson
Files
- changelog.md +14/−0
- doc/plugins.org +1326/−1640
- doc/quick-start.org +360/−270
- examples/xmobar.config +1/−0
- examples/xmobar.hs +2/−1
- readme.org +156/−107
- src/Xmobar.hs +2/−2
- src/Xmobar/App/Config.hs +3/−1
- src/Xmobar/App/EventLoop.hs +0/−283
- src/Xmobar/App/Main.hs +8/−44
- src/Xmobar/App/Opts.hs +29/−18
- src/Xmobar/App/Timer.hs +0/−221
- src/Xmobar/Config/Parse.hs +9/−5
- src/Xmobar/Config/Types.hs +5/−1
- src/Xmobar/Plugins/Command.hs +54/−0
- src/Xmobar/Plugins/Monitors/Cpu.hs +2/−2
- src/Xmobar/Plugins/StdinReader.hs +1/−1
- src/Xmobar/Plugins/XMonadLog.hs +6/−2
- src/Xmobar/Run/Actions.hs +43/−0
- src/Xmobar/Run/Command.hs +0/−54
- src/Xmobar/Run/Exec.hs +1/−1
- src/Xmobar/Run/Loop.hs +126/−0
- src/Xmobar/Run/Parsers.hs +234/−0
- src/Xmobar/Run/Template.hs +2/−1
- src/Xmobar/Run/Timer.hs +221/−0
- src/Xmobar/Run/Types.hs +2/−3
- src/Xmobar/System/Utils.hs +22/−1
- src/Xmobar/Text/Ansi.hs +49/−0
- src/Xmobar/Text/Loop.hs +48/−0
- src/Xmobar/Text/Output.hs +55/−0
- src/Xmobar/Text/Pango.hs +48/−0
- src/Xmobar/Text/Swaybar.hs +147/−0
- src/Xmobar/Text/SwaybarClicks.hs +60/−0
- src/Xmobar/X11/Actions.hs +0/−34
- src/Xmobar/X11/Bitmap.hs +3/−3
- src/Xmobar/X11/Draw.hs +49/−19
- src/Xmobar/X11/Loop.hs +229/−0
- src/Xmobar/X11/Parsers.hs +0/−227
- src/Xmobar/X11/Window.hs +1/−1
- xmobar.cabal +34/−26
changelog.md view
@@ -1,3 +1,17 @@+## Version 0.42 (March, 2022)++_New features_++ - New text mode (thanks to Pavel Kagulin, see issue #601), with+ output formats compatible with color terminals and pango.+ - New text mode with format following swaybar-protocol, supporting+ colors, faces, boxes and actions.++_Bug fixes_++ - Fix for bottom placement (#608)+ - Fix for memory leak during X drawing (#609)+ ## Version 0.41 (January, 2022) _New features_
doc/plugins.org view
@@ -1,1640 +1,1326 @@-* System Monitor Plugins-- This is the description of the system monitor plugins available in- xmobar. Some of them are only installed when an optional build- option is set: we mention that fact, when needed, in their- description.-- Each monitor has an =alias= to be used in the output- template. Monitors may have default aliases, see the documentation- of the monitor in question.-- There are two types of arguments: ones that all monitors share (the- so called /default monitor arguments/) and arguments that are specific- to a certain monitor.-- All Monitors accept a common set of arguments, described below in- [[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- =template= and =Low= arguments and then specifies the battery-specific- =off= option.-- #+begin_src haskell- Run Battery- [ "--template", "<acstatus>"- , "--Low" , "15"- -- battery specific options start here.- , "--"- , "--off" , "<left> (<timeleft>)"- ]- 100- #+end_src--** Icon Patterns--Some monitors allow usage of strings that depend on some integer value-from 0 to 8 by replacing all occurrences of =%%= with it-(i.e. =<icon=/path/to/icon_%%.xpm/>= will be interpreted as-=<icon=/path/to/icon_3.xpm/>= when the value is =3=, also =%= is-interpreted as =%=, =%%= as =3=, =%%%= as =3%=, =%%%%= as =33= and so-on). Essentially it allows to replace vertical bars with custom-icons. For example,--#+begin_src haskell- Run Brightness- [ "-t", "<ipat>"- , "--"- , "--brightness-icon-pattern", "<icon=bright_%%.xpm/>"- ] 30-#+end_src--Will display =bright_0.xpm= to =bright_8.xpm= depending on current-brightness value.--** Default Monitor Arguments--These are the options available for all monitors:--- =-t= /string/ Output template-- - Template for the monitor output. Field names must be enclosed- between pointy brackets (=<foo>=) and will be substituted by the- computed values. You can also specify the foreground (and- optionally, background) color for a region by bracketing it between- =<fc=fgcolor>= (or =<fc=fgcolor,bgcolor>=) and =</fc>=. The rest of- the template is output verbatim.- - Long option: =--template=- - Default value: per monitor (see above).--- =-H= /number/ The high threshold.-- - Numerical values higher than /number/ will be displayed with the- color specified by =-h= (see below).- - Long option: =--High=- - Default value: 66--- =-L= /number/ The low threshold.-- - Numerical values higher than /number/ and lower than the high- threshold will be displayed with the color specified by =-n= (see- below). Values lower than /number/ will use the =-l= color.- - Long option: =--Low=- - Default value: 33--- =-h= /color/ High threshold color.-- - Color for displaying values above the high threshold. /color/ can be- either a name (e.g. "blue") or an hexadecimal RGB (e.g. "#FF0000").- - Long option: =--high=- - Default: none (use the default foreground).--- =-n= /color/ Color for 'normal' values-- - Color used for values greater than the low threshold but lower than- the high one.- - Long option: =--normal=- - Default: none (use the default foreground).--- =-l= /color/ The low threshold color-- - Color for displaying values below the low threshold.- - Long option: =--low=- - Default: none (use the default foreground).--- =-S= /boolean/ Display optional suffixes-- - When set to a true designator ("True", "Yes" or "On"), optional- value suffixes such as the '%' symbol or optional units will be- displayed.- - Long option: =--suffix=- - Default: False.--- =-p= /number/ Percentages padding-- - Width, in number of digits, for quantities representing percentages.- For instance =-p 3= means that all percentages in the monitor will- be represented using 3 digits.- - Long option: =--ppad=- - Default value: 0 (don't pad)--- =-d= /number/ Decimal digits-- - Number of digits after the decimal period to use in float values.- - Long option: =--ddigits=- - Default value: 0 (display only integer part)--- =-m= /number/ Minimum field width-- - Minimum width, in number of characters, of the fields in the monitor- template. Values whose printed representation is shorter than this- value will be padded using the padding characters given by the =-c=- option with the alignment specified by =-a= (see below).- - Long option: =--minwidth=- - Default: 0--- =-M= /number/ Maximum field width-- - Maximum width, in number of characters, of the fields in the monitor- template. Values whose printed representation is longer than this- value will be truncated.- - Long option: =--maxwidth=- - Default: 0 (no maximum width)--- =-e= /string/ Maximum width ellipsis-- - Ellipsis to be added to the field when it has reached its max width.- - Long option: =--maxwidthellipsis=- - Default: "" (no ellipsis)--- =-w= /number/ Fixed field width-- - All fields will be set to this width, padding or truncating as- needed.- - Long option: =--width=- - Default: 0 (variable width)--- =-T= /number/ Maximum total width-- - Maximum total width of the text.- - Long option: =--maxtwidth=- - Default: 0 (no limit)--- =-E= /string/ Maximum total width ellipsis-- - Ellipsis to be added to the total text when it has reached its max- width.- - Long option: =--maxtwidthellipsis=- - Default: "" (no ellipsis)--- =-c= /string/-- - Characters used for padding. The characters of /string/ are used- cyclically. E.g., with =-P +- -w 6=, a field with value "foo" will- be represented as "+-+foo".- - Long option: =--padchars=- - Default value: " "--- =-a= r|l Field alignment-- - Whether to use right (r) or left (l) alignment of field values when- padding.- - Long option: =--align=- - Default value: r (padding to the left)--- =-b= /string/ Bar background-- - Characters used, cyclically, to draw the background of bars. For- instance, if you set this option to "·.", an empty bar will look- like this: =·.·.·.·.·.=- - Long option: =--bback=- - Default value: ":"--- =-f= /string/ Bar foreground-- - Characters used, cyclically, to draw the foreground of bars.- - Long option: =--bfore=- - Default value: "#"--- =-W= /number/ Bar width-- - Total number of characters used to draw bars.- - Long option: =--bwidth=- - Default value: 10- - Special value: 0. When this parameter is 0, the percentage to- display is interpreted as a position in the bar foreground string- (given by =-f=), and the character at that position is displayed.--- =-x= /string/ N/A string-- - String to be used when the monitor is not available- - Long option: =--nastring=- - Default value: "N/A"--Commands' arguments must be set as a list. E.g.:--#+begin_src haskell- Run Weather "EGPF" ["-t", "<station>: <tempC>C"] 36000-#+end_src--In this case xmobar will run the weather monitor, getting information-for the weather station ID EGPF (Glasgow Airport, as a homage to GHC)-every hour (36000 tenth of seconds), with a template that will output-something like:--#+begin_src shell- Glasgow Airport: 16.0C-#+end_src--** Battery Monitors-*** =Battery Args RefreshRate=-- Same as-- #+begin_src haskell- BatteryP ["BAT", "BAT0", "BAT1", "BAT2"] Args RefreshRate- #+end_src--*** =BatteryP Dirs Args RefreshRate=-- - Aliases to =battery=-- - Dirs: list of directories in =/sys/class/power_supply/= where to look- for the ACPI files of each battery. Example: =["BAT0","BAT1","BAT2"]=.- Only up to 3 existing directories will be searched.-- - Args: default monitor arguments, plus the following specific ones- (these options, being specific to the monitor, are to be specified- after a =--= in the argument list):-- - =-O=: string for AC "on" status (default: "On")- - =-i=: string for AC "idle" status (default: "On")- - =-o=: string for AC "off" status (default: "Off")- - =-L=: low power (=watts=) threshold (default: 10)- - =-H=: high power threshold (default: 12)- - =-l=: color to display power lower than the =-L= threshold- - =-m=: color to display power lower than the =-H= threshold- - =-h=: color to display power higher than the =-H= threshold- - =-p=: color to display positive power (battery charging)- - =-f=: file in =/sys/class/power_supply= with AC info (default:- "AC/online")- - =-A=: a number between 0 and 100, threshold below which the action- given by =-a=, if any, is performed (default: 5)- - =-a=: a string with a system command that is run when the percentage- left in the battery is less or equal than the threshold given by the- =-A= option. If not present, no action is undertaken.- - =-P=: to include a percentage symbol in =left=.- - =--on-icon-pattern=: dynamic string for current battery charge when- AC is "on" in =leftipat=.- - =--off-icon-pattern=: dynamic string for current battery charge when- AC is "off" in =leftipat=.- - =--idle-icon-pattern=: dynamic string for current battery charge- when AC is "idle" in =leftipat=.- - =--lows=: string for AC "off" status and power lower than the =-L=- threshold (default: "")- - =--mediums=: string for AC "off" status and power lower than the- =-H= threshold (default: "")- - =--highs=: string for AC "off" status and power higher than the =-H=- threshold (default: "")-- - Variables that can be used with the =-t/--template= argument:- =left=, =leftbar=, =leftvbar=, =leftipat=, =timeleft=, =watts=,- =acstatus=-- - Default template: =Batt: <watts>, <left>% / <timeleft>=-- - Example (note that you need "--" to separate regular monitor options- from Battery's specific ones):-- #+begin_src haskell- Run BatteryP ["BAT0"]- ["-t", "<acstatus><watts> (<left>%)",- "-L", "10", "-H", "80", "-p", "3",- "--", "-O", "<fc=green>On</fc> - ", "-i", "",- "-L", "-15", "-H", "-5",- "-l", "red", "-m", "blue", "-h", "green",- "-a", "notify-send -u critical 'Battery running out!!'",- "-A", "3"]- 600- #+end_src-- In the above example, the thresholds before the =--= separator affect- only the =<left>= and =<leftbar>= fields, while those after the- separator affect how =<watts>= is displayed. For this monitor, neither- the generic nor the specific options have any effect on =<timeleft>=.- We are also telling the monitor to execute the unix command- =notify-send= when the percentage left in the battery reaches 6%.-- It is also possible to specify template variables in the =-O= and =-o=- switches, as in the following example:-- #+begin_src haskell- Run BatteryP ["BAT0"]- ["-t", "<acstatus>"- , "-L", "10", "-H", "80"- , "-l", "red", "-h", "green"- , "--", "-O", "Charging", "-o", "Battery: <left>%"- ] 10- #+end_src-- - The "idle" AC state is selected whenever the AC power entering the- battery is zero.--*** =BatteryN Dirs Args RefreshRate Alias=-- Works like =BatteryP=, but lets you specify an alias for the monitor- other than "battery". Useful in case you one separate monitors for more- than one battery.-** Cpu and Memory Monitors-*** =Cpu Args RefreshRate=-- - Aliases to =cpu=- - Args: default monitor arguments, plus:-- - =--load-icon-pattern=: dynamic string for cpu load in =ipat=-- - Thresholds refer to percentage of CPU load- - Variables that can be used with the =-t/--template= argument:- =total=, =bar=, =vbar=, =ipat=, =user=, =nice=, =system=, =idle=,- =iowait=- - Default template: =Cpu: <total>%=--*** =MultiCpu Args RefreshRate=-- - Aliases to =multicpu=- - Args: default monitor arguments, plus:-- - =--load-icon-pattern=: dynamic string for overall cpu load in- =ipat=.- - =--load-icon-patterns=: dynamic string for each cpu load in- =autoipat=, =ipat{i}=. This option can be specified several times.- nth option corresponds to nth cpu.- - =--fallback-icon-pattern=: dynamic string used by =autoipat= and- =ipat{i}= when no =--load-icon-patterns= has been provided for- =cpu{i}=- - =--contiguous-icons=: flag (no value needs to be provided) that- causes the load icons to be drawn without padding.-- - Thresholds refer to percentage of CPU load- - Variables that can be used with the =-t/--template= argument:- =autototal=, =autobar=, =autovbar=, =autoipat=, =autouser=,- =autonice=, =autosystem=, =autoidle=, =total=, =bar=, =vbar=, =ipat=,- =user=, =nice=, =system=, =idle=, =total0=, =bar0=, =vbar0=, =ipat0=,- =user0=, =nice0=, =system0=, =idle0=, ... The auto* variables- automatically detect the number of CPUs on the system and display one- entry for each.- - Default template: =Cpu: <total>%=--*** =CpuFreq Args RefreshRate=-- - Aliases to =cpufreq=-- - Args: default monitor arguments-- - Thresholds refer to frequency in GHz-- - Variables that can be used with the =-t/--template= argument:- =cpu0=, =cpu1=, .., =cpuN=-- - Default template: =Freq: <cpu0>GHz=-- - This monitor requires acpi_cpufreq module to be loaded in kernel-- - Example:-- #+begin_src haskell- Run CpuFreq ["-t", "Freq:<cpu0>|<cpu1>GHz", "-L", "0", "-H", "2",- "-l", "lightblue", "-n","white", "-h", "red"] 50- #+end_src--*** =CoreTemp Args RefreshRate=-- - Aliases to =coretemp=-- - Args: default monitor arguments-- - Thresholds refer to temperature in degrees-- - Variables that can be used with the =-t/--template= argument:- =core0=, =core1=, .., =coreN=-- - Default template: =Temp: <core0>C=-- - This monitor requires coretemp module to be loaded in kernel-- - Example:-- #+begin_src haskell- Run CoreTemp ["-t", "Temp:<core0>|<core1>C",- "-L", "40", "-H", "60",- "-l", "lightblue", "-n", "gray90", "-h", "red"] 50- #+end_src--*** =MultiCoreTemp Args RefreshRate=-- - Aliases to =multicoretemp=-- - Args: default monitor arguments, plus:-- - =--max-icon-pattern=: dynamic string for overall cpu load in- =maxipat=.- - =--avg-icon-pattern=: dynamic string for overall cpu load in- =avgipat=.- - =--mintemp=: temperature in degree Celsius, that sets the lower- limit for percentage calculation.- - =--maxtemp=: temperature in degree Celsius, that sets the upper- limit for percentage calculation.- - =--hwmon-path=: this monitor tries to find coretemp devices by- looking for them in directories following the pattern- =/sys/bus/platform/devices/coretemp.*/hwmon/hwmon*=, but some- processors (notably Ryzen) might expose those files in a different- tree (e.g., Ryzen) puts them somewhere in "/sys/class/hwmon/hwmon*",- and the lookup is most costly. With this option, it is possible to- explicitly specify the full path to the directory where the- =tempN_label= and =tempN_input= files are located.-- - Thresholds refer to temperature in degree Celsius-- - Variables that can be used with the =-t/--template= argument: =max=,- =maxpc=, =maxbar=, =maxvbar=, =maxipat=, =avg=, =avgpc=, =avgbar=,- =avgvbar=, =avgipat=, =core0=, =core1=, ..., =coreN=-- The /pc, /bar, /vbar and /ipat variables are showing percentages on- the scale defined by =--mintemp= and =--maxtemp=. The max* and avg*- variables to the highest and the average core temperature.-- - Default template: =Temp: <max>°C - <maxpc>%=-- - This monitor requires coretemp module to be loaded in kernel-- - Example:-- #+begin_src haskell- Run MultiCoreTemp ["-t", "Temp: <avg>°C | <avgpc>%",- "-L", "60", "-H", "80",- "-l", "green", "-n", "yellow", "-h", "red",- "--", "--mintemp", "20", "--maxtemp", "100"] 50- #+end_src--*** =K10Temp Slot Args RefreshRate=-- - Aliases to =k10temp=-- - Slot: The PCI slot address of the k10temp device as a string. You- can find it as a subdirectory in =/sys/bus/pci/drivers/k10temp/=.-- - Args: default monitor arguments-- - Thresholds refer to temperature in degrees-- - Variables that can be used with the =-t/--template= argument:- =Tctl=, =Tdie=, =Tccd1=, .., =Tccd8=-- - Default template: =Temp: <Tdie>C=-- - This monitor requires k10temp module to be loaded in kernel-- - It is important to note that not all measurements are available- on on all models of processor. Of particular importance - Tdie- (used in the default template) may not be present on processors- prior to Zen (17h). Tctl, however, may be offset from the real- temperature and so is not used by default.-- - Example:-- #+begin_src haskell- Run K10Temp "0000:00:18.3"- ["-t", "Temp: <Tdie>C|<Tccd1>C",- "-L", "40", "-H", "60",- "-l", "lightblue", "-n", "gray90", "-h", "red"]- 50- #+end_src---*** =Memory Args RefreshRate=-- - Aliases to =memory=- - Args: default monitor arguments, plus:-- - =--used-icon-pattern=: dynamic string for used memory ratio in- =usedipat=.- - =--free-icon-pattern=: dynamic string for free memory ratio in- =freeipat=.- - =--available-icon-pattern=: dynamic string for available memory- ratio in =availableipat=.-- - Thresholds refer to percentage of used memory- - Variables that can be used with the =-t/--template= argument:- =total=, =free=, =buffer=, =cache=, =available=, =used=, =usedratio=,- =usedbar=, =usedvbar=, =usedipat=, =freeratio=, =freebar=, =freevbar=,- =freeipat=, =availableratio=, =availablebar=, =availablevbar=,- =availableipat=- - Default template: =Mem: <usedratio>% (<cache>M)=--*** =Swap Args RefreshRate=-- - Aliases to =swap=- - Args: default monitor arguments- - Thresholds refer to percentage of used swap- - Variables that can be used with the =-t/--template= argument:- =total=, =used=, =free=, =usedratio=- - Default template: =Swap: <usedratio>%=-** Date Monitors-*** =Date Format Alias RefreshRate=-- - Format is a time format string, as accepted by the standard ISO C- =strftime= function (or Haskell's =formatCalendarTime=). Basically,- if =date +"my-string"= works with your command then =Date= will handle- it correctly.-- - Timezone changes are picked up automatically every minute.-- - Sample usage:-- #+begin_src haskell- Run Date "%a %b %_d %Y <fc=#ee9a00>%H:%M:%S</fc>" "date" 10- #+end_src--*** =DateZone Format Locale Zone Alias RefreshRate=-- A variant of the =Date= monitor where one is able to explicitly set the- time-zone, as well as the locale.-- - The format of =DateZone= is exactly the same as =Date=.-- - If =Locale= is =""= (the empty string) the default locale of the- system is used, otherwise use the given locale. If there are more- instances of =DateZone=, using the empty string as input for =Locale=- is not recommended.-- - =Zone= is the name of the =TimeZone=. It is assumed that the time-zone- database is stored in =/usr/share/zoneinfo/=. If the empty string is- given as =Zone=, the default system time is used.-- - Sample usage:-- #+begin_src haskell- Run DateZone "%a %H:%M:%S" "de_DE.UTF-8" "Europe/Vienna" "viennaTime" 10- #+end_src-** Disk Monitors-*** =DiskU Disks Args RefreshRate=-- - Aliases to =disku=-- - Disks: list of pairs of the form (device or mount point, template),- where the template can contain =<size>=, =<free>=, =<used>=, =<freep>=- or =<usedp>=, =<freebar>=, =<freevbar>=, =<freeipat>=, =<usedbar>=,- =<usedvbar>= or =<usedipat>= for total, free, used, free percentage- and used percentage of the given file system capacity.-- - Thresholds refer to usage percentage.-- - Args: default monitor arguments. =-t/--template= is ignored. Plus-- - =--free-icon-pattern=: dynamic string for free disk space in- =freeipat=.- - =--used-icon-pattern=: dynamic string for used disk space in- =usedipat=.-- - Default template: none (you must specify a template for each file- system).-- - Example:-- #+begin_src haskell- DiskU [("/", "<used>/<size>"), ("sdb1", "<usedbar>")]- ["-L", "20", "-H", "50", "-m", "1", "-p", "3"]- 20- #+end_src--*** =DiskIO Disks Args RefreshRate=-- - Aliases to =diskio=-- - Disks: list of pairs of the form (device or mount point, template),- where the template can contain =<total>=, =<read>=, =<write>= for- total, read and write speed, respectively, as well as =<totalb>=,- =<readb>=, =<writeb>=, which report number of bytes during the last- refresh period rather than speed. There are also bar versions of each:- =<totalbar>=, =<totalvbar>=, =<totalipat>=, =<readbar>=, =<readvbar>=,- =<readipat>=, =<writebar>=, =<writevbar>=, and =<writeipat>=; and- their "bytes" counterparts: =<totalbbar>=, =<totalbvbar>=,- =<totalbipat>=, =<readbbar>=, =<readbvbar>=, =<readbipat>=,- =<writebbar>=, =<writebvbar>=, and =<writebipat>=.-- - Thresholds refer to speed in b/s-- - Args: default monitor arguments. =-t/--template= is ignored. Plus-- - =--total-icon-pattern=: dynamic string for total disk I/O in- =<totalipat>=.- - =--write-icon-pattern=: dynamic string for write disk I/O in- =<writeipat>=.- - =--read-icon-pattern=: dynamic string for read disk I/O in- =<readipat>=.-- - Default template: none (you must specify a template for each file- system).-- - Example:-- #+begin_src haskell- DiskIO [("/", "<read> <write>"), ("sdb1", "<total>")] [] 10- #+end_src--** Keyboard Monitors-*** =Kbd Opts=-- - Registers to XKB/X11-Events and output the currently active keyboard- layout. Supports replacement of layout names.-- - Aliases to =kbd=-- - Opts is a list of tuples:-- - first element of the tuple is the search string- - second element of the tuple is the corresponding replacement-- - Example:-- #+begin_src haskell- Run Kbd [("us(dvorak)", "DV"), ("us", "US")]- #+end_src--*** =Locks=-- - Displays the status of Caps Lock, Num Lock and Scroll Lock.-- - Aliases to =locks=-- - Example:-- #+begin_src haskell- Run Locks- #+end_src-** Process Monitors-*** =TopProc Args RefreshRate=-- - Aliases to =top=- - Args: default monitor arguments. The low and high thresholds (=-L= and- =-H=) denote, for memory entries, the percent of the process memory- over the total amount of memory currently in use and, for cpu entries,- the activity percentage (i.e., the value of =cpuN=, which takes values- between 0 and 100).- - Variables that can be used with the =-t/--template= argument: =no=,- =name1=, =cpu1=, =both1=, =mname1=, =mem1=, =mboth1=, =name2=, =cpu2=,- =both2=, =mname2=, =mem2=, =mboth2=, ...- - Default template: =<both1>=- - Displays the name and cpu/mem usage of running processes (=bothn= and- =mboth= display both, and is useful to specify an overall maximum- and/or minimum width, using the =-m/-M= arguments. =no= gives the- total number of processes.--*** =TopMem Args RefreshRate=-- - Aliases to =topmem=- - Args: default monitor arguments. The low and high thresholds (=-L= and- =-H=) denote the percent of the process memory over the total amount- of memory currently in use.- - Variables that can be used with the =-t/--template= argument:- =name1=, =mem1=, =both1=, =name2=, =mem2=, =both2=, ...- - Default template: =<both1>=- - Displays the name and RSS (resident memory size) of running processes- (=bothn= displays both, and is useful to specify an overall maximum- and/or minimum width, using the =-m/-M= arguments.-** Thermal Monitors-*** =ThermalZone Number Args RefreshRate=-- - Aliases to "thermaln": so =ThermalZone 0 []= can be used in template- as =%thermal0%=-- - Thresholds refer to temperature in degrees-- - Args: default monitor arguments-- - Variables that can be used with the =-t/--template= argument: =temp=-- - Default template: =<temp>C=-- - This plugin works only on systems with devices having thermal zone.- Check directories in =/sys/class/thermal= for possible values of the- zone number (e.g., 0 corresponds to =thermal_zone0= in that- directory).-- - Example:-- #+begin_src haskell- Run ThermalZone 0 ["-t","<id>: <temp>C"] 30- #+end_src--*** =Thermal Zone Args RefreshRate=-- - *This plugin is deprecated. Use =ThermalZone= instead.*-- - Aliases to the Zone: so =Thermal "THRM" []= can be used in template as- =%THRM%=-- - Args: default monitor arguments-- - Thresholds refer to temperature in degrees-- - Variables that can be used with the =-t/--template= argument: =temp=-- - Default template: =Thm: <temp>C=-- - This plugin works only on systems with devices having thermal zone.- Check directories in /proc/acpi/thermal_zone for possible values.-- - Example:-- #+begin_src haskell- Run Thermal "THRM" ["-t","iwl4965-temp: <temp>C"] 50- #+end_src-** Volume Monitors-*** =Volume Mixer Element Args RefreshRate=-- - Aliases to the mixer name and element name separated by a colon. Thus,- =Volume "default" "Master" [] 10= can be used as =%default:Master%=.- - Args: default monitor arguments. Also accepts:-- - =-O= /string/ On string-- - The string used in place of =<status>= when the mixer element is- on. Defaults to "[on]".- - Long option: =--on=-- - =-o= /string/ Off string-- - The string used in place of =<status>= when the mixer element is- off. Defaults to "[off]".- - Long option: =--off=-- - =-C= /color/ On color-- - The color to be used for =<status>= when the mixer element is on.- Defaults to "green".- - Long option: =--onc=-- - =-c= /color/ Off color-- - The color to be used for =<status>= when the mixer element is off.- Defaults to "red".- - Long option: =--offc=-- - =--highd= /number/ High threshold for dB. Defaults to -5.0.- - =--lowd= /number/ Low threshold for dB. Defaults to -30.0.- - =--volume-icon-pattern= /string/ dynamic string for current volume- in =volumeipat=.- - =-H= /number/ High threshold for volume (in %). Defaults to 60.0.-- - Long option: =--highv=-- - =-L= /number/ Low threshold for volume (in %). Defaults to 20.0.-- - Long option: =--lowv=-- - =-h=: /string/ High string-- - The string added in front of =<status>= when the mixer element is- on and the volume percentage is higher than the =-H= threshold.- Defaults to "".- - Long option: =--highs=-- - =-m=: /string/ Medium string-- - The string added in front of =<status>= when the mixer element is- on and the volume percentage is lower than the =-H= threshold.- Defaults to "".- - Long option: =--mediums=-- - =-l=: /string/ Low string-- - The string added in front of =<status>= when the mixer element is- on and the volume percentage is lower than the =-L= threshold.- Defaults to "".- - Long option: =--lows=-- - Variables that can be used with the =-t/--template= argument:- =volume=, =volumebar=, =volumevbar=, =volumeipat=, =dB=, =status=,- =volumestatus=- - Note that =dB= might only return 0 on your system. This is known to- happen on systems with a pulseaudio backend.- - Default template: =Vol: <volume>% <status>=- - Requires the package [[http://hackage.haskell.org/package/alsa-core][alsa-core]] and [[http://hackage.haskell.org/package/alsa-mixer][alsa-mixer]] installed in your- system. In addition, to activate this plugin you must pass the- =with_alsa= flag during compilation.--*** =Alsa Mixer Element Args=-- Like [[=Volume Mixer Element Args RefreshRate=][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- use CPU until a change happens.- - Aliases to =alsa:= followed by the mixer name and element name- separated by a colon. Thus, =Alsa "default" "Master" []= can be used- as =%alsa:default:Master%=.- - Additional options (after the =--=):- - =--alsactl=/path/to/alsactl=: If this option is not specified,- =alsactl= will be sought in your =PATH= first, and failing that, at- =/usr/sbin/alsactl= (this is its location on Debian systems.- =alsactl monitor= works as a non-root user despite living in- =/usr/sbin=.).- - =stdbuf= (from coreutils) must be (and most probably already is) in- your =PATH=.-** Mail Monitors-*** =Mail Args Alias=-- - Args: list of maildirs in form =[("name1","path1"),...]=. Paths may- start with a '~' to expand to the user's home directory.-- - This plugin requires inotify support in your Linux kernel and the- [[http://hackage.haskell.org/package/hinotify/][hinotify]] package. To activate, pass the =with_inotify= flag during- compilation.-- - Example:-- #+begin_src haskell- Run Mail [("inbox", "~/var/mail/inbox"),- ("lists", "~/var/mail/lists")]- "mail"- #+end_src--*** =MailX Args Opts Alias=-- - Args: list of maildirs in form =[("name1","path1","color1"),...]=.- Paths may start with a '~' to expand to the user's home directory.- When mails are present, counts are displayed with the given name and- color.-- - Opts is a possibly empty list of options, as flags. Possible values:- -d dir --dir dir a string giving the base directory where maildir- files with a relative path live. -p prefix --prefix prefix a string- giving a prefix for the list of displayed mail counts -s suffix- --suffix suffix a string giving a suffix for the list of displayed- mail counts-- - This plugin requires inotify support in your Linux kernel and the- [[http://hackage.haskell.org/package/hinotify/][hinotify]] package. To activate, pass the =with_inotify= flag during- compilation.-- - Example:-- #+begin_src haskell- Run MailX [("I", "inbox", "green"),- ("L", "lists", "orange")]- ["-d", "~/var/mail", "-p", " ", "-s", " "]- "mail"- #+end_src--*** =MBox Mboxes Opts Alias=-- - Mboxes a list of mbox files of the form =[("name", "path", "color")]=,- where name is the displayed name, path the absolute or relative (to- BaseDir) path of the mbox file, and color the color to use to display- the mail count (use an empty string for the default).-- - Opts is a possibly empty list of options, as flags. Possible values:- -a --all (no arg) Show all mailboxes, even if empty. -u (no arg) Show- only the mailboxes' names, sans counts. -d dir --dir dir a string- giving the base directory where mbox files with a relative path live.- -p prefix --prefix prefix a string giving a prefix for the list of- displayed mail counts -s suffix --suffix suffix a string giving a- suffix for the list of displayed mail counts-- - Paths may start with a '~' to expand to the user's home directory.-- - This plugin requires inotify support in your Linux kernel and the- [[http://hackage.haskell.org/package/hinotify/][hinotify]] package. To activate, pass the =with_inotify= flag during- compilation.-- - Example. The following command look for mails in =/var/mail/inbox= and- =~/foo/mbox=, and will put a space in front of the printed string- (when it's not empty); it can be used in the template with the alias- =mbox=:-- #+begin_src haskell- Run MBox [("I ", "inbox", "red"), ("O ", "~/foo/mbox", "")]- ["-d", "/var/mail/", "-p", " "] "mbox"- #+end_src--*** =NotmuchMail Alias Args Rate=-- This plugin checks for new mail, provided that this mail is indexed by- =notmuch=. In the =notmuch= spirit, this plugin checks for new *threads*- and not new individual messages.-- - Alias: What name the plugin should have in your template string.-- - Args: A list of =MailItem= s of the form-- #+begin_src haskell- [ MailItem "name" "address" "query"- ...- ]- #+end_src-- where-- - =name= is what gets printed in the status bar before the number of- new threads.- - =address= is the e-mail address of the recipient, i.e. we only query- mail that was send to this particular address (in more concrete- terms, we pass the address to the =to:= constructor when performing- the search). If =address= is empty, we search through all unread- mail, regardless of whom it was sent to.- - =query= is funneled to =notmuch search= verbatim. For the general- query syntax, consult =notmuch search --help=, as well as- =notmuch-search-terms(7)=. Note that the =unread= tag is *always*- added in front of the query and composed with it via an *and*.-- - Rate: Rate with which to update the plugin (in deciseconds).-- - Example:-- - A single =MailItem= that displays all unread threads from the given- address:-- #+begin_src haskell- MailItem "mbs:" "soliditsallgood@mailbox.org" ""- #+end_src-- - A single =MailItem= that displays all unread threads with- "[My-Subject]" somewhere in the title:-- #+begin_src haskell- MailItem "S:" "" "subject:[My-Subject]"- #+end_src-- - A full example of a =NotmuchMail= configuration:-- #+begin_src haskell- Run NotmuchMail "mail" -- name for the template string- [ -- All unread mail to the below address, but nothing that's tagged- -- with @lists@ or @haskell@.- MailItem "mbs:"- "soliditsallgood@mailbox.org"- "not tag:lists and not tag:haskell"-- -- All unread mail that has @[Haskell-Cafe]@ in the subject line.- , MailItem "C:" "" "subject:[Haskell-Cafe]"-- -- All unread mail that's tagged as @lists@, but not @haskell@.- , MailItem "H:" "" "tag:lists and not tag:haskell"- ]- 600 -- update every 60 seconds- #+end_src--** Music Monitors-*** =MPD Args RefreshRate=-- - This monitor will only be compiled if you ask for it using the- =with_mpd= flag. It needs [[http://hackage.haskell.org/package/libmpd/][libmpd]] 5.0 or later (available on Hackage).-- - Aliases to =mpd=-- - Args: default monitor arguments. In addition you can provide =-P=,- =-S= and =-Z=, with an string argument, to represent the playing,- stopped and paused states in the =statei= template field. The- environment variables =MPD_HOST= and =MPD_PORT= are used to configure- the mpd server to communicate with, unless given in the additional- arguments =-p= (=--port=) and =-h= (=--host=). Also available:-- - =lapsed-icon-pattern=: dynamic string for current track position in- =ipat=.-- - Variables that can be used with the =-t/--template= argument: =bar=,- =vbar=, =ipat=, =state=, =statei=, =volume=, =length=, =lapsed=,- =remaining=, =plength= (playlist length), =ppos= (playlist position),- =flags= (ncmpcpp-style playback mode), =name=, =artist=, =composer=,- =performer=, =album=, =title=, =track=, =file=, =genre=, =date=-- - Default template: =MPD: <state>=-- - Example (note that you need "--" to separate regular monitor options- from MPD's specific ones):-- #+begin_src haskell- Run MPD ["-t",- "<composer> <title> (<album>) <track>/<plength> <statei> [<flags>]",- "--", "-P", ">>", "-Z", "|", "-S", "><"] 10- #+end_src--*** =MPDX Args RefreshRate Alias=-- Like =MPD= but uses as alias its last argument instead of "mpd".--*** =Mpris1 PlayerName Args RefreshRate=-- - Aliases to =mpris1=-- - Requires [[http://hackage.haskell.org/package/dbus][dbus]] and [[http://hackage.haskell.org/package/text][text]] packages. To activate, pass the =with_mpris=- flag during compilation.-- - PlayerName: player supporting MPRIS v1 protocol. Some players need- this to be an all lowercase name (e.g. "spotify"), but some others- don't.-- - Args: default monitor arguments.-- - Variables that can be used with the =-t/--template= argument:- =album=, =artist=, =arturl=, =length=, =title=, =tracknumber=-- - Default template: =<artist> - <title>=-- - Example:-- #+begin_src haskell- Run Mpris1 "clementine" ["-t", "<artist> - [<tracknumber>] <title>"] 10- #+end_src--*** =Mpris2 PlayerName Args RefreshRate=-- - Aliases to =mpris2=-- - Requires [[http://hackage.haskell.org/package/dbus][dbus]] and [[http://hackage.haskell.org/package/text][text]] packages. To activate, pass the =with_mpris=- flag during compilation.-- - PlayerName: player supporting MPRIS v2 protocol. Some players need- this to be an all lowercase name (e.g. "spotify"), but some others- don't.-- - Args: default monitor arguments.-- - Variables that can be used with the =-t/--template= argument:- =album=, =artist=, =arturl=, =length=, =title=, =tracknumber=,- =composer=, =genre=-- - Default template: =<artist> - <title>=-- - Example:-- #+begin_src haskell- Run Mpris2 "spotify" ["-t", "<artist> - [<composer>] <title>"] 10- #+end_src-** Network Monitors-*** =Network Interface Args RefreshRate=-- - Aliases to the interface name: so =Network "eth0" []= can be used as- =%eth0%=- - Thresholds refer to velocities expressed in Kb/s- - Args: default monitor arguments, plus:-- - =--rx-icon-pattern=: dynamic string for reception rate in =rxipat=.- - =--tx-icon-pattern=: dynamic string for transmission rate in- =txipat=.- - =--up=: string used for the =up= variable value when the interface- is up.-- - Variables that can be used with the =-t=/=--template= argument: =dev=,- =rx=, =tx=, =rxbar=, =rxvbar=, =rxipat=, =txbar=, =txvbar=, =txipat=,- =up=. Reception and transmission rates (=rx= and =tx=) are displayed- by default as Kb/s, without any suffixes, but you can set the =-S= to- "True" to make them displayed with adaptive units (Kb/s, Mb/s, etc.).- - Default template: =<dev>: <rx>KB|<tx>KB=--*** =DynNetwork Args RefreshRate=-- - Active interface is detected automatically- - Aliases to "dynnetwork"- - Thresholds are expressed in Kb/s- - Args: default monitor arguments, plus:-- - =--rx-icon-pattern=: dynamic string for reception rate in =rxipat=.- - =--tx-icon-pattern=: dynamic string for transmission rate in =txipat=- - =--devices=: comma-separated list of devices to show.-- - Variables that can be used with the =-t=/=--template= argument:- =dev=, =rx=, =tx=, =rxbar=, =rxvbar=, =rxipat=, =txbar=, =txvbar=,- =txipat=.-- Reception and transmission rates (=rx= and =tx=) are displayed in Kbytes- per second, and you can set the =-S= to "True" to make them displayed- with units (the string "Kb/s").- - Default template: =<dev>: <rx>KB|<tx>KB=- - Example of usage of =--devices= option:-- =["--", "--devices", "wlp2s0,enp0s20f41"]=--*** =Wireless Interface Args RefreshRate=-- - If set to "", first suitable wireless interface is used.- - Aliases to the interface name with the suffix "wi": thus,- =Wireless "wlan0" []= can be used as =%wlan0wi%=, and- =Wireless "" []= as =%wi%=.- - Args: default monitor arguments, plus:-- - =--quality-icon-pattern=: dynamic string for connection quality in- =qualityipat=.-- - Variables that can be used with the =-t=/=--template= argument:- =ssid=, =signal=, =quality=, =qualitybar=, =qualityvbar=,- =qualityipat=- - Thresholds refer to link quality on a =[0, 100]= scale. Note that- =quality= is calculated from =signal= (in dBm) by a possibly lossy- conversion. It is also not taking into account many factors such as- noise level, air busy time, transcievers' capabilities and the others- which can have drastic impact on the link performance.- - Default template: =<ssid> <quality>=- - To activate this plugin you must pass the =with_nl80211= or the- =with_iwlib= flag during compilation.-** Weather Monitors-*** =Weather StationID Args RefreshRate=-- - Aliases to the Station ID: so =Weather "LIPB" []= can be used in- template as =%LIPB%=- - Thresholds refer to temperature in the selected units- - Args: default monitor arguments, plus:-- - =--weathers= /string/ : display a default string when the =weather=- variable is not reported.-- - short option: =-w=- - Default: ""-- - =--useManager= /bool/ : Whether to use one single manager per- monitor for managing network connections or create a new one every- time a connection is made.-- - Short option: =-m=- - Default: True-- - Variables that can be used with the =-t/--template= argument:- =station=, =stationState=, =year=, =month=, =day=, =hour=,- =windCardinal=, =windAzimuth=, =windMph=, =windKnots=, =windMs=,- =windKmh= =visibility=, =skyCondition=, =weather=, =tempC=, =tempF=,- =dewPointC=, =dewPointF=, =rh=, =pressure=- - Default template: =<station>: <tempC>C, rh <rh>% (<hour>)=- - Retrieves weather information from http://tgftp.nws.noaa.gov. Here is- an [[https://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYLD.TXT][example]], also showcasing the kind of information that may be- extracted. Here is [[https://weather.rap.ucar.edu/surface/stations.txt][a sample list of station IDs]].--*** =WeatherX StationID SkyConditions Args RefreshRate=-- - Works in the same way as =Weather=, but takes an additional argument,- a list of pairs from sky conditions to their replacement (typically a- unicode string or an icon specification).- - Use the variable =skyConditionS= to display the replacement of the- corresponding sky condition. All other =Weather= template variables- are available as well.-- For example:-- #+begin_src haskell- WeatherX "LEBL"- [ ("clear", "🌣")- , ("sunny", "🌣")- , ("mostly clear", "🌤")- , ("mostly sunny", "🌤")- , ("partly sunny", "⛅")- , ("fair", "🌑")- , ("cloudy","☁")- , ("overcast","☁")- , ("partly cloudy", "⛅")- , ("mostly cloudy", "🌧")- , ("considerable cloudiness", "⛈")]- ["-t", "<fn=2><skyConditionS></fn> <tempC>° <rh>% <windKmh> (<hour>)"- , "-L","10", "-H", "25", "--normal", "black"- , "--high", "lightgoldenrod4", "--low", "darkseagreen4"]- 18000- #+end_src-- As mentioned, the replacement string can also be an icon specification,- such as =("clear", "<icon=weather-clear.xbm/>")=.-** Other Monitors-*** =Brightness Args RefreshRate=-- - Aliases to =bright=-- - Args: default monitor arguments, plus the following specif ones:-- - =-D=: directory in =/sys/class/backlight/= with files in it- (default: "acpi_video0")- - =-C=: file with the current brightness (default: actual_brightness)- - =-M=: file with the maximum brightness (default: max_brightness)- - =--brightness-icon-pattern=: dynamic string for current brightness- in =ipat=.-- - Variables that can be used with the =-t/--template= argument:- =vbar=, =percent=, =bar=, =ipat=-- - Default template: =<percent>=-- - Example:-- #+begin_src haskell- Run Brightness ["-t", "<bar>"] 60- #+end_src--*** =CatInt n filename=-- - Reads and displays an integer from the file whose path is =filename=- (especially useful with files in =/sys=).-- - Aliases as =catn= (e.g. =Cat 0= as =cat0=, etc.) so you can have- several.-- - Example:-- #+begin_src haskell- Run CatInt 0 "/sys/devices/platform/thinkpad_hwmon/fan1_input" [] 50- #+end_src--*** =CommandReader "/path/to/program" Alias=-- - Runs the given program, and displays its standard output.--*** =Uptime Args RefreshRate=-- - Aliases to =uptime=- - Args: default monitor arguments. The low and high thresholds refer to- the number of days.- - Variables that can be used with the =-t/--template= argument: =days=,- =hours=, =minutes=, =seconds=. The total uptime is the sum of all- those fields. You can set the =-S= argument to =True= to add units to- the display of those numeric fields.- - Default template: =Up: <days>d <hours>h <minutes>m=--*** =UVMeter=-- - Aliases to "uv" + station id. For example: =%uv Brisbane%= or- =%uv Alice Springs%=-- - Args: default monitor arguments, plus:-- - =--useManager= /bool/ : Whether to use one single manager per- monitor for managing network connections or create a new one every- time a connection is made.-- - Short option: =-m=- - Default: True-- - /Reminder:/ Keep the refresh rate high, to avoid making unnecessary- requests every time the plug-in is run.-- - Station IDs can be found here:- http://www.arpansa.gov.au/uvindex/realtime/xml/uvvalues.xml-- - Example:-- #+begin_src haskell- Run UVMeter "Brisbane" ["-H", "3", "-L", "3", "--low", "green", "--high", "red"] 900- #+end_src--* Interfacing with Window Managers-- Listed below are ways to interface xmobar with your window manager- of choice.--** Property-based Logging-*** =XMonadLog=-- - Aliases to XMonadLog-- - Displays information from xmonad's =_XMONAD_LOG=. You can use this by- using functions from the [[https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/XMonad-Hooks-DynamicLog.html][XMonad.Hooks.DynamicLog]] module. By using the- =xmonadPropLog= function in your logHook, you can write the the above- property. The following shows a minimal xmonad configuration that- spawns xmobar and then writes to the =_XMONAD_LOG= property.-- #+begin_src haskell- main = do- spawn "xmobar"- xmonad $ def- { logHook = dynamicLogString defaultPP >>= xmonadPropLog- }- #+end_src-- This plugin can be used as a sometimes more convenient alternative to- =StdinReader=. For instance, it allows you to (re)start xmobar outside- xmonad.--*** =UnsafeXMonadLog=-- - Aliases to UnsafeXMonadLog- - Displays any text received by xmobar on the =_XMONAD_LOG= atom.- - Will not do anything to the text received. This means you can pass- xmobar dynamic actions. Be careful to escape (using =<raw=…>=) or- remove tags from dynamic text that you pipe through to xmobar in this- way.-- - Sample usage: Send the list of your workspaces, enclosed by actions- tags, to xmobar. This enables you to switch to a workspace when you- click on it in xmobar!-- #+begin_src shell- <action=`xdotool key alt+1`>ws1</action> <action=`xdotool key alt+1`>ws2</action>- #+end_src-- - If you use xmonad, It is advised that you still use =xmobarStrip= for- the =ppTitle= in your logHook:-- #+begin_src haskell- myPP = defaultPP { ppTitle = xmobarStrip }- main = xmonad $ def- { logHook = dynamicLogString myPP >>= xmonadPropLog- }- #+end_src--*** =XPropertyLog PropName=-- - Aliases to =PropName=- - Reads the X property named by =PropName= (a string) and displays its- value. The [[https://github.com/jaor/xmobar/raw/master/examples/xmonadpropwrite.hs][examples/xmonadpropwrite.hs script]] in xmobar's distribution- can be used to set the given property from the output of any other- program or script.--*** =UnsafeXPropertyLog PropName=-- - Aliases to =PropName=- - Same as =XPropertyLog= but the input is not filtered to avoid- injection of actions (cf. =UnsafeXMonadLog=). The program writing the- value of the read property is responsible of performing any needed- cleanups.--*** =NamedXPropertyLog PropName Alias=-- - Aliases to =Alias=- - Same as =XPropertyLog= but a custom alias can be specified.--*** =UnsafeNamedXPropertyLog PropName Alias=-- - Aliases to =Alias=- - Same as =UnsafeXPropertyLog=, but a custom alias can be specified.--** Logging via Stdin-*** =StdinReader=-- - Aliases to StdinReader- - Displays any text received by xmobar on its standard input.- - Strips actions from the text received. This means you can't pass- dynamic actions via stdin. This is safer than =UnsafeStdinReader=- because there is no need to escape the content before passing it to- xmobar's standard input.--*** =UnsafeStdinReader=-- - 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- 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=!--** Pipe-based Logging-*** =PipeReader "default text:/path/to/pipe" Alias=-- - Reads its displayed output from the given pipe.- - Prefix an optional default text separated by a colon- - Expands environment variables in the first argument of syntax =${VAR}=- or =$VAR=--*** =MarqueePipeReader "default text:/path/to/pipe" (length, rate, sep) Alias=-- - Generally equivalent to PipeReader-- - Text is displayed as marquee with the specified length, rate in 10th- seconds and separator when it wraps around-- #+begin_src haskell- Run MarqueePipeReader "/tmp/testpipe" (10, 7, "+") "mpipe"- #+end_src-- - Expands environment variables in the first argument--*** =BufferedPipeReader Alias [(Timeout, Bool, "/path/to/pipe1"), ..]=-- - Display data from multiple pipes.-- - Timeout (in tenth of seconds) is the value after which the previous- content is restored i.e. if there was already something from a- previous pipe it will be put on display again, overwriting the current- status.-- - A pipe with Timeout of 0 will be displayed permanently, just like- =PipeReader=-- - The boolean option indicates whether new data for this pipe should- make xmobar appear (unhide, reveal). In this case, the Timeout- additionally specifies when the window should be hidden again. The- output is restored in any case.-- - Use it for OSD-like status bars e.g. for setting the volume or- brightness:-- #+begin_src haskell- Run BufferedPipeReader "bpr"- [ ( 0, False, "/tmp/xmobar_window" )- , ( 15, True, "/tmp/xmobar_status" )- ]- #+end_src-- Have your window manager send window titles to =/tmp/xmobar_window=.- They will always be shown and not reveal your xmobar. Sending some- status information to =/tmp/xmobar_status= will reveal xmonad for 1.5- seconds and temporarily overwrite the window titles.-- - Take a look at [[http://github.com/jaor/xmobar/raw/master/examples/status.sh][examples/status.sh]]-- - Expands environment variables for the pipe path--** Handle-based Logging-*** =HandleReader Handle Alias=-- - Display data from a Haskell =Handle=-- - This plugin is only useful if you are running xmobar from another- Haskell program like XMonad.-- - You can use =System.Process.createPipe= to create a pair of =read= &- =write= Handles. Pass the =read= Handle to HandleReader and write your- output to the =write= Handle:-- #+begin_src haskell- (readHandle, writeHandle) <- createPipe- xmobarProcess <- forkProcess $ xmobar myConfig- { commands =- Run (HandleReader readHandle "handle") : commands myConfig- }- hPutStr writeHandle "Hello World"- #+end_src--** Software Transactional Memory-- When invoking xmobar from other Haskell code it can be easier and- more performant to use shared memory. The following plugins- leverage =Control.Concurrent.STM= to realize these gains for xmobar.--*** =QueueReader (TQueue a) (a -> String) String=-- - Display data from a Haskell =TQueue a=.-- - This plugin is only useful if you are running xmobar from another- haskell program like xmonad.-- - You should make an =IO= safe =TQueue a= with =Control.Concurrent.STM.newTQueueIO=.- Write to it from the user code with =writeTQueue=, and read with =readTQueue=.- A common use is to overwite =ppOutput= from =XMonad.Hooks.DynamicLog= as shown- below.-- #+begin_src haskell- main :: IO ()- main = do- q <- STM.newTQueueIO @String- bar <- forkIO $ xmobar myConf- { commands = Run (QueueReader q id "XMonadLog") : commands myConf }- xmonad $ def { logHook = logWorkspacesToQueue q }-- logWorkspacesToQueue :: STM.TQueue String -> X ()- logWorkspacesToQueue q =- dynamicLogWithPP def { ppOutput = STM.atomically . STM.writeTQueue q }- where- -- Manage the PrettyPrinting configuration here.- ppLayout' :: String -> String- ppLayout' "Spacing Tall" = xpm "layout-spacing-tall"- ppLayout' "Spacing Mirror Tall" = xpm "layout-spacing-mirror"- ppLayout' "Spacing Full" = xpm "layout-full"- ppLayout' x = x-- icon :: String -> String- icon path = "<icon=" ++ path ++ "/>"-- xpm :: String -> String- xpm = icon . (++ ".xpm")- #+end_src--* Executing External Commands-- In order to execute an external command you can either write the- command name in the template, in this case it will be executed- without arguments, or you can configure it in the "commands"- configuration option list with the Com template command:-- =Com ProgramName Args Alias RefreshRate=-- - ProgramName: the name of the program- - Args: the arguments to be passed to the program at execution time- - RefreshRate: number of tenths of second between re-runs of the- command. A zero or negative rate means that the command will be- executed only once.- - Alias: a name to be used in the template. If the alias is en empty- string the program name can be used in the template.-- E.g.:-- #+begin_src haskell- Run Com "uname" ["-s","-r"] "" 0- #+end_src-- can be used in the output template as =%uname%= (and xmobar will call- /uname/ only once), while-- #+begin_src haskell- Run Com "date" ["+\"%a %b %_d %H:%M\""] "mydate" 600- #+end_src-- can be used in the output template as =%mydate%=.-- Sometimes, you don't mind if the command executed exits with an- error, or you might want to display a custom message in that- case. To that end, you can use the =ComX= variant:-- =ComX ProgramName Args ExitMessage Alias RefreshRate=-- Works like =Com=, but displaying =ExitMessage= (a string) if the- execution fails. For instance:-- #+begin_src haskell- Run ComX "date" ["+\"%a %b %_d %H:%M\""] "N/A" "mydate" 600- #+end_src-- will display "N/A" if for some reason the =date= invocation fails.--* The DBus Interface-- When compiled with the optional =with_dbus= flag, xmobar can be- controlled over dbus. All signals defined in [[https://github.com/jaor/xmobar/blob/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 can- acquire the dbus. This is handled on a first-come-first-served- basis, meaning that the first process will get the dbus- interface. Other processes will run without further problems, yet- have no dbus interface.-- - Bus Name: =org.Xmobar.Control=- - Object Path: =/org/Xmobar/Control=- - Member Name: Any of SignalType, e.g. =string:Reveal=- - Interface Name: =org.Xmobar.Control=-- An example using the =dbus-send= command line utility:-- #+begin_src shell- dbus-send \- --session \- --dest=org.Xmobar.Control \- --type=method_call \- --print-reply \- '/org/Xmobar/Control' \- org.Xmobar.Control.SendSignal \- "string:Toggle 0"- #+end_src-- It is also possible to send multiple signals at once:-- #+begin_src shell- # send to another screen, reveal and toggle the persistent flag- dbus-send [..] \- "string:ChangeScreen 0" "string:Reveal 0" "string:TogglePersistent"- #+end_src-- The =Toggle=, =Reveal=, and =Hide= signals take an additional integer- argument that denotes an initial delay, in tenths of a second,- before the command takes effect.--** Example for using the DBus IPC interface with XMonad-- Bind the key which should {,un}map xmobar to a dummy value. This is- necessary for {,un}grabKey in xmonad.-- #+begin_src haskell- ((0, xK_Alt_L), pure ())- #+end_src-- Also, install =avoidStruts= layout modifier from- =XMonad.Hooks.ManageDocks=-- Finally, install these two event hooks (=handleEventHook= in =XConfig=)- =myDocksEventHook= is a replacement for =docksEventHook= which reacts- on unmap events as well (which =docksEventHook= doesn't).-- #+begin_src haskell- import qualified XMonad.Util.ExtensibleState as XS-- data DockToggleTime = DTT { lastTime :: Time } deriving (Eq, Show, Typeable)-- instance ExtensionClass DockToggleTime where- initialValue = DTT 0-- toggleDocksHook :: Int -> KeySym -> Event -> X All- toggleDocksHook to ks ( KeyEvent { ev_event_display = d- , ev_event_type = et- , ev_keycode = ekc- , ev_time = etime- } ) =- io (keysymToKeycode d ks) >>= toggleDocks >> return (All True)- where- toggleDocks kc- | ekc == kc && et == keyPress = do- safeSendSignal ["Reveal 0", "TogglePersistent"]- XS.put ( DTT etime )- | ekc == kc && et == keyRelease = do- gap <- XS.gets ( (-) etime . lastTime )- safeSendSignal [ "TogglePersistent"- , "Hide " ++ show (if gap < 400 then to else 0)- ]- | otherwise = return ()-- safeSendSignal s = catchX (io $ sendSignal s) (return ())- sendSignal = withSession . callSignal- withSession mc = connectSession >>= \c -> callNoReply c mc >> disconnect c- callSignal :: [String] -> MethodCall- callSignal s = ( methodCall- ( objectPath_ "/org/Xmobar/Control" )- ( interfaceName_ "org.Xmobar.Control" )- ( memberName_ "SendSignal" )- ) { methodCallDestination = Just $ busName_ "org.Xmobar.Control"- , methodCallBody = map toVariant s- }-- toggleDocksHook _ _ _ = return (All True)-- myDocksEventHook :: Event -> X All- myDocksEventHook e = do- when (et == mapNotify || et == unmapNotify) $- whenX ((not `fmap` (isClient w)) <&&> runQuery checkDock w) refresh- return (All True)- where w = ev_window e- et = ev_event_type e- #+end_src+#+title: Plugins and monitors++* System Monitor Plugins++ This is the description of the system monitor plugins available in+ xmobar. Some of them are only installed when an optional build+ option is set: we mention that fact, when needed, in their+ description.++ Each monitor has an =alias= to be used in the output+ template. Monitors may have default aliases, see the documentation+ of the monitor in question.++ There are two types of arguments: ones that all monitors share (the+ so called /default monitor arguments/) and arguments that are specific+ to a certain monitor.++ All Monitors accept a common set of arguments, described below in+ [[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+ =template= and =Low= arguments and then specifies the battery-specific+ =off= option.++ #+begin_src haskell+ Run Battery+ [ "--template", "<acstatus>"+ , "--Low" , "15"+ -- battery specific options start here.+ , "--"+ , "--off" , "<left> (<timeleft>)"+ ]+ 100+ #+end_src++ See also [[./window-managers.org][Interfacing with window managers]] for a collection of+ plugins that let you interact and control xmobar from window+ managers.++*** Icon Patterns++ Some monitors allow usage of strings that depend on some integer+ value from 0 to 8 by replacing all occurrences of =%%= with it+ (i.e. =<icon=/path/to/icon_%%.xpm/>= will be interpreted as+ =<icon=/path/to/icon_3.xpm/>= when the value is =3=, also =%= is+ interpreted as =%=, =%%= as =3=, =%%%= as =3%=, =%%%%= as =33= and so+ on). Essentially it allows to replace vertical bars with custom+ icons. For example,++ #+begin_src haskell+ Run Brightness+ [ "-t", "<ipat>"+ , "--"+ , "--brightness-icon-pattern", "<icon=bright_%%.xpm/>"+ ] 30+ #+end_src++ Will display =bright_0.xpm= to =bright_8.xpm= depending on current+ brightness value.++*** Default Monitor Arguments++ These are the options available for all monitors:++ - =-t= /string/ Output template++ - Template for the monitor output. Field names must be enclosed+ between pointy brackets (=<foo>=) and will be substituted by the+ computed values. You can also specify the foreground (and+ optionally, background) color for a region by bracketing it between+ =<fc=fgcolor>= (or =<fc=fgcolor,bgcolor>=) and =</fc>=. The rest of+ the template is output verbatim.+ - Long option: =--template=+ - Default value: per monitor (see above).++ - =-H= /number/ The high threshold.++ - Numerical values higher than /number/ will be displayed with the+ color specified by =-h= (see below).+ - Long option: =--High=+ - Default value: 66++ - =-L= /number/ The low threshold.++ - Numerical values higher than /number/ and lower than the high+ threshold will be displayed with the color specified by =-n= (see+ below). Values lower than /number/ will use the =-l= color.+ - Long option: =--Low=+ - Default value: 33++ - =-h= /color/ High threshold color.++ - Color for displaying values above the high threshold. /color/ can be+ either a name (e.g. "blue") or an hexadecimal RGB (e.g. "#FF0000").+ - Long option: =--high=+ - Default: none (use the default foreground).++ - =-n= /color/ Color for 'normal' values++ - Color used for values greater than the low threshold but lower than+ the high one.+ - Long option: =--normal=+ - Default: none (use the default foreground).++ - =-l= /color/ The low threshold color++ - Color for displaying values below the low threshold.+ - Long option: =--low=+ - Default: none (use the default foreground).++ - =-S= /boolean/ Display optional suffixes++ - When set to a true designator ("True", "Yes" or "On"), optional+ value suffixes such as the '%' symbol or optional units will be+ displayed.+ - Long option: =--suffix=+ - Default: False.++ - =-p= /number/ Percentages padding++ - Width, in number of digits, for quantities representing percentages.+ For instance =-p 3= means that all percentages in the monitor will+ be represented using 3 digits.+ - Long option: =--ppad=+ - Default value: 0 (don't pad)++ - =-d= /number/ Decimal digits++ - Number of digits after the decimal period to use in float values.+ - Long option: =--ddigits=+ - Default value: 0 (display only integer part)++ - =-m= /number/ Minimum field width++ - Minimum width, in number of characters, of the fields in the monitor+ template. Values whose printed representation is shorter than this+ value will be padded using the padding characters given by the =-c=+ option with the alignment specified by =-a= (see below).+ - Long option: =--minwidth=+ - Default: 0++ - =-M= /number/ Maximum field width++ - Maximum width, in number of characters, of the fields in the monitor+ template. Values whose printed representation is longer than this+ value will be truncated.+ - Long option: =--maxwidth=+ - Default: 0 (no maximum width)++ - =-e= /string/ Maximum width ellipsis++ - Ellipsis to be added to the field when it has reached its max width.+ - Long option: =--maxwidthellipsis=+ - Default: "" (no ellipsis)++ - =-w= /number/ Fixed field width++ - All fields will be set to this width, padding or truncating as+ needed.+ - Long option: =--width=+ - Default: 0 (variable width)++ - =-T= /number/ Maximum total width++ - Maximum total width of the text.+ - Long option: =--maxtwidth=+ - Default: 0 (no limit)++ - =-E= /string/ Maximum total width ellipsis++ - Ellipsis to be added to the total text when it has reached its max+ width.+ - Long option: =--maxtwidthellipsis=+ - Default: "" (no ellipsis)++ - =-c= /string/++ - Characters used for padding. The characters of /string/ are used+ cyclically. E.g., with =-P +- -w 6=, a field with value "foo" will+ be represented as "+-+foo".+ - Long option: =--padchars=+ - Default value: " "++ - =-a= r|l Field alignment++ - Whether to use right (r) or left (l) alignment of field values when+ padding.+ - Long option: =--align=+ - Default value: r (padding to the left)++ - =-b= /string/ Bar background++ - Characters used, cyclically, to draw the background of bars. For+ instance, if you set this option to "·.", an empty bar will look+ like this: =·.·.·.·.·.=+ - Long option: =--bback=+ - Default value: ":"++ - =-f= /string/ Bar foreground++ - Characters used, cyclically, to draw the foreground of bars.+ - Long option: =--bfore=+ - Default value: "#"++ - =-W= /number/ Bar width++ - Total number of characters used to draw bars.+ - Long option: =--bwidth=+ - Default value: 10+ - Special value: 0. When this parameter is 0, the percentage to+ display is interpreted as a position in the bar foreground string+ (given by =-f=), and the character at that position is displayed.++ - =-x= /string/ N/A string++ - String to be used when the monitor is not available+ - Long option: =--nastring=+ - Default value: "N/A"++ Commands' arguments must be set as a list. E.g.:++ #+begin_src haskell+ Run Weather "EGPF" ["-t", "<station>: <tempC>C"] 36000+ #+end_src++ In this case xmobar will run the weather monitor, getting information+ for the weather station ID EGPF (Glasgow Airport, as a homage to GHC)+ every hour (36000 tenth of seconds), with a template that will output+ something like:++ #+begin_src shell+ Glasgow Airport: 16.0C+ #+end_src++*** Battery Monitors+***** =Battery Args RefreshRate=++ Same as++ #+begin_src haskell+ BatteryP ["BAT", "BAT0", "BAT1", "BAT2"] Args RefreshRate+ #+end_src++***** =BatteryP Dirs Args RefreshRate=++ - Aliases to =battery=++ - Dirs: list of directories in =/sys/class/power_supply/= where to look+ for the ACPI files of each battery. Example: =["BAT0","BAT1","BAT2"]=.+ Only up to 3 existing directories will be searched.++ - Args: default monitor arguments, plus the following specific ones+ (these options, being specific to the monitor, are to be specified+ after a =--= in the argument list):++ - =-O=: string for AC "on" status (default: "On")+ - =-i=: string for AC "idle" status (default: "On")+ - =-o=: string for AC "off" status (default: "Off")+ - =-L=: low power (=watts=) threshold (default: 10)+ - =-H=: high power threshold (default: 12)+ - =-l=: color to display power lower than the =-L= threshold+ - =-m=: color to display power lower than the =-H= threshold+ - =-h=: color to display power higher than the =-H= threshold+ - =-p=: color to display positive power (battery charging)+ - =-f=: file in =/sys/class/power_supply= with AC info (default:+ "AC/online")+ - =-A=: a number between 0 and 100, threshold below which the action+ given by =-a=, if any, is performed (default: 5)+ - =-a=: a string with a system command that is run when the percentage+ left in the battery is less or equal than the threshold given by the+ =-A= option. If not present, no action is undertaken.+ - =-P=: to include a percentage symbol in =left=.+ - =--on-icon-pattern=: dynamic string for current battery charge when+ AC is "on" in =leftipat=.+ - =--off-icon-pattern=: dynamic string for current battery charge when+ AC is "off" in =leftipat=.+ - =--idle-icon-pattern=: dynamic string for current battery charge+ when AC is "idle" in =leftipat=.+ - =--lows=: string for AC "off" status and power lower than the =-L=+ threshold (default: "")+ - =--mediums=: string for AC "off" status and power lower than the+ =-H= threshold (default: "")+ - =--highs=: string for AC "off" status and power higher than the =-H=+ threshold (default: "")++ - Variables that can be used with the =-t/--template= argument:+ =left=, =leftbar=, =leftvbar=, =leftipat=, =timeleft=, =watts=,+ =acstatus=++ - Default template: =Batt: <watts>, <left>% / <timeleft>=++ - Example (note that you need "--" to separate regular monitor options+ from Battery's specific ones):++ #+begin_src haskell+ Run BatteryP ["BAT0"]+ ["-t", "<acstatus><watts> (<left>%)",+ "-L", "10", "-H", "80", "-p", "3",+ "--", "-O", "<fc=green>On</fc> - ", "-i", "",+ "-L", "-15", "-H", "-5",+ "-l", "red", "-m", "blue", "-h", "green",+ "-a", "notify-send -u critical 'Battery running out!!'",+ "-A", "3"]+ 600+ #+end_src++ In the above example, the thresholds before the =--= separator affect+ only the =<left>= and =<leftbar>= fields, while those after the+ separator affect how =<watts>= is displayed. For this monitor, neither+ the generic nor the specific options have any effect on =<timeleft>=.+ We are also telling the monitor to execute the unix command+ =notify-send= when the percentage left in the battery reaches 6%.++ It is also possible to specify template variables in the =-O= and =-o=+ switches, as in the following example:++ #+begin_src haskell+ Run BatteryP ["BAT0"]+ ["-t", "<acstatus>"+ , "-L", "10", "-H", "80"+ , "-l", "red", "-h", "green"+ , "--", "-O", "Charging", "-o", "Battery: <left>%"+ ] 10+ #+end_src++ - The "idle" AC state is selected whenever the AC power entering the+ battery is zero.++***** =BatteryN Dirs Args RefreshRate Alias=++ Works like =BatteryP=, but lets you specify an alias for the+ monitor other than "battery". Useful in case you one separate+ monitors for more than one battery.+*** Cpu and Memory Monitors+***** =Cpu Args RefreshRate=++ - Aliases to =cpu=+ - Args: default monitor arguments, plus:++ - =--load-icon-pattern=: dynamic string for cpu load in =ipat=++ - Thresholds refer to percentage of CPU load+ - Variables that can be used with the =-t/--template= argument:+ =total=, =bar=, =vbar=, =ipat=, =user=, =nice=, =system=, =idle=,+ =iowait=+ - Default template: =Cpu: <total>%=++***** =MultiCpu Args RefreshRate=++ - Aliases to =multicpu=+ - Args: default monitor arguments, plus:++ - =--load-icon-pattern=: dynamic string for overall cpu load in+ =ipat=.+ - =--load-icon-patterns=: dynamic string for each cpu load in+ =autoipat=, =ipat{i}=. This option can be specified several times.+ nth option corresponds to nth cpu.+ - =--fallback-icon-pattern=: dynamic string used by =autoipat= and+ =ipat{i}= when no =--load-icon-patterns= has been provided for+ =cpu{i}=+ - =--contiguous-icons=: flag (no value needs to be provided) that+ causes the load icons to be drawn without padding.++ - Thresholds refer to percentage of CPU load+ - Variables that can be used with the =-t/--template= argument:+ =autototal=, =autobar=, =autovbar=, =autoipat=, =autouser=,+ =autonice=, =autosystem=, =autoidle=, =total=, =bar=, =vbar=, =ipat=,+ =user=, =nice=, =system=, =idle=, =total0=, =bar0=, =vbar0=, =ipat0=,+ =user0=, =nice0=, =system0=, =idle0=, ... The auto* variables+ automatically detect the number of CPUs on the system and display one+ entry for each.+ - Default template: =Cpu: <total>%=++***** =CpuFreq Args RefreshRate=++ - Aliases to =cpufreq=++ - Args: default monitor arguments++ - Thresholds refer to frequency in GHz++ - Variables that can be used with the =-t/--template= argument:+ =cpu0=, =cpu1=, .., =cpuN=++ - Default template: =Freq: <cpu0>GHz=++ - This monitor requires acpi_cpufreq module to be loaded in kernel++ - Example:++ #+begin_src haskell+ Run CpuFreq ["-t", "Freq:<cpu0>|<cpu1>GHz", "-L", "0", "-H", "2",+ "-l", "lightblue", "-n","white", "-h", "red"] 50+ #+end_src++***** =CoreTemp Args RefreshRate=++ - Aliases to =coretemp=++ - Args: default monitor arguments++ - Thresholds refer to temperature in degrees++ - Variables that can be used with the =-t/--template= argument:+ =core0=, =core1=, .., =coreN=++ - Default template: =Temp: <core0>C=++ - This monitor requires coretemp module to be loaded in kernel++ - Example:++ #+begin_src haskell+ Run CoreTemp ["-t", "Temp:<core0>|<core1>C",+ "-L", "40", "-H", "60",+ "-l", "lightblue", "-n", "gray90", "-h", "red"] 50+ #+end_src++***** =MultiCoreTemp Args RefreshRate=++ - Aliases to =multicoretemp=++ - Args: default monitor arguments, plus:++ - =--max-icon-pattern=: dynamic string for overall cpu load in+ =maxipat=.+ - =--avg-icon-pattern=: dynamic string for overall cpu load in+ =avgipat=.+ - =--mintemp=: temperature in degree Celsius, that sets the lower+ limit for percentage calculation.+ - =--maxtemp=: temperature in degree Celsius, that sets the upper+ limit for percentage calculation.+ - =--hwmon-path=: this monitor tries to find coretemp devices by+ looking for them in directories following the pattern+ =/sys/bus/platform/devices/coretemp.*/hwmon/hwmon*=, but some+ processors (notably Ryzen) might expose those files in a different+ tree (e.g., Ryzen) puts them somewhere in "/sys/class/hwmon/hwmon*",+ and the lookup is most costly. With this option, it is possible to+ explicitly specify the full path to the directory where the+ =tempN_label= and =tempN_input= files are located.++ - Thresholds refer to temperature in degree Celsius++ - Variables that can be used with the =-t/--template= argument: =max=,+ =maxpc=, =maxbar=, =maxvbar=, =maxipat=, =avg=, =avgpc=, =avgbar=,+ =avgvbar=, =avgipat=, =core0=, =core1=, ..., =coreN=++ The /pc, /bar, /vbar and /ipat variables are showing percentages on+ the scale defined by =--mintemp= and =--maxtemp=. The max* and avg*+ variables to the highest and the average core temperature.++ - Default template: =Temp: <max>°C - <maxpc>%=++ - This monitor requires coretemp module to be loaded in kernel++ - Example:++ #+begin_src haskell+ Run MultiCoreTemp ["-t", "Temp: <avg>°C | <avgpc>%",+ "-L", "60", "-H", "80",+ "-l", "green", "-n", "yellow", "-h", "red",+ "--", "--mintemp", "20", "--maxtemp", "100"] 50+ #+end_src++***** =K10Temp Slot Args RefreshRate=++ - Aliases to =k10temp=++ - Slot: The PCI slot address of the k10temp device as a string. You+ can find it as a subdirectory in =/sys/bus/pci/drivers/k10temp/=.++ - Args: default monitor arguments++ - Thresholds refer to temperature in degrees++ - Variables that can be used with the =-t/--template= argument:+ =Tctl=, =Tdie=, =Tccd1=, .., =Tccd8=++ - Default template: =Temp: <Tdie>C=++ - This monitor requires k10temp module to be loaded in kernel++ - It is important to note that not all measurements are available+ on on all models of processor. Of particular importance - Tdie+ (used in the default template) may not be present on processors+ prior to Zen (17h). Tctl, however, may be offset from the real+ temperature and so is not used by default.++ - Example:++ #+begin_src haskell+ Run K10Temp "0000:00:18.3"+ ["-t", "Temp: <Tdie>C|<Tccd1>C",+ "-L", "40", "-H", "60",+ "-l", "lightblue", "-n", "gray90", "-h", "red"]+ 50+ #+end_src+++***** =Memory Args RefreshRate=++ - Aliases to =memory=+ - Args: default monitor arguments, plus:++ - =--used-icon-pattern=: dynamic string for used memory ratio in+ =usedipat=.+ - =--free-icon-pattern=: dynamic string for free memory ratio in+ =freeipat=.+ - =--available-icon-pattern=: dynamic string for available memory+ ratio in =availableipat=.++ - Thresholds refer to percentage of used memory+ - Variables that can be used with the =-t/--template= argument:+ =total=, =free=, =buffer=, =cache=, =available=, =used=, =usedratio=,+ =usedbar=, =usedvbar=, =usedipat=, =freeratio=, =freebar=, =freevbar=,+ =freeipat=, =availableratio=, =availablebar=, =availablevbar=,+ =availableipat=+ - Default template: =Mem: <usedratio>% (<cache>M)=++***** =Swap Args RefreshRate=++ - Aliases to =swap=+ - Args: default monitor arguments+ - Thresholds refer to percentage of used swap+ - Variables that can be used with the =-t/--template= argument:+ =total=, =used=, =free=, =usedratio=+ - Default template: =Swap: <usedratio>%=++*** Date Monitors+***** =Date Format Alias RefreshRate=++ - Format is a time format string, as accepted by the standard ISO C+ =strftime= function (or Haskell's =formatCalendarTime=). Basically,+ if =date +"my-string"= works with your command then =Date= will handle+ it correctly.++ - Timezone changes are picked up automatically every minute.++ - Sample usage:++ #+begin_src haskell+ Run Date "%a %b %_d %Y <fc=#ee9a00>%H:%M:%S</fc>" "date" 10+ #+end_src++***** =DateZone Format Locale Zone Alias RefreshRate=++ A variant of the =Date= monitor where one is able to explicitly set the+ time-zone, as well as the locale.++ - The format of =DateZone= is exactly the same as =Date=.++ - If =Locale= is =""= (the empty string) the default locale of the+ system is used, otherwise use the given locale. If there are more+ instances of =DateZone=, using the empty string as input for =Locale=+ is not recommended.++ - =Zone= is the name of the =TimeZone=. It is assumed that the time-zone+ database is stored in =/usr/share/zoneinfo/=. If the empty string is+ given as =Zone=, the default system time is used.++ - Sample usage:++ #+begin_src haskell+ Run DateZone "%a %H:%M:%S" "de_DE.UTF-8" "Europe/Vienna" "viennaTime" 10+ #+end_src+*** Disk Monitors+***** =DiskU Disks Args RefreshRate=++ - Aliases to =disku=++ - Disks: list of pairs of the form (device or mount point, template),+ where the template can contain =<size>=, =<free>=, =<used>=, =<freep>=+ or =<usedp>=, =<freebar>=, =<freevbar>=, =<freeipat>=, =<usedbar>=,+ =<usedvbar>= or =<usedipat>= for total, free, used, free percentage+ and used percentage of the given file system capacity.++ - Thresholds refer to usage percentage.++ - Args: default monitor arguments. =-t/--template= is ignored. Plus++ - =--free-icon-pattern=: dynamic string for free disk space in+ =freeipat=.+ - =--used-icon-pattern=: dynamic string for used disk space in+ =usedipat=.++ - Default template: none (you must specify a template for each file+ system).++ - Example:++ #+begin_src haskell+ DiskU [("/", "<used>/<size>"), ("sdb1", "<usedbar>")]+ ["-L", "20", "-H", "50", "-m", "1", "-p", "3"]+ 20+ #+end_src++***** =DiskIO Disks Args RefreshRate=++ - Aliases to =diskio=++ - Disks: list of pairs of the form (device or mount point, template),+ where the template can contain =<total>=, =<read>=, =<write>= for+ total, read and write speed, respectively, as well as =<totalb>=,+ =<readb>=, =<writeb>=, which report number of bytes during the last+ refresh period rather than speed. There are also bar versions of each:+ =<totalbar>=, =<totalvbar>=, =<totalipat>=, =<readbar>=, =<readvbar>=,+ =<readipat>=, =<writebar>=, =<writevbar>=, and =<writeipat>=; and+ their "bytes" counterparts: =<totalbbar>=, =<totalbvbar>=,+ =<totalbipat>=, =<readbbar>=, =<readbvbar>=, =<readbipat>=,+ =<writebbar>=, =<writebvbar>=, and =<writebipat>=.++ - Thresholds refer to speed in b/s++ - Args: default monitor arguments. =-t/--template= is ignored. Plus++ - =--total-icon-pattern=: dynamic string for total disk I/O in+ =<totalipat>=.+ - =--write-icon-pattern=: dynamic string for write disk I/O in+ =<writeipat>=.+ - =--read-icon-pattern=: dynamic string for read disk I/O in+ =<readipat>=.++ - Default template: none (you must specify a template for each file+ system).++ - Example:++ #+begin_src haskell+ DiskIO [("/", "<read> <write>"), ("sdb1", "<total>")] [] 10+ #+end_src++*** Keyboard Monitors+***** =Kbd Opts=++ - Registers to XKB/X11-Events and output the currently active keyboard+ layout. Supports replacement of layout names.++ - Aliases to =kbd=++ - Opts is a list of tuples:++ - first element of the tuple is the search string+ - second element of the tuple is the corresponding replacement++ - Example:++ #+begin_src haskell+ Run Kbd [("us(dvorak)", "DV"), ("us", "US")]+ #+end_src++***** =Locks=++ - Displays the status of Caps Lock, Num Lock and Scroll Lock.++ - Aliases to =locks=++ - Example:++ #+begin_src haskell+ Run Locks+ #+end_src++*** Process Monitors+***** =TopProc Args RefreshRate=++ - Aliases to =top=+ - Args: default monitor arguments. The low and high thresholds (=-L= and+ =-H=) denote, for memory entries, the percent of the process memory+ over the total amount of memory currently in use and, for cpu entries,+ the activity percentage (i.e., the value of =cpuN=, which takes values+ between 0 and 100).+ - Variables that can be used with the =-t/--template= argument: =no=,+ =name1=, =cpu1=, =both1=, =mname1=, =mem1=, =mboth1=, =name2=, =cpu2=,+ =both2=, =mname2=, =mem2=, =mboth2=, ...+ - Default template: =<both1>=+ - Displays the name and cpu/mem usage of running processes (=bothn= and+ =mboth= display both, and is useful to specify an overall maximum+ and/or minimum width, using the =-m/-M= arguments. =no= gives the+ total number of processes.++***** =TopMem Args RefreshRate=++ - Aliases to =topmem=+ - Args: default monitor arguments. The low and high thresholds (=-L= and+ =-H=) denote the percent of the process memory over the total amount+ of memory currently in use.+ - Variables that can be used with the =-t/--template= argument:+ =name1=, =mem1=, =both1=, =name2=, =mem2=, =both2=, ...+ - Default template: =<both1>=+ - Displays the name and RSS (resident memory size) of running processes+ (=bothn= displays both, and is useful to specify an overall maximum+ and/or minimum width, using the =-m/-M= arguments.++*** Thermal Monitors+***** =ThermalZone Number Args RefreshRate=++ - Aliases to "thermaln": so =ThermalZone 0 []= can be used in template+ as =%thermal0%=++ - Thresholds refer to temperature in degrees++ - Args: default monitor arguments++ - Variables that can be used with the =-t/--template= argument: =temp=++ - Default template: =<temp>C=++ - This plugin works only on systems with devices having thermal zone.+ Check directories in =/sys/class/thermal= for possible values of the+ zone number (e.g., 0 corresponds to =thermal_zone0= in that+ directory).++ - Example:++ #+begin_src haskell+ Run ThermalZone 0 ["-t","<id>: <temp>C"] 30+ #+end_src++***** =Thermal Zone Args RefreshRate=++ - *This plugin is deprecated. Use =ThermalZone= instead.*++ - Aliases to the Zone: so =Thermal "THRM" []= can be used in template as+ =%THRM%=++ - Args: default monitor arguments++ - Thresholds refer to temperature in degrees++ - Variables that can be used with the =-t/--template= argument: =temp=++ - Default template: =Thm: <temp>C=++ - This plugin works only on systems with devices having thermal zone.+ Check directories in /proc/acpi/thermal_zone for possible values.++ - Example:++ #+begin_src haskell+ Run Thermal "THRM" ["-t","iwl4965-temp: <temp>C"] 50+ #+end_src++*** Volume Monitors+***** =Volume Mixer Element Args RefreshRate=++ - Aliases to the mixer name and element name separated by a+ colon. Thus, =Volume "default" "Master" [] 10= can be used as+ =%default:Master%=.+ - Args: default monitor arguments. Also accepts:++ - =-O= /string/ On string++ - The string used in place of =<status>= when the mixer element is+ on. Defaults to "[on]".+ - Long option: =--on=++ - =-o= /string/ Off string++ - The string used in place of =<status>= when the mixer element is+ off. Defaults to "[off]".+ - Long option: =--off=++ - =-C= /color/ On color++ - The color to be used for =<status>= when the mixer element is on.+ Defaults to "green".+ - Long option: =--onc=++ - =-c= /color/ Off color++ - The color to be used for =<status>= when the mixer element is off.+ Defaults to "red".+ - Long option: =--offc=++ - =--highd= /number/ High threshold for dB. Defaults to -5.0.+ - =--lowd= /number/ Low threshold for dB. Defaults to -30.0.+ - =--volume-icon-pattern= /string/ dynamic string for current volume+ in =volumeipat=.+ - =-H= /number/ High threshold for volume (in %). Defaults to 60.0.++ - Long option: =--highv=++ - =-L= /number/ Low threshold for volume (in %). Defaults to 20.0.++ - Long option: =--lowv=++ - =-h=: /string/ High string++ - The string added in front of =<status>= when the mixer element is+ on and the volume percentage is higher than the =-H= threshold.+ Defaults to "".+ - Long option: =--highs=++ - =-m=: /string/ Medium string++ - The string added in front of =<status>= when the mixer element is+ on and the volume percentage is lower than the =-H= threshold.+ Defaults to "".+ - Long option: =--mediums=++ - =-l=: /string/ Low string++ - The string added in front of =<status>= when the mixer element is+ on and the volume percentage is lower than the =-L= threshold.+ Defaults to "".+ - Long option: =--lows=++ - Variables that can be used with the =-t/--template= argument:+ =volume=, =volumebar=, =volumevbar=, =volumeipat=, =dB=, =status=,+ =volumestatus=+ - Note that =dB= might only return 0 on your system. This is known to+ happen on systems with a pulseaudio backend.+ - Default template: =Vol: <volume>% <status>=+ - Requires the package [[http://hackage.haskell.org/package/alsa-core][alsa-core]] and [[http://hackage.haskell.org/package/alsa-mixer][alsa-mixer]] installed in your+ system. In addition, to activate this plugin you must pass the+ =with_alsa= flag during compilation.++***** =Alsa Mixer Element Args=++ Like [[=Volume Mixer Element Args RefreshRate=][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+ use CPU until a change happens.+ - Aliases to =alsa:= followed by the mixer name and element name+ separated by a colon. Thus, =Alsa "default" "Master" []= can be used+ as =%alsa:default:Master%=.+ - Additional options (after the =--=):+ - =--alsactl=/path/to/alsactl=: If this option is not specified,+ =alsactl= will be sought in your =PATH= first, and failing that, at+ =/usr/sbin/alsactl= (this is its location on Debian systems.+ =alsactl monitor= works as a non-root user despite living in+ =/usr/sbin=.).+ - =stdbuf= (from coreutils) must be (and most probably already is) in+ your =PATH=.++*** Mail Monitors+***** =Mail Args Alias=++ - Args: list of maildirs in form =[("name1","path1"),...]=. Paths may+ start with a '~' to expand to the user's home directory.++ - This plugin requires inotify support in your Linux kernel and the+ [[http://hackage.haskell.org/package/hinotify/][hinotify]] package. To activate, pass the =with_inotify= flag during+ compilation.++ - Example:++ #+begin_src haskell+ Run Mail [("inbox", "~/var/mail/inbox"),+ ("lists", "~/var/mail/lists")]+ "mail"+ #+end_src++***** =MailX Args Opts Alias=++ - Args: list of maildirs in form =[("name1","path1","color1"),...]=.+ Paths may start with a '~' to expand to the user's home directory.+ When mails are present, counts are displayed with the given name and+ color.++ - Opts is a possibly empty list of options, as flags. Possible values:+ -d dir --dir dir a string giving the base directory where maildir+ files with a relative path live. -p prefix --prefix prefix a string+ giving a prefix for the list of displayed mail counts -s suffix+ --suffix suffix a string giving a suffix for the list of displayed+ mail counts++ - This plugin requires inotify support in your Linux kernel and the+ [[http://hackage.haskell.org/package/hinotify/][hinotify]] package. To activate, pass the =with_inotify= flag during+ compilation.++ - Example:++ #+begin_src haskell+ Run MailX [("I", "inbox", "green"),+ ("L", "lists", "orange")]+ ["-d", "~/var/mail", "-p", " ", "-s", " "]+ "mail"+ #+end_src++***** =MBox Mboxes Opts Alias=++ - Mboxes a list of mbox files of the form =[("name", "path", "color")]=,+ where name is the displayed name, path the absolute or relative (to+ BaseDir) path of the mbox file, and color the color to use to display+ the mail count (use an empty string for the default).++ - Opts is a possibly empty list of options, as flags. Possible values:+ -a --all (no arg) Show all mailboxes, even if empty. -u (no arg) Show+ only the mailboxes' names, sans counts. -d dir --dir dir a string+ giving the base directory where mbox files with a relative path live.+ -p prefix --prefix prefix a string giving a prefix for the list of+ displayed mail counts -s suffix --suffix suffix a string giving a+ suffix for the list of displayed mail counts++ - Paths may start with a '~' to expand to the user's home directory.++ - This plugin requires inotify support in your Linux kernel and the+ [[http://hackage.haskell.org/package/hinotify/][hinotify]] package. To activate, pass the =with_inotify= flag during+ compilation.++ - Example. The following command look for mails in =/var/mail/inbox= and+ =~/foo/mbox=, and will put a space in front of the printed string+ (when it's not empty); it can be used in the template with the alias+ =mbox=:++ #+begin_src haskell+ Run MBox [("I ", "inbox", "red"), ("O ", "~/foo/mbox", "")]+ ["-d", "/var/mail/", "-p", " "] "mbox"+ #+end_src++***** =NotmuchMail Alias Args Rate=++ This plugin checks for new mail, provided that this mail is indexed by+ =notmuch=. In the =notmuch= spirit, this plugin checks for new *threads*+ and not new individual messages.++ - Alias: What name the plugin should have in your template string.++ - Args: A list of =MailItem= s of the form++ #+begin_src haskell+ [ MailItem "name" "address" "query"+ ...+ ]+ #+end_src++ where++ - =name= is what gets printed in the status bar before the number of+ new threads.+ - =address= is the e-mail address of the recipient, i.e. we only query+ mail that was send to this particular address (in more concrete+ terms, we pass the address to the =to:= constructor when performing+ the search). If =address= is empty, we search through all unread+ mail, regardless of whom it was sent to.+ - =query= is funneled to =notmuch search= verbatim. For the general+ query syntax, consult =notmuch search --help=, as well as+ =notmuch-search-terms(7)=. Note that the =unread= tag is *always*+ added in front of the query and composed with it via an *and*.++ - Rate: Rate with which to update the plugin (in deciseconds).++ - Example:++ - A single =MailItem= that displays all unread threads from the given+ address:++ #+begin_src haskell+ MailItem "mbs:" "soliditsallgood@mailbox.org" ""+ #+end_src++ - A single =MailItem= that displays all unread threads with+ "[My-Subject]" somewhere in the title:++ #+begin_src haskell+ MailItem "S:" "" "subject:[My-Subject]"+ #+end_src++ - A full example of a =NotmuchMail= configuration:++ #+begin_src haskell+ Run NotmuchMail "mail" -- name for the template string+ [ -- All unread mail to the below address, but nothing that's tagged+ -- with @lists@ or @haskell@.+ MailItem "mbs:"+ "soliditsallgood@mailbox.org"+ "not tag:lists and not tag:haskell"++ -- All unread mail that has @[Haskell-Cafe]@ in the subject line.+ , MailItem "C:" "" "subject:[Haskell-Cafe]"++ -- All unread mail that's tagged as @lists@, but not @haskell@.+ , MailItem "H:" "" "tag:lists and not tag:haskell"+ ]+ 600 -- update every 60 seconds+ #+end_src++*** Music Monitors+***** =MPD Args RefreshRate=++ - This monitor will only be compiled if you ask for it using the+ =with_mpd= flag. It needs [[http://hackage.haskell.org/package/libmpd/][libmpd]] 5.0 or later (available on Hackage).++ - Aliases to =mpd=++ - Args: default monitor arguments. In addition you can provide =-P=,+ =-S= and =-Z=, with an string argument, to represent the playing,+ stopped and paused states in the =statei= template field. The+ environment variables =MPD_HOST= and =MPD_PORT= are used to configure+ the mpd server to communicate with, unless given in the additional+ arguments =-p= (=--port=) and =-h= (=--host=). Also available:++ - =lapsed-icon-pattern=: dynamic string for current track position in+ =ipat=.++ - Variables that can be used with the =-t/--template= argument: =bar=,+ =vbar=, =ipat=, =state=, =statei=, =volume=, =length=, =lapsed=,+ =remaining=, =plength= (playlist length), =ppos= (playlist position),+ =flags= (ncmpcpp-style playback mode), =name=, =artist=, =composer=,+ =performer=, =album=, =title=, =track=, =file=, =genre=, =date=++ - Default template: =MPD: <state>=++ - Example (note that you need "--" to separate regular monitor options+ from MPD's specific ones):++ #+begin_src haskell+ Run MPD ["-t",+ "<composer> <title> (<album>) <track>/<plength> <statei> [<flags>]",+ "--", "-P", ">>", "-Z", "|", "-S", "><"] 10+ #+end_src++***** =MPDX Args RefreshRate Alias=++ Like =MPD= but uses as alias its last argument instead of "mpd".++***** =Mpris1 PlayerName Args RefreshRate=++ - Aliases to =mpris1=++ - Requires [[http://hackage.haskell.org/package/dbus][dbus]] and [[http://hackage.haskell.org/package/text][text]] packages. To activate, pass the =with_mpris=+ flag during compilation.++ - PlayerName: player supporting MPRIS v1 protocol. Some players need+ this to be an all lowercase name (e.g. "spotify"), but some others+ don't.++ - Args: default monitor arguments.++ - Variables that can be used with the =-t/--template= argument:+ =album=, =artist=, =arturl=, =length=, =title=, =tracknumber=++ - Default template: =<artist> - <title>=++ - Example:++ #+begin_src haskell+ Run Mpris1 "clementine" ["-t", "<artist> - [<tracknumber>] <title>"] 10+ #+end_src++***** =Mpris2 PlayerName Args RefreshRate=++ - Aliases to =mpris2=++ - Requires [[http://hackage.haskell.org/package/dbus][dbus]] and [[http://hackage.haskell.org/package/text][text]] packages. To activate, pass the =with_mpris=+ flag during compilation.++ - PlayerName: player supporting MPRIS v2 protocol. Some players need+ this to be an all lowercase name (e.g. "spotify"), but some others+ don't.++ - Args: default monitor arguments.++ - Variables that can be used with the =-t/--template= argument:+ =album=, =artist=, =arturl=, =length=, =title=, =tracknumber=,+ =composer=, =genre=++ - Default template: =<artist> - <title>=++ - Example:++ #+begin_src haskell+ Run Mpris2 "spotify" ["-t", "<artist> - [<composer>] <title>"] 10+ #+end_src++*** Network Monitors+***** =Network Interface Args RefreshRate=++ - Aliases to the interface name: so =Network "eth0" []= can be used as+ =%eth0%=+ - Thresholds refer to velocities expressed in Kb/s+ - Args: default monitor arguments, plus:++ - =--rx-icon-pattern=: dynamic string for reception rate in =rxipat=.+ - =--tx-icon-pattern=: dynamic string for transmission rate in+ =txipat=.+ - =--up=: string used for the =up= variable value when the interface+ is up.++ - Variables that can be used with the =-t=/=--template= argument: =dev=,+ =rx=, =tx=, =rxbar=, =rxvbar=, =rxipat=, =txbar=, =txvbar=, =txipat=,+ =up=. Reception and transmission rates (=rx= and =tx=) are displayed+ by default as Kb/s, without any suffixes, but you can set the =-S= to+ "True" to make them displayed with adaptive units (Kb/s, Mb/s, etc.).+ - Default template: =<dev>: <rx>KB|<tx>KB=++***** =DynNetwork Args RefreshRate=++ - Active interface is detected automatically+ - Aliases to "dynnetwork"+ - Thresholds are expressed in Kb/s+ - Args: default monitor arguments, plus:++ - =--rx-icon-pattern=: dynamic string for reception rate in =rxipat=.+ - =--tx-icon-pattern=: dynamic string for transmission rate in =txipat=+ - =--devices=: comma-separated list of devices to show.++ - Variables that can be used with the =-t=/=--template= argument:+ =dev=, =rx=, =tx=, =rxbar=, =rxvbar=, =rxipat=, =txbar=, =txvbar=,+ =txipat=.++ Reception and transmission rates (=rx= and =tx=) are displayed in Kbytes+ per second, and you can set the =-S= to "True" to make them displayed+ with units (the string "Kb/s").+ - Default template: =<dev>: <rx>KB|<tx>KB=+ - Example of usage of =--devices= option:++ =["--", "--devices", "wlp2s0,enp0s20f41"]=++***** =Wireless Interface Args RefreshRate=++ - If set to "", first suitable wireless interface is used.+ - Aliases to the interface name with the suffix "wi": thus,+ =Wireless "wlan0" []= can be used as =%wlan0wi%=, and+ =Wireless "" []= as =%wi%=.+ - Args: default monitor arguments, plus:++ - =--quality-icon-pattern=: dynamic string for connection quality in+ =qualityipat=.++ - Variables that can be used with the =-t=/=--template= argument:+ =ssid=, =signal=, =quality=, =qualitybar=, =qualityvbar=,+ =qualityipat=+ - Thresholds refer to link quality on a =[0, 100]= scale. Note that+ =quality= is calculated from =signal= (in dBm) by a possibly lossy+ conversion. It is also not taking into account many factors such as+ noise level, air busy time, transcievers' capabilities and the others+ which can have drastic impact on the link performance.+ - Default template: =<ssid> <quality>=+ - To activate this plugin you must pass the =with_nl80211= or the+ =with_iwlib= flag during compilation.++*** Weather Monitors+***** =Weather StationID Args RefreshRate=++ - Aliases to the Station ID: so =Weather "LIPB" []= can be used in+ template as =%LIPB%=+ - Thresholds refer to temperature in the selected units+ - Args: default monitor arguments, plus:++ - =--weathers= /string/ : display a default string when the =weather=+ variable is not reported.++ - short option: =-w=+ - Default: ""++ - =--useManager= /bool/ : Whether to use one single manager per+ monitor for managing network connections or create a new one every+ time a connection is made.++ - Short option: =-m=+ - Default: True++ - Variables that can be used with the =-t/--template= argument:+ =station=, =stationState=, =year=, =month=, =day=, =hour=,+ =windCardinal=, =windAzimuth=, =windMph=, =windKnots=, =windMs=,+ =windKmh= =visibility=, =skyCondition=, =weather=, =tempC=, =tempF=,+ =dewPointC=, =dewPointF=, =rh=, =pressure=+ - Default template: =<station>: <tempC>C, rh <rh>% (<hour>)=+ - Retrieves weather information from http://tgftp.nws.noaa.gov. Here is+ an [[https://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYLD.TXT][example]], also showcasing the kind of information that may be+ extracted. Here is [[https://weather.rap.ucar.edu/surface/stations.txt][a sample list of station IDs]].++***** =WeatherX StationID SkyConditions Args RefreshRate=++ - Works in the same way as =Weather=, but takes an additional argument,+ a list of pairs from sky conditions to their replacement (typically a+ unicode string or an icon specification).+ - Use the variable =skyConditionS= to display the replacement of the+ corresponding sky condition. All other =Weather= template variables+ are available as well.++ For example:++ #+begin_src haskell+ WeatherX "LEBL"+ [ ("clear", "🌣")+ , ("sunny", "🌣")+ , ("mostly clear", "🌤")+ , ("mostly sunny", "🌤")+ , ("partly sunny", "⛅")+ , ("fair", "🌑")+ , ("cloudy","☁")+ , ("overcast","☁")+ , ("partly cloudy", "⛅")+ , ("mostly cloudy", "🌧")+ , ("considerable cloudiness", "⛈")]+ ["-t", "<fn=2><skyConditionS></fn> <tempC>° <rh>% <windKmh> (<hour>)"+ , "-L","10", "-H", "25", "--normal", "black"+ , "--high", "lightgoldenrod4", "--low", "darkseagreen4"]+ 18000+ #+end_src++ As mentioned, the replacement string can also be an icon specification,+ such as =("clear", "<icon=weather-clear.xbm/>")=.++*** Other Monitors+***** =Brightness Args RefreshRate=++ - Aliases to =bright=++ - Args: default monitor arguments, plus the following specif ones:++ - =-D=: directory in =/sys/class/backlight/= with files in it+ (default: "acpi_video0")+ - =-C=: file with the current brightness (default: actual_brightness)+ - =-M=: file with the maximum brightness (default: max_brightness)+ - =--brightness-icon-pattern=: dynamic string for current brightness+ in =ipat=.++ - Variables that can be used with the =-t/--template= argument:+ =vbar=, =percent=, =bar=, =ipat=++ - Default template: =<percent>=++ - Example:++ #+begin_src haskell+ Run Brightness ["-t", "<bar>"] 60+ #+end_src++***** =CatInt n filename=++ - Reads and displays an integer from the file whose path is =filename=+ (especially useful with files in =/sys=).++ - Aliases as =catn= (e.g. =Cat 0= as =cat0=, etc.) so you can have+ several.++ - Example:++ #+begin_src haskell+ Run CatInt 0 "/sys/devices/platform/thinkpad_hwmon/fan1_input" [] 50+ #+end_src++***** =CommandReader "/path/to/program" Alias=++ - Runs the given program, and displays its standard output.++***** =Uptime Args RefreshRate=++ - Aliases to =uptime=+ - Args: default monitor arguments. The low and high thresholds refer to+ the number of days.+ - Variables that can be used with the =-t/--template= argument: =days=,+ =hours=, =minutes=, =seconds=. The total uptime is the sum of all+ those fields. You can set the =-S= argument to =True= to add units to+ the display of those numeric fields.+ - Default template: =Up: <days>d <hours>h <minutes>m=++***** =UVMeter=++ - Aliases to "uv" + station id. For example: =%uv Brisbane%= or+ =%uv Alice Springs%=++ - Args: default monitor arguments, plus:++ - =--useManager= /bool/ : Whether to use one single manager per+ monitor for managing network connections or create a new one every+ time a connection is made.++ - Short option: =-m=+ - Default: True++ - /Reminder:/ Keep the refresh rate high, to avoid making unnecessary+ requests every time the plug-in is run.++ - Station IDs can be found here:+ http://www.arpansa.gov.au/uvindex/realtime/xml/uvvalues.xml++ - Example:++ #+begin_src haskell+ Run UVMeter "Brisbane" ["-H", "3", "-L", "3", "--low", "green", "--high", "red"] 900+ #+end_src++* Executing External Commands++ In order to execute an external command you can either write the+ command name in the template, in this case it will be executed+ without arguments, or you can configure it in the "commands"+ configuration option list with the Com template command:++ =Com ProgramName Args Alias RefreshRate=++ - ProgramName: the name of the program+ - Args: the arguments to be passed to the program at execution time+ - RefreshRate: number of tenths of second between re-runs of the+ command. A zero or negative rate means that the command will be+ executed only once.+ - Alias: a name to be used in the template. If the alias is en empty+ string the program name can be used in the template.++ E.g.:++ #+begin_src haskell+ Run Com "uname" ["-s","-r"] "" 0+ #+end_src++ can be used in the output template as =%uname%= (and xmobar will call+ /uname/ only once), while++ #+begin_src haskell+ Run Com "date" ["+\"%a %b %_d %H:%M\""] "mydate" 600+ #+end_src++ can be used in the output template as =%mydate%=.++ Sometimes, you don't mind if the command executed exits with an+ error, or you might want to display a custom message in that+ case. To that end, you can use the =ComX= variant:++ =ComX ProgramName Args ExitMessage Alias RefreshRate=++ Works like =Com=, but displaying =ExitMessage= (a string) if the+ execution fails. For instance:++ #+begin_src haskell+ Run ComX "date" ["+\"%a %b %_d %H:%M\""] "N/A" "mydate" 600+ #+end_src++ will display "N/A" if for some reason the =date= invocation fails.
doc/quick-start.org view
@@ -1,3 +1,5 @@+#+title: Quick start: using xmobar+ Xmobar can either be configured using the configuration language, or used as a Haskell library (similar to xmonad) and compiled with your specific configuration. For an example of the latter, you can have a@@ -7,373 +9,461 @@ There is also an example of a config using the configuration language available [[http://github.com/jaor/xmobar/raw/master/examples/xmobar.config][here]]. -* Configuration Options+* Command Line Options -Here are all the global configuration options that you can set within-the =Config= block in your configuration.+ xmobar can be either configured with a configuration file or with+ command line options. In the second case, the command line options will+ overwrite the corresponding options set in the configuration file. -- =font= Name of the font to be used. Use the =xft:= prefix for XFT- fonts.+ Example: -- =additionalFonts= Haskell-style list of fonts to be used with the- =fn=-template. Use the =xft:= prefix for XFT fonts. See also- =textOffsets= below. For example:+ #+begin_src shell+ xmobar -B white -a right -F blue -t '%LIPB%' -c '[Run Weather "LIPB" [] 36000]'+ #+end_src - #+begin_src haskell- additionalFonts = [iconFont, altIconFont]+ This is the list of command line options (the output of =xmobar --help=):++ #+begin_src shell+ Usage: xmobar [OPTION...] [FILE]+ Options:+ -h, -? --help This help+ -v --verbose Emit verbose debugging messages+ -r --recompile Force recompilation+ -V --version Show version information+ -f font name --font=font name Font name+ -N font name --add-font=font name Add to the list of additional fonts+ -w class --wmclass=class X11 WM_CLASS property+ -n name --wmname=name X11 WM_NAME property+ -B bg color --bgcolor=bg color The background color. Default black+ -F fg color --fgcolor=fg color The foreground color. Default grey+ -i path --iconroot=path Root directory for icon pattern paths. Default '.'+ -A alpha --alpha=alpha Transparency: 0 is transparent, 255 is opaque. Default: 255+ -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+*** Global options+ Here are all the global configuration options that you can set within+ the =Config= block in your configuration. -- =bgColor= Background color.+ - =font= Name of the font to be used. Use the =xft:= prefix for XFT+ fonts. -- =fgColor= Default font color.+ - =additionalFonts= Haskell-style list of fonts to be used with the+ =fn=-template. Use the =xft:= prefix for XFT fonts. See also+ =textOffsets= below. For example: -- =alpha= The transparency. 0 is transparent, 255 is opaque.+ #+begin_src haskell+ additionalFonts = [iconFont, altIconFont]+ #+end_src -- =position= Top, TopH, TopP, TopW, TopSize, Bottom, BottomH,- BottomP, BottomW, BottomSize or Static (with x, y, width and height).+ - =bgColor= Background color. - TopP and BottomP take 2 arguments: left padding and right padding.+ - =fgColor= Default font color. - 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.+ - =alpha= The transparency. 0 is transparent, 255 is opaque. - 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.+ - =position= Top, TopH, TopP, TopW, TopSize, Bottom, BottomH,+ BottomP, BottomW, BottomSize or Static (with x, y, width and height). - TopH and BottomH take one argument (Int) which adjusts the bar height.+ TopP and BottomP take 2 arguments: left padding and right padding. - For example:+ 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. - #+begin_src haskell- position = TopH 30- #+end_src+ 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. - to make a 30 tall bar on the top, or+ TopH and BottomH take one argument (Int) which adjusts the bar height. - #+begin_src haskell- position = BottomH 30- #+end_src+ For example: - to make a 30 tall bar on the bottom of the screen.+ #+begin_src haskell+ position = TopH 30+ #+end_src - #+begin_src haskell- position = BottomW C 75- #+end_src+ to make a 30 tall bar on the top, or - to place xmobar at the bottom, centered with the 75% of the screen- width. Or+ #+begin_src haskell+ position = BottomH 30+ #+end_src - #+begin_src haskell- position = BottomP 120 0- #+end_src+ to make a 30 tall bar on the bottom of the screen. - to place xmobar at the bottom, with 120 pixel indent of the left. Or+ #+begin_src haskell+ position = BottomW C 75+ #+end_src - #+begin_src haskell- position = Static { xpos = 0 , ypos = 0, width = 1024, height = 15 }- #+end_src+ to place xmobar at the bottom, centered with the 75% of the screen+ width. Or - or+ #+begin_src haskell+ position = BottomP 120 0+ #+end_src - #+begin_src haskell- position = Top- #+end_src+ to place xmobar at the bottom, with 120 pixel indent of the left. Or -- =textOffset= The vertical offset, in pixels, for the text baseline. If- negative or not given, xmobar will try to center text vertically.+ #+begin_src haskell+ position = Static { xpos = 0 , ypos = 0, width = 1024, height = 15 }+ #+end_src -- =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.+ or -- =iconOffset= The vertical offset, in pixels, for icons bottom line. If- negative or not given, xmobar will try to center icons vertically.+ #+begin_src haskell+ position = Top+ #+end_src -- =lowerOnStart= When True the window is sent the bottom of the window- stack initially.+ - =textOffset= The vertical offset, in pixels, for the text baseline. If+ negative or not given, xmobar will try to center text vertically. -- =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.+ - =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. -- =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.+ - =iconOffset= The vertical offset, in pixels, for icons bottom line. If+ negative or not given, xmobar will try to center icons 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=.+ - =lowerOnStart= When True the window is sent the bottom of the window+ stack initially. -- =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.+ - =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. -- =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.+ - =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. -- =border= TopB, TopBM, BottomB, BottomBM, FullB, FullBM or NoBorder- (default).+ - =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=. - TopB, BottomB, FullB take no arguments, and request drawing a border- at the top, bottom or around xmobar's window, respectively.+ - =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. - TopBM, BottomBM, FullBM take an integer argument, which is the margin,- in pixels, between the border of the window and the drawn border.+ - =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. -- =borderColor= Border color.+ - =border= TopB, TopBM, BottomB, BottomBM, FullB, FullBM or NoBorder+ (default). -- =borderWidth= Border width in pixels.+ TopB, BottomB, FullB take no arguments, and request drawing a border+ at the top, bottom or around xmobar's window, respectively. -- =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+ TopBM, BottomBM, FullBM take an integer argument, which is the margin,+ in pixels, between the border of the window and the drawn border. - #+begin_src haskell- iconRoot ++ "/"- #+end_src+ - =borderColor= Border color. - prepended to it. Default is =.=.+ - =borderWidth= Border width in pixels. -- =commands= For setting the options of the programs to run (optional).+ - =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 -- =sepChar= The character to be used for indicating commands in the- output template (default '%').+ #+begin_src haskell+ iconRoot ++ "/"+ #+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.+ prepended to it. Default is =.=. -- =template= The output template.+ - =commands= For setting the options of the programs to run (optional). -- =wmClass= The value for the window's X11 WM_CLASS property. Defaults- to "xmobar".+ - =sepChar= The character to be used for indicating commands in the+ output template (default '%'). -- =wmName= The value for the window's X11 WM_NAME property. Defaults to- "xmobar".+ - =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. -** The Output =template=+ - =template= The output template. -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 name will be tried. If a-command is found, the arguments specified in the =commands= list will be-used.+ - =wmClass= The value for the window's X11 ~WM_CLASS~ property. Defaults+ to "xmobar". -If no command is found in the =commands= list, xmobar will ask the-operating system to execute a program with the name found in the-template. If the execution is not successful an error will be reported.+ - =wmName= The value for the window's X11 ~WM_NAME~ property. Defaults to+ "xmobar". -The syntax for the output template is as follows:+ - =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. -- =%command%= will execute command and print the output. The output may- contain markups to change the characters' color.+ - =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. -- =<fc=#FF0000>string</fc>= will print =string= with =#FF0000= color- (red). =<fc=#FF0000,#000000>string</fc>= will print =string= in red- with a black background (=#000000=). Background absolute offsets can- be specified for XFT fonts. =<fc=#FF0000,#000000:0>string</fc>= will- have a background matching the bar's height.+*** The output =template= -- =<box>string</box>= will print string surrounded by a box in the- foreground color. The =box= tag accepts several optional arguments to- tailor its looks:+ 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+ name will be tried. If a command is found, the arguments specified+ in the =commands= list will be used. - - =type=: =Top=, =Bottom=, =VBoth= (a single line above or below- string, or both), =Left=, =Right=, =HBoth= (single vertical lines),- =Full= (a rectangle, the default).- - =color=: the color of the box lines.- - =width=: the width of the box lines.- - =offset=: an alignment char (L, C or R) followed by the amount of- pixels to offset the box lines; the alignment denotes the position- of the resulting line, with L/R meaning top/bottom for the vertical- lines, and left/right for horizontal ones.- - =mt=, =mb=, =ml=, =mr= specify margins to be added at the top,- bottom, left and right lines.+ If no command is found in the =commands= list, xmobar will ask the+ operating system to execute a program with the name found in the+ template. If the execution is not successful an error will be+ reported. - For example, a box underlining its text with a red line of width 2:+***** Template syntax - #+begin_src shell- <box type=Bottom width=2 color=red>string</box>- #+end_src+ The syntax for the output template is as follows: - and if you wanted an underline and an overline with a margin of 2- pixels either side:+ - =%command%= will execute command and print the output. The output may+ contain markups to change the characters' color. - #+begin_src shell- <box type=VBoth mt=2 mb=2>string</box>- #+end_src+ - =<fc=#FF0000>string</fc>= will print =string= with =#FF0000= color+ (red). =<fc=#FF0000,#000000>string</fc>= will print =string= in red+ with a black background (=#000000=). Background absolute offsets can+ be specified for XFT fonts. =<fc=#FF0000,#000000:0>string</fc>= will+ have a background matching the bar's height. -- =<fn=1>string</fn>= will print =string= with the first font from- =additionalFonts=. The index =0= corresponds to the standard font.+ - =<fn=1>string</fn>= will print =string= with the first font from+ =additionalFonts=. The index =0= corresponds to the standard font. -- =<hspace=X/>= will insert a blank horizontal space of =X= pixels.- For example, to add a blank horizontal space of 123 pixels,- =<hspace=123/>= may be used.+ - =<hspace=X/>= will insert a blank horizontal space of =X= pixels.+ For example, to add a blank horizontal space of 123 pixels,+ =<hspace=123/>= may be used. -- =<icon=/path/to/icon.xbm/>= will insert the given bitmap. XPM image- format is also supported when compiled with the =with_xpm= flag.+ - =<box>string</box>= will print string surrounded by a box in the+ foreground color. The =box= tag accepts several optional arguments to+ tailor its looks: see next section. -- =<action=`command` button=12345>= will execute given command when- clicked with specified buttons. If not specified, button is equal to 1- (left mouse button). Using old syntax (without backticks surrounding- =command=) will result in =button= attribute being ignored.+ - =<icon=/path/to/icon.xbm/>= will insert the given bitmap. XPM image+ format is also supported when compiled with the =with_xpm= flag. -- =<raw=len:str/>= allows the encapsulation of arbitrary text =str=- (which must be =len= =Char=s long, where =len= is encoded as a decimal- sequence). Careful use of this and =UnsafeStdinReader=, for example,- permits window managers to feed xmobar strings with =<action>= tags- mixed with un-trusted content (e.g. window titles). For example, if- xmobar is invoked as+ - =<action=`command` button=12345>= will execute given command when+ clicked with specified buttons. If not specified, button is equal to 1+ (left mouse button). Using old syntax (without backticks surrounding+ =command=) will result in =button= attribute being ignored. - #+begin_src shell- xmobar -c "[Run UnsafeStdinReader]" -t "%UnsafeStdinReader%"- #+end_src+ - =<raw=len:str/>= allows the encapsulation of arbitrary text =str=+ (which must be =len= =Char=s long, where =len= is encoded as a decimal+ sequence). Careful use of this and =UnsafeStdinReader=, for example,+ permits window managers to feed xmobar strings with =<action>= tags+ mixed with un-trusted content (e.g. window titles). For example, if+ xmobar is invoked as - and receives on standard input the line+ #+begin_src shell+ xmobar -c "[Run UnsafeStdinReader]" -t "%UnsafeStdinReader%"+ #+end_src - #+begin_src shell- <action=`echo test` button=1><raw=41:<action=`echo mooo` button=1>foo</action>/></action>`- #+end_src+ and receives on standard input the line - then it will display the text- =<action=`echo mooo` button=1>foo</action>=, which, when clicked, will- cause =test= to be echoed.+ #+begin_src shell+ <action=`echo test` button=1><raw=41:<action=`echo mooo` button=1>foo</action>/></action>`+ #+end_src -*** Bitmap Icons+ then it will display the text+ =<action=`echo mooo` button=1>foo</action>=, which, when clicked, will+ cause =test= to be echoed. -It's possible to insert in the global templates icon directives of the-form:+ See the subsections below for more information on ~<box/>~,+ ~<icon/>~ and ~<action/>~. -#+begin_src shell- <icon=/path/to/bitmap.xbm/>-#+end_src+***** Boxes around text -which will produce the expected result. Accepted image formats are XBM-and XPM (when =with_xpm= flag is enabled). If path does not start with-=/=, =./=, =../= it will have+ - =<box>string</box>= will print string surrounded by a box in the+ foreground color. The =box= tag accepts several optional arguments to+ tailor its looks: -#+begin_src haskell- iconRoot ++ "/"-#+end_src+ - =type=: =Top=, =Bottom=, =VBoth= (a single line above or below+ string, or both), =Left=, =Right=, =HBoth= (single vertical lines),+ =Full= (a rectangle, the default).+ - =color=: the color of the box lines.+ - =width=: the width of the box lines.+ - =offset=: an alignment char (L, C or R) followed by the amount of+ pixels to offset the box lines; the alignment denotes the position+ of the resulting line, with L/R meaning top/bottom for the vertical+ lines, and left/right for horizontal ones.+ - =mt=, =mb=, =ml=, =mr= specify margins to be added at the top,+ bottom, left and right lines. -prepended to it.+ For example, a box underlining its text with a red line of width 2: -*** Action Directives+ #+begin_src shell+ <box type=Bottom width=2 color=red>string</box>+ #+end_src -It's also possible to use action directives of the form:+ and if you wanted an underline and an overline with a margin of 2+ pixels either side: -#+begin_src shell- <action=`command` button=12345>-#+end_src+ #+begin_src shell+ <box type=VBoth mt=2 mb=2>string</box>+ #+end_src -which will be executed when clicked on with specified mouse buttons.-This tag can be nested, allowing different commands to be run depending-on button clicked.+ When xmobar is run in text mode with output format swaybar, box+ types, colors and widths are valid too, but margins and offsets+ are ignored. -** The =commands= Configuration Option+***** Bitmap Icons -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.+ It's possible to insert in the global templates icon directives of the+ form: -The option consists in a list of commands separated by a comma and-enclosed by square parenthesis.+ prepended to it. Default is =.=. -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 shell+ <icon=/path/to/bitmap.xbm/>+ #+end_src -#+begin_src haskell- template = "<icon=/home/jao/.xmobar/mem.xbm/><memory> <swap>"-#+end_src+ which will produce the expected result. Accepted image formats are XBM+ and XPM (when =with_xpm= flag is enabled). If path does not start with+ =/=, =./=, =../= it will have -This example will run "xclock" command when date is clicked:+ #+begin_src haskell+ iconRoot ++ "/"+ #+end_src -#+begin_src haskell- template = "<action=`xclock`>%date%</action>"-#+end_src+ prepended to it. -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.+ Icons are ignored when xmobar is run in text output mode. -Other commands can be created as plugins with the Plugin infrastructure.-See below.-** Running xmobar with =i3status=+***** Action Directives -xmobar can be used to display information generated by [[http://i3wm.org/i3status/][i3status]], a small-program that gathers system information and outputs it in formats-suitable for being displayed by the dzen2 status bar, wmii's status bar-or xmobar's =StdinReader=. See [[http://i3wm.org/i3status/manpage.html#_using_i3status_with_xmobar][i3status manual]] for further details.+ It's also possible to use action directives of the form: -** Dynamically sizing xmobar+ #+begin_src shell+ <action=`command` button=12345>+ #+end_src -See [[https://github.com/jaor/xmobar/issues/239#issuecomment-233206552][this idea]] by Jonas Camillus Jeppensen for a way of adapting-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-[[../examples/padding-icon.sh][examples/padding-icon.sh]].+ which will be executed when clicked on with specified mouse+ buttons. This tag can be nested, allowing different commands to+ be run depending on button clicked. -* Command Line Options+ Actions work also when xmobar is run in text mode and used as+ the status command of swaybar. -xmobar can be either configured with a configuration file or with-command line options. In the second case, the command line options will-overwrite the corresponding options set in the configuration file.+*** The =commands= configuration option -Example:+ 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. -#+begin_src shell- xmobar -B white -a right -F blue -t '%LIPB%' -c '[Run Weather "LIPB" [] 36000]'-#+end_src+ The option consists in a list of commands separated by a comma and+ enclosed by square parenthesis. -This is the list of command line options (the output of =xmobar --help=):+ Example: -#+begin_src shell- Usage: xmobar [OPTION...] [FILE]- Options:- -h, -? --help This help- -v --verbose Emit verbose debugging messages- -r --recompile Force recompilation- -V --version Show version information- -f font name --font=font name Font name- -N font name --add-font=font name Add to the list of additional fonts- -w class --wmclass=class X11 WM_CLASS property- -n name --wmname=name X11 WM_NAME property- -B bg color --bgcolor=bg color The background color. Default black- -F fg color --fgcolor=fg color The foreground color. Default grey- -i path --iconroot=path Root directory for icon pattern paths. Default '.'- -A alpha --alpha=alpha Transparency: 0 is transparent, 255 is opaque. Default: 255- -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+ #+begin_src haskell+ [Run Memory ["-t","Mem: <usedratio>%"] 10, Run Swap [] 10]+ #+end_src - Mail bug reports and suggestions to <mail@jao.io>-#+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 with =i3status=++ xmobar can be used to display information generated by [[http://i3wm.org/i3status/][i3status]], a small+ program that gathers system information and outputs it in formats+ suitable for being displayed by the dzen2 status bar, wmii's status bar+ or xmobar's =StdinReader=. See [[http://i3wm.org/i3status/manpage.html#_using_i3status_with_xmobar][i3status manual]] for further details.++*** Dynamically sizing xmobar++ See [[https://github.com/jaor/xmobar/issues/239#issuecomment-233206552][this idea]] by Jonas Camillus Jeppensen for a way of adapting+ 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+ [[../examples/padding-icon.sh][examples/padding-icon.sh]].++*** Signal Handling++ xmobar reacts to ~SIGUSR1~ and ~SIGUSR2~:++ - After receiving ~SIGUSR1~ xmobar moves its position to the next screen.++ - After receiving ~SIGUSR2~ xmobar repositions itself on the current+ screen.+* The DBus Interface++ When compiled with the optional =with_dbus= flag, xmobar can be+ controlled over dbus. All signals defined in [[https://github.com/jaor/xmobar/blob/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 can+ acquire the dbus. This is handled on a first-come-first-served+ basis, meaning that the first process will get the dbus+ interface. Other processes will run without further problems, yet+ have no dbus interface.++ - Bus Name: =org.Xmobar.Control=+ - Object Path: =/org/Xmobar/Control=+ - Member Name: Any of SignalType, e.g. =string:Reveal=+ - Interface Name: =org.Xmobar.Control=++ An example using the =dbus-send= command line utility:++ #+begin_src shell+ dbus-send \+ --session \+ --dest=org.Xmobar.Control \+ --type=method_call \+ --print-reply \+ '/org/Xmobar/Control' \+ org.Xmobar.Control.SendSignal \+ "string:Toggle 0"+ #+end_src++ It is also possible to send multiple signals at once:++ #+begin_src shell+ # send to another screen, reveal and toggle the persistent flag+ dbus-send [..] \+ "string:ChangeScreen 0" "string:Reveal 0" "string:TogglePersistent"+ #+end_src++ The =Toggle=, =Reveal=, and =Hide= signals take an additional integer+ argument that denotes an initial delay, in tenths of a second,+ before the command takes effect.++ See [[window-managers.org::*Example of using][Interfacing with window managers]] for an example of how to use+ the DBus interface from xmonad.
examples/xmobar.config view
@@ -15,6 +15,7 @@ , iconRoot = "." , allDesktops = True , overrideRedirect = True+ , textOutputFormat = Ansi , commands = [ Run Weather "EGPF" ["-t","<station>: <tempC>C", "-L","18","-H","25", "--normal","green",
examples/xmobar.hs view
@@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- |--- Copyright: (c) 2018, 2019 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -49,6 +49,7 @@ , iconRoot = "." , allDesktops = True , overrideRedirect = True+ , textOutputFormat = Ansi , commands = [ Run $ Weather "EGPH" ["-t","<station>: <tempC>C", "-L","18","-H","25", "--normal","green",
readme.org view
@@ -1,14 +1,15 @@-[[http://hackage.haskell.org/package/xmobar][https://img.shields.io/hackage/v/xmobar.svg]]+#+title: xmobar, a minimalistic status bar -* About+[[http://hackage.haskell.org/package/xmobar][https://img.shields.io/hackage/v/xmobar.svg]] Xmobar is a minimalistic status bar. It was originally designed and-implemented by Andrea Rossato to work with [[http://xmonad.org][xmonad]], but it is actually-usable with any window manager.+implemented to work with [[http://xmonad.org][xmonad]], but it is actually usable with any+window manager in X11 and also (via its text output mode) Wayland. Xmobar was inspired by the [[http://tuomov.iki.fi/software/][Ion3]] status bar, and supports similar features, like dynamic color management, icons, output templates, and-extensibility through plugins.+extensibility through plugins. It is also able to write to standard+output, in a variety of formats. These are some xmobar [[file:doc/screenshots][screenshots]] using the author's configuration: @@ -18,160 +19,208 @@ [[file:doc/screenshots/xmobar-exwm.png]] -This is the [[https://xmobar.org/changelog.html][changelog]] for recent releases.+Check [[./changelog.md][the change log]] for our release history. We also have an IRC+channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. * Installation-** From your Systems Package Manager+*** From your system's package manager -Xmobar is probably available from your distributions package manager!-Most distributions compile xmobar with the =all_extensions= flag, so you-don't have to.+ Xmobar is probably available from your distributions package+ manager! Most distributions compile xmobar with the =all_extensions=+ flag, so you don't have to. -*** Arch Linux+***** Arch Linux -#+begin_src shell- pacman -S xmobar-#+end_src+ #+begin_src shell+ pacman -S xmobar+ #+end_src -*** Debian/Ubuntu based+***** Debian/Ubuntu based -#+begin_src shell- apt install xmobar-#+end_src+ #+begin_src shell+ apt install xmobar+ #+end_src -*** OpenSUSE+***** OpenSUSE -#+begin_src shell- zypper install xmobar-#+end_src+ #+begin_src shell+ zypper install xmobar+ #+end_src -*** Void Linux+***** Void Linux -#+begin_src shell- xbps-install xmobar-#+end_src+ #+begin_src shell+ xbps-install xmobar+ #+end_src -*** Gentoo-#+begin_src shell- emerge --ask xmobar-#+end_src+***** Gentoo+ #+begin_src shell+ emerge --ask xmobar+ #+end_src -** Using cabal-install+*** Using cabal-install -Xmobar is available from [[http://hackage.haskell.org/package/xmobar/][Hackage]], and you can install it using-=cabal-install=:+ Xmobar is available from [[http://hackage.haskell.org/package/xmobar/][Hackage]], and you can install it using+ =cabal-install=: -#+begin_src shell- cabal install xmobar-#+end_src+ #+begin_src shell+ cabal install xmobar+ #+end_src -Starting with version 0.35.1, xmobar now requires at least GHC version-8.4.x. to build. See [[https://github.com/jaor/xmobar/issues/461][this issue]] for more information.+ Starting with version 0.35.1, xmobar now requires at least GHC+ version 8.4.x. to build. See [[https://github.com/jaor/xmobar/issues/461][this issue]] for more information. -See [[file:doc/compiling.org][compiling]] for a list of optional compilation flags that will enable-some optional plugins. For instance, to install xmobar with all the-bells and whistles (this is probably what you want), use:+ See [[file:doc/compiling.org][compiling]] for a list of optional compilation flags that will+ enable some optional plugins. For instance, to install xmobar with+ all the bells and whistles (this is probably what you want), use: -#+begin_src shell- cabal install xmobar --flags="all_extensions"-#+end_src+ #+begin_src shell+ cabal install xmobar --flags="all_extensions"+ #+end_src -** From source+*** From source -See [[file:doc/compiling.org][compiling]].+ See [[file:doc/compiling.org][compiling]]. * Running xmobar -You can run xmobar with:+ You can run xmobar with: -#+begin_src shell- xmobar /path/to/config &-#+end_src+ #+begin_src shell+ xmobar /path/to/config &+ #+end_src -or+ or -#+begin_src shell- xmobar &-#+end_src+ #+begin_src shell+ xmobar &+ #+end_src -if you have the default configuration file saved as-=$XDG\_CONFIG\_HOME/xmobar/xmobarrc= (defaulting to-=~/.config/xmobar/xmobarrc=), or =~/.xmobarrc=.+ if you have the default configuration file saved as+ =$XDG_CONFIG_HOME/xmobar/xmobarrc= (defaulting to+ =~/.config/xmobar/xmobarrc=), or =~/.xmobarrc=. -** Signal Handling+*** Running xmobar in text mode -Since 0.14 xmobar reacts to SIGUSR1 and SIGUSR2:+ By default, xmobar will run as an X11 application, in a docked+ window, but it is possible to redirect xmobar's 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+ (so, for instance, you could pipe xmobar's output to a Wayland+ application, such as swaybar.) -- After receiving SIGUSR1 xmobar moves its position to the next screen.+ To run xmobar in text mode, either pass the =-T= flag to its+ invocation: -- After receiving SIGUSR2 xmobar repositions itself on the current- screen.+ #+begin_src shell+ xmobar -T /path/to/config &+ #+end_src -* Configuration and Further Links+ or set the parameter =textOutput= to True in its configuration. You+ can also specify the format of color escapes, for instance,+ omitting them altogether with ~Plain~: -- If you want to jump straight into configuring xmobar, head over to the- [[./doc/quick-start.org][quick-start]] guide.+ #+begin_src shell+ xmobar -TPlain /path/to/config &+ #+end_src -- If you want to get a detailed overview of all available plugins and- monitors, visit the [[./doc/plugins.org][plugins]] file.+ Other options are ~Ansi~, ~Pango~, and ~Swaybar~. -- If you want to know how to contribute to the xmobar project, check out- [[contributing.org][contributing]].+*** Using xmobar in Wayland with swaybar or waybar -- If you want to write your own plugins, see [[./doc/write-your-own-plugin.org][write-your-own-plugin]].+ In text mode, xmobar can be told to ouput its information using+ pango markup for colors and fonts, and it that way you can use it+ with swaybar or waybar, if you don't have actions or boxes in your+ template. Here's a minimal ~bar~ configuration for sway's+ configuration file: -* Authors and credits+ #+begin_src conf+ bar {+ status_command xmobar -TPango+ pango_markup enabled+ }+ #+end_src -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 case you want to use boxes around text or click actions in your+ template, you can use instead the format ~Swaybar~, which supports+ both. This output format follows the JSON /swaybar-protocol/+ defined by swaybar. Configure it simply with: -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,-Reto Hablützel, Juraj Hercek, Tomáš Janoušek, Ada Joule, Spencer-Janssen, Roman Joost, 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-Michal Zielonka.+ #+begin_src conf+ bar {+ status_command xmobar -TSwaybar+ }+ #+end_src -** Thanks+* Configuration and further Links -*Andrea Rossato*:+ - If you want to jump straight into running xmobar, head over to the+ [[./doc/quick-start.org][quick start guide]]. -Thanks to Robert Manea and Spencer Janssen for their help in-understanding how X works. They gave me suggestions on how to solve many-problems with xmobar.+ - If you want to get a detailed overview of all available plugins and+ monitors, visit the [[./doc/plugins.org][plugins index]]. -Thanks to Claus Reinke for make me understand existential types (or at-least for letting me think I grasp existential types...;-).+ - [[./doc/window-managers.org][Interfacing with window managers]] describes plugins and extensions+ for interacting with xmobar from your window manager. -*jao*:+ - If you want to know how to contribute to the xmobar project, check out+ [[contributing.org][contributing]]. -Thanks to Andrea for creating xmobar in the first place, and for giving-me the chance to contribute.+ - If you want to write your own plugins, see [[./doc/write-your-own-plugin.org][Write your own plugin]]. -* Related+ - To understand the internal mysteries of xmobar you may try reading+ [[https://wiki.haskell.org/X_window_programming_in_Haskell][this tutorial]] on X Window Programming in Haskell. -- To understand the internal mysteries of xmobar you may try reading- [[https://wiki.haskell.org/X_window_programming_in_Haskell][this tutorial]] on X Window Programming in Haskell.+* 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, 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 Michal+ Zielonka.++*** Thanks++ *Andrea Rossato*:++ Thanks to Robert Manea and Spencer Janssen for their help in+ understanding how X works. They gave me suggestions on how to solve many+ problems with xmobar.++ Thanks to Claus Reinke for make me understand existential types (or at+ least for letting me think I grasp existential types...;-).++ *jao*:++ Thanks to Andrea for creating xmobar in the first place, and for giving+ me the chance to contribute.++ * License This software is released under a BSD-style license. See [[https://github.com/jaor/xmobar/raw/master/license][license]] for more details. -Copyright © 2010-2020 Jose Antonio Ortega Ruiz+Copyright © 2010-2022 Jose Antonio Ortega Ruiz Copyright © 2007-2010 Andrea Rossato
src/Xmobar.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Xmobar--- Copyright : (c) 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2019 Jose Antonio Ortega Ruiz+-- Copyright : (c) 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2019, 2022 Jose Antonio Ortega Ruiz -- (c) 2007 Andrea Rossato -- License : BSD-style (see LICENSE) --@@ -51,9 +51,9 @@ import Xmobar.Run.Runnable import Xmobar.Run.Exec-import Xmobar.Run.Command import Xmobar.Config.Types import Xmobar.Config.Parse+import Xmobar.Plugins.Command import Xmobar.Plugins.BufferedPipeReader import Xmobar.Plugins.CommandReader import Xmobar.Plugins.Date
src/Xmobar/App/Config.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Config.Defaults--- Copyright: (c) 2018, 2019, 2020 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -65,6 +65,8 @@ "<fc=#00FF00>%uname%</fc> * <fc=#FF0000>%theDate%</fc>" , verbose = False , signal = SignalChan Nothing+ , textOutput = False+ , textOutputFormat = Plain } -- | Return the path to the xmobar data directory. This directory is
− src/Xmobar/App/EventLoop.hs
@@ -1,283 +0,0 @@-{-# LANGUAGE CPP #-}----------------------------------------------------------------------------------- |--- Module: Xmobar.X11.EventLoop--- Copyright: (c) 2018, 2020 Jose Antonio Ortega Ruiz--- License: BSD3-style (see LICENSE)------ Maintainer: jao@gnu.org--- Stability: unstable--- Portability: portable--- Created: Sat Nov 24, 2018 19:40--------- Event loop-------------------------------------------------------------------------------------module Xmobar.App.EventLoop- ( startLoop- , startCommand- , newRefreshLock- , refreshLock- ) where--import Prelude hiding (lookup)-import Graphics.X11.Xlib hiding (textExtents, textWidth)-import Graphics.X11.Xlib.Extras-import Graphics.X11.Xinerama-import Graphics.X11.Xrandr--import Control.Arrow ((&&&))-import Control.Monad.Reader-import Control.Concurrent-import Control.Concurrent.Async (Async, async)-import Control.Concurrent.STM-import Control.Exception (bracket_, handle, SomeException(..))-import Data.Bits-import Data.Map hiding (foldr, map, filter)-import Data.Maybe (fromJust, isJust)-import qualified Data.List.NonEmpty as NE--import Xmobar.System.Signal-import Xmobar.Config.Types (persistent, position, iconRoot, Config, Align(..), XPosition(..))-import Xmobar.Run.Exec-import Xmobar.Run.Runnable-import Xmobar.X11.Actions-import Xmobar.X11.Parsers-import Xmobar.X11.Window-import Xmobar.X11.Text-import Xmobar.X11.Draw-import Xmobar.X11.Bitmap as Bitmap-import Xmobar.X11.Types-import Xmobar.System.Utils (safeIndex)--#ifndef THREADED_RUNTIME-import Xmobar.X11.Events(nextEvent')-#endif--#ifdef XFT-import Graphics.X11.Xft-#endif--#ifdef DBUS-import Xmobar.System.DBus-#endif--runX :: XConf -> X () -> IO ()-runX xc f = runReaderT f xc--newRefreshLock :: IO (TMVar ())-newRefreshLock = newTMVarIO ()--refreshLock :: TMVar () -> IO a -> IO a-refreshLock var = bracket_ lock unlock- where- lock = atomically $ takeTMVar var- unlock = atomically $ putTMVar var ()--refreshLockT :: TMVar () -> STM a -> STM a-refreshLockT var action = do- takeTMVar var- r <- action- putTMVar var ()- return r---- | Starts the main event loop and threads-startLoop :: XConf- -> TMVar SignalType- -> TMVar ()- -> [[([Async ()], TVar String)]]- -> IO ()-startLoop xcfg@(XConf _ _ w _ _ _ _) sig pauser vs = do-#ifdef XFT- xftInitFtLibrary-#endif- tv <- newTVarIO []- _ <- forkIO (handle (handler "checker") (checker tv [] vs sig pauser))-#ifdef THREADED_RUNTIME- _ <- forkOS (handle (handler "eventer") (eventer sig))-#else- _ <- forkIO (handle (handler "eventer") (eventer sig))-#endif-#ifdef DBUS- runIPC sig-#endif- eventLoop tv xcfg [] sig- where- handler thing (SomeException e) =- void $ putStrLn ("Thread " ++ thing ++ " failed: " ++ show e)- -- Reacts on events from X- eventer signal =- allocaXEvent $ \e -> do- dpy <- openDisplay ""- xrrSelectInput dpy (defaultRootWindow dpy) rrScreenChangeNotifyMask- selectInput dpy w (exposureMask .|. structureNotifyMask .|. buttonPressMask)-- forever $ do-#ifdef THREADED_RUNTIME- nextEvent dpy e-#else- nextEvent' dpy e-#endif- ev <- getEvent e- case ev of- ConfigureEvent {} -> atomically $ putTMVar signal Reposition- ExposeEvent {} -> atomically $ putTMVar signal Wakeup- RRScreenChangeNotifyEvent {} -> atomically $ putTMVar signal Reposition- ButtonEvent {} -> atomically $- putTMVar signal (Action (ev_button ev) (fi $ ev_x ev))- _ -> return ()---- | Send signal to eventLoop every time a var is updated-checker :: TVar [String]- -> [String]- -> [[([Async ()], TVar String)]]- -> TMVar SignalType- -> TMVar ()- -> IO ()-checker tvar ov vs signal pauser = do- nval <- atomically $ refreshLockT pauser $ do- nv <- mapM concatV vs- guard (nv /= ov)- writeTVar tvar nv- return nv- atomically $ putTMVar signal Wakeup- checker tvar nval vs signal pauser- where- concatV = fmap concat . mapM (readTVar . snd)----- | Continuously wait for a signal from a thread or a interrupt handler-eventLoop :: TVar [String]- -> XConf- -> [([Action], Position, Position)]- -> TMVar SignalType- -> IO ()-eventLoop tv xc@(XConf d r w fs vos is cfg) as signal = do- typ <- atomically $ takeTMVar signal- case typ of- Wakeup -> do- str <- updateString cfg tv- xc' <- updateCache d w is (iconRoot cfg) str >>=- \c -> return xc { iconS = c }- as' <- updateActions xc r str- runX xc' $ drawInWin r str- eventLoop tv xc' as' signal-- Reposition ->- reposWindow cfg-- ChangeScreen -> do- ncfg <- updateConfigPosition cfg- reposWindow ncfg-- Hide t -> hide (t*100*1000)- Reveal t -> reveal (t*100*1000)- Toggle t -> toggle t-- TogglePersistent -> eventLoop- tv xc { config = cfg { persistent = not $ persistent cfg } } as signal-- Action but x -> action but x-- where- isPersistent = not $ persistent cfg-- hide t- | t == 0 =- when isPersistent (hideWindow d w) >> eventLoop tv xc as signal- | otherwise = do- void $ forkIO- $ threadDelay t >> atomically (putTMVar signal $ Hide 0)- eventLoop tv xc as signal-- reveal t- | t == 0 = do- when isPersistent (showWindow r cfg d w)- eventLoop tv xc as signal- | otherwise = do- void $ forkIO- $ threadDelay t >> atomically (putTMVar signal $ Reveal 0)- eventLoop tv xc as signal-- toggle t = do- ismapped <- isMapped d w- atomically (putTMVar signal $ if ismapped then Hide t else Reveal t)- eventLoop tv xc as signal-- reposWindow rcfg = do- r' <- repositionWin d w (NE.head fs) rcfg- eventLoop tv (XConf d r' w fs vos is rcfg) as signal-- updateConfigPosition ocfg =- case position ocfg of- OnScreen n o -> do- srs <- getScreenInfo d- return (if n == length srs- then- (ocfg {position = OnScreen 1 o})- else- (ocfg {position = OnScreen (n+1) o}))- o -> return (ocfg {position = OnScreen 1 o})-- action button x = do- mapM_ runAction $- filter (\(Spawn b _) -> button `elem` b) $- concatMap (\(a,_,_) -> a) $- filter (\(_, from, to) -> x >= from && x <= to) as- eventLoop tv xc as signal---- $command---- | Runs a command as an independent thread and returns its Async handles--- and the TVar the command will be writing to.-startCommand :: TMVar SignalType- -> (Runnable,String,String)- -> IO ([Async ()], TVar String)-startCommand sig (com,s,ss)- | alias com == "" = do var <- newTVarIO is- atomically $ writeTVar var (s ++ ss)- return ([], var)- | otherwise = do var <- newTVarIO is- let cb str = atomically $ writeTVar var (s ++ str ++ ss)- a1 <- async $ start com cb- a2 <- async $ trigger com $ maybe (return ())- (atomically . putTMVar sig)- return ([a1, a2], var)- where is = s ++ "Updating..." ++ ss--updateString :: Config -> TVar [String]- -> IO [[(Widget, TextRenderInfo, Int, Maybe [Action])]]-updateString conf v = do- s <- readTVarIO v- let l:c:r:_ = s ++ repeat ""- liftIO $ mapM (parseString conf) [l, c, r]--updateActions :: XConf -> Rectangle -> [[(Widget, TextRenderInfo, Int, Maybe [Action])]]- -> IO [([Action], Position, Position)]-updateActions conf (Rectangle _ _ wid _) ~[left,center,right] = do- let (d,fs) = (display &&& fontListS) conf- strLn :: [(Widget, TextRenderInfo, Int, Maybe [Action])] -> IO [(Maybe [Action], Position, Position)]- strLn = liftIO . mapM getCoords- iconW i = maybe 0 Bitmap.width (lookup i $ iconS conf)- getCoords (Text s,_,i,a) = textWidth d (safeIndex fs i) s >>= \tw -> return (a, 0, fi tw)- getCoords (Icon s,_,_,a) = return (a, 0, fi $ iconW s)- getCoords (Hspace w,_,_,a) = return (a, 0, fi w)- partCoord off xs = map (\(a, x, x') -> (fromJust a, x, x')) $- filter (\(a, _,_) -> isJust a) $- scanl (\(_,_,x') (a,_,w') -> (a, x', x' + w'))- (Nothing, 0, off)- xs- totSLen = foldr (\(_,_,len) -> (+) len) 0- remWidth xs = fi wid - totSLen xs- offs = 1- offset a xs = case a of- C -> (remWidth xs + offs) `div` 2- R -> remWidth xs- L -> offs- fmap concat $ mapM (\(a,xs) ->- (\xs' -> partCoord (offset a xs') xs') <$> strLn xs) $- zip [L,C,R] [left,center,right]
src/Xmobar/App/Main.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.App.Main--- Copyright: (c) 2018, 2019, 2020 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -17,66 +17,29 @@ module Xmobar.App.Main (xmobar, xmobarMain, configFromArgs) where -import Control.Concurrent.Async (Async, cancel)-import Control.Concurrent.STM (newEmptyTMVarIO)-import Control.Exception (bracket)-import Control.Monad (unless) -import Data.Foldable (for_)-import qualified Data.Map as Map import Data.List (intercalate)-import Data.Maybe (isJust) import System.Posix.Process (executeFile) import System.Environment (getArgs) import System.FilePath ((</>), takeBaseName, takeDirectory, takeExtension) import Text.Parsec.Error (ParseError)-import Data.List.NonEmpty (NonEmpty(..)) -import Graphics.X11.Xlib+import Control.Monad (unless) +import Xmobar.App.Config import Xmobar.Config.Types import Xmobar.Config.Parse-import Xmobar.System.Signal (setupSignalHandler, withDeferSignals)-import Xmobar.Run.Template-import Xmobar.X11.Types-import Xmobar.X11.Text-import Xmobar.X11.Window+import Xmobar.X11.Loop (x11Loop)+import Xmobar.Text.Loop (textLoop) import Xmobar.App.Opts (recompileFlag, verboseFlag, getOpts, doOpts)-import Xmobar.App.EventLoop (startLoop, startCommand, newRefreshLock, refreshLock) import Xmobar.App.Compile (recompile, trace)-import Xmobar.App.Config-import Xmobar.App.Timer (withTimer) xmobar :: Config -> IO ()-xmobar conf = withDeferSignals $ do- initThreads- d <- openDisplay ""- fs <- initFont d (font conf)- fl <- mapM (initFont d) (additionalFonts conf)- cls <- mapM (parseTemplate (commands conf) (sepChar conf))- (splitTemplate (alignSep conf) (template conf))- let confSig = unSignalChan (signal conf)- sig <- maybe newEmptyTMVarIO pure confSig- unless (isJust confSig) $ setupSignalHandler sig- refLock <- newRefreshLock- withTimer (refreshLock refLock) $- bracket (mapM (mapM $ startCommand sig) cls)- cleanupThreads- $ \vars -> do- (r,w) <- createWin d fs conf- let ic = Map.empty- to = textOffset conf- ts = textOffsets conf ++ replicate (length fl) (-1)- startLoop (XConf d r w (fs :| fl) (to :| ts) ic conf) sig refLock vars+xmobar cfg = if textOutput cfg then textLoop cfg else x11Loop cfg configFromArgs :: Config -> IO Config configFromArgs cfg = getArgs >>= getOpts >>= doOpts cfg . fst -cleanupThreads :: [[([Async ()], a)]] -> IO ()-cleanupThreads vars =- for_ (concat vars) $ \(asyncs, _) ->- for_ asyncs cancel- buildLaunch :: [String] -> Bool -> Bool -> String -> ParseError -> IO () buildLaunch args verb force p e = do let exec = takeBaseName p@@ -110,5 +73,6 @@ Just p -> do r <- readConfig defaultConfig p case r of Left e ->- buildLaunch (filter (/= p) args) (verboseFlag flags) (recompileFlag flags) p e+ buildLaunch (filter (/= p) args) (verboseFlag flags)+ (recompileFlag flags) p e Right (c, defs) -> doOpts c flags >>= xmobar' defs
src/Xmobar/App/Opts.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.App.Opts--- Copyright: (c) 2018, 2019, 2020 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -14,7 +14,10 @@ -- ------------------------------------------------------------------------------ -module Xmobar.App.Opts (recompileFlag, verboseFlag, getOpts, doOpts) where+module Xmobar.App.Opts ( recompileFlag+ , verboseFlag+ , getOpts+ , doOpts) where import Control.Monad (when) import System.Console.GetOpt@@ -30,24 +33,25 @@ | Verbose | Recompile | Version- | Font String- | AddFont String- | BgColor String- | FgColor String- | Alpha String+ | TextOutput (Maybe String)+ | Font String+ | AddFont String+ | BgColor String+ | FgColor String+ | Alpha String | T | B | D- | AlignSep String- | Commands String+ | AlignSep String+ | Commands String | AddCommand String- | SepChar String- | Template String- | OnScr String- | IconRoot String- | Position String- | WmClass String- | WmName String+ | SepChar String+ | Template String+ | OnScr String+ | IconRoot String+ | Position String+ | WmClass String+ | WmName String deriving (Show, Eq) options :: [OptDescr Opts]@@ -56,8 +60,11 @@ , Option "v" ["verbose"] (NoArg Verbose) "Emit verbose debugging messages" , Option "r" ["recompile"] (NoArg Recompile) "Force recompilation" , Option "V" ["version"] (NoArg Version) "Show version information"+ , Option "T" ["text"] (OptArg TextOutput "color")+ "Write text-only output to stdout. Plain/Ansi/Pango/Swaybar" , Option "f" ["font"] (ReqArg Font "font name") "Font name"- , Option "N" ["add-font"] (ReqArg AddFont "font name") "Add to the list of additional fonts"+ , Option "N" ["add-font"] (ReqArg AddFont "font name")+ "Add to the list of additional fonts" , Option "w" ["wmclass"] (ReqArg WmClass "class") "X11 WM_CLASS property" , Option "n" ["wmname"] (ReqArg WmName "name") "X11 WM_NAME property" , Option "B" ["bgcolor"] (ReqArg BgColor "bg color" )@@ -106,7 +113,7 @@ info :: String info = "xmobar " ++ showVersion version- ++ "\n (C) 2010 - 2020 Jose A Ortega Ruiz"+ ++ "\n (C) 2010 - 2022 Jose A Ortega Ruiz" ++ "\n (C) 2007 - 2010 Andrea Rossato\n " ++ mail ++ "\n" ++ license ++ "\n" @@ -127,6 +134,10 @@ Help -> doOpts' conf Version -> doOpts' conf Recompile -> doOpts' conf+ TextOutput s -> doOpts' $ case s of+ Just fmt -> conf {textOutput = True,+ textOutputFormat = read fmt}+ Nothing -> conf {textOutput = True} Verbose -> doOpts' (conf {verbose = True}) Font s -> doOpts' (conf {font = s}) AddFont s -> doOpts' (conf {additionalFonts = additionalFonts conf ++ [s]})
− src/Xmobar/App/Timer.hs
@@ -1,221 +0,0 @@-{-# LANGUAGE LambdaCase #-}---------------------------------------------------------------------------------- |--- Module: Xmobar.App.Timer--- Copyright: (c) 2019, 2020 Tomáš Janoušek--- License: BSD3-style (see LICENSE)------ Maintainer: Tomáš Janoušek <tomi@nomi.cz>--- Stability: unstable------ Timer coalescing for recurring actions.------------------------------------------------------------------------------------module Xmobar.App.Timer- ( doEveryTenthSeconds- , tenthSeconds- , withTimer- ) where--import Control.Concurrent (threadDelay)-import Control.Concurrent.Async (withAsync)-import Control.Concurrent.STM-import Control.Exception-import Control.Monad (forever, forM, guard)-import Data.Foldable (foldrM, for_)-import Data.Int (Int64)-import Data.Map (Map)-import qualified Data.Map as M-import Data.Maybe (isJust, fromJust)-import Data.Time.Clock.POSIX (getPOSIXTime)-import Data.Unique-import System.IO.Unsafe (unsafePerformIO)--type Periods = Map Unique Period--data Tick = Tick (TMVar ()) | UnCoalesce--data Period = Period { rate :: Int64, next :: Int64, tick :: TMVar Tick }--data UnCoalesceException = UnCoalesceException deriving Show-instance Exception UnCoalesceException--{-# NOINLINE periodsVar #-}-periodsVar :: TVar (Maybe Periods)-periodsVar = unsafePerformIO $ newTVarIO Nothing--now :: IO Int64-now = do- posix <- getPOSIXTime- return $ floor (10 * posix)--newPeriod :: Int64 -> IO (Unique, Period)-newPeriod r = do- u <- newUnique- t <- now- v <- newEmptyTMVarIO- let t' = t - t `mod` r- return (u, Period { rate = r, next = t', tick = v })---- | Perform a given action every N tenths of a second.------ The timer is aligned (coalesced) with other timers to minimize the number--- of wakeups and unnecessary redraws. If the action takes too long (one--- second or when the next timer is due), coalescing is disabled for it and it--- falls back to periodic sleep.-doEveryTenthSeconds :: Int -> IO () -> IO ()-doEveryTenthSeconds r action =- doEveryTenthSecondsCoalesced r action `catch` \UnCoalesceException ->- doEveryTenthSecondsSleeping r action---- | Perform a given action every N tenths of a second,--- coalesce with other timers using a given Timer instance.-doEveryTenthSecondsCoalesced :: Int -> IO () -> IO ()-doEveryTenthSecondsCoalesced r action = do- (u, p) <- newPeriod (fromIntegral r)- bracket_ (push u p) (pop u) $ forever $ bracket (wait p) done $ const action- where- push u p = atomically $ modifyTVar' periodsVar $ \case- Just periods -> Just $ M.insert u p periods- Nothing -> throw UnCoalesceException- pop u = atomically $ modifyTVar' periodsVar $ \case- Just periods -> Just $ M.delete u periods- Nothing -> Nothing-- wait p = atomically (takeTMVar $ tick p) >>= \case- Tick doneVar -> return doneVar- UnCoalesce -> throwIO UnCoalesceException- done doneVar = atomically $ putTMVar doneVar ()---- | Perform a given action every N tenths of a second,--- making no attempt to synchronize with other timers.-doEveryTenthSecondsSleeping :: Int -> IO () -> IO ()-doEveryTenthSecondsSleeping r action = go- where go = action >> tenthSeconds r >> go---- | Sleep for a given amount of tenths of a second.------ (Work around the Int max bound: since threadDelay takes an Int, it--- is not possible to set a thread delay grater than about 45 minutes.--- With a little recursion we solve the problem.)-tenthSeconds :: Int -> IO ()-tenthSeconds s | s >= x = do threadDelay (x * 100000)- tenthSeconds (s - x)- | otherwise = threadDelay (s * 100000)- where x = (maxBound :: Int) `div` 100000---- | Start the timer coordination thread and perform a given IO action (this--- is meant to surround the entire xmobar execution), terminating the timer--- thread afterwards.------ Additionally, if the timer thread fails, individual--- 'doEveryTenthSecondsCoalesced' invocations that are waiting to be--- coordinated by it are notified to fall back to periodic sleeping.------ The timer thread _will_ fail immediately when running in a non-threaded--- RTS.-withTimer :: (IO () -> IO ()) -> IO a -> IO a-withTimer pauseRefresh action =- withAsync (timerThread `finally` cleanup) $ const action- where- timerThread = do- atomically $ writeTVar periodsVar $ Just M.empty- timerLoop pauseRefresh-- cleanup = atomically $ readTVar periodsVar >>= \case- Just periods -> do- for_ periods unCoalesceTimer'- writeTVar periodsVar Nothing- Nothing -> return ()--timerLoop :: (IO () -> IO ()) -> IO ()-timerLoop pauseRefresh = forever $ do- tNow <- now- (toFire, tMaybeNext) <- atomically $ do- periods <- fromJust <$> readTVar periodsVar- let toFire = timersToFire tNow periods- let periods' = advanceTimers tNow periods- let tMaybeNext = nextFireTime periods'- writeTVar periodsVar $ Just periods'- return (toFire, tMaybeNext)- pauseRefresh $ do- -- To avoid multiple refreshes, pause refreshing for up to 1 second,- -- fire timers and wait for them to finish (update their text).- -- Those that need more time (e.g. weather monitors) will be dropped- -- from timer coalescing and will fall back to periodic sleep.- timeoutVar <- registerDelay $ case tMaybeNext of- Just tNext -> fromIntegral ((tNext - tNow) `max` 10) * 100000- Nothing -> 1000000- fired <- fireTimers toFire- timeouted <- waitForTimers timeoutVar fired- unCoalesceTimers timeouted- delayUntilNextFire--advanceTimers :: Int64 -> Periods -> Periods-advanceTimers t = M.map advance- where- advance p | next p <= t = p { next = t - t `mod` rate p + rate p }- | otherwise = p--timersToFire :: Int64 -> Periods -> [(Unique, Period)]-timersToFire t periods = [ (u, p) | (u, p) <- M.toList periods, next p <= t ]--nextFireTime :: Periods -> Maybe Int64-nextFireTime periods- | M.null periods = Nothing- | otherwise = Just $ minimum [ next p | p <- M.elems periods ]--fireTimers :: [(Unique, Period)] -> IO [(Unique, TMVar ())]-fireTimers toFire = atomically $ forM toFire $ \(u, p) -> do- doneVar <- newEmptyTMVar- putTMVar (tick p) (Tick doneVar)- return (u, doneVar)--waitForTimers :: TVar Bool -> [(Unique, TMVar ())] -> IO [Unique]-waitForTimers timeoutVar fired = atomically $ do- timeoutOver <- readTVar timeoutVar- dones <- forM fired $ \(u, doneVar) -> do- done <- isJust <$> tryReadTMVar doneVar- return (u, done)- guard $ timeoutOver || all snd dones- return [u | (u, False) <- dones]---- | Handle slow timers (drop and signal them to stop coalescing).-unCoalesceTimers :: [Unique] -> IO ()-unCoalesceTimers timers = atomically $ do- periods <- fromJust <$> readTVar periodsVar- periods' <- foldrM unCoalesceTimer periods timers- writeTVar periodsVar $ Just periods'--unCoalesceTimer :: Unique -> Periods -> STM Periods-unCoalesceTimer u periods = do- unCoalesceTimer' (periods M.! u)- return $ u `M.delete` periods--unCoalesceTimer' :: Period -> STM ()-unCoalesceTimer' p = do- _ <- tryTakeTMVar (tick p)- putTMVar (tick p) UnCoalesce--delayUntilNextFire :: IO ()-delayUntilNextFire = do- Just periods <- readTVarIO periodsVar- let tMaybeNext = nextFireTime periods- tNow <- now- delayVar <- case tMaybeNext of- Just tNext -> do- -- Work around the Int max bound: threadDelay takes an Int, we can- -- only sleep for so long, which is okay, we'll just check timers- -- sooner and sleep again.- let maxDelay = (maxBound :: Int) `div` 100000- delay = (tNext - tNow) `min` fromIntegral maxDelay- delayUsec = fromIntegral delay * 100000- registerDelay delayUsec- Nothing -> newTVarIO False- atomically $ do- delayOver <- readTVar delayVar- periods' <- fromJust <$> readTVar periodsVar- let tMaybeNext' = nextFireTime periods'- -- Return also if a new period is added (it may fire sooner).- guard $ delayOver || tMaybeNext /= tMaybeNext'
src/Xmobar/Config/Parse.hs view
@@ -2,7 +2,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Config.Parse--- Copyright: (c) 2018, 2020 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2020, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -61,8 +61,9 @@ perms = permute $ Config <$?> pFont <|?> pFontList <|?> pWmClass <|?> pWmName- <|?> pBgColor <|?> pFgColor- <|?> pPosition <|?> pTextOffset <|?> pTextOffsets+ <|?> pBgColor <|?> pFgColor <|?> pPosition+ <|?> pTextOutput <|?> pTextOutputFormat+ <|?> pTextOffset <|?> pTextOffsets <|?> pIconOffset <|?> pBorder <|?> pBdColor <|?> pBdWidth <|?> pAlpha <|?> pHideOnStart <|?> pAllDesktops <|?> pOverrideRedirect <|?> pPickBroadest@@ -70,15 +71,18 @@ <|?> pCommands <|?> pSepChar <|?> pAlignSep <|?> pTemplate <|?> pVerbose <|?> pSignal - fields = [ "font", "additionalFonts","bgColor", "fgColor"+ fields = [ "font", "additionalFonts", "bgColor", "fgColor" , "wmClass", "wmName", "sepChar" , "alignSep" , "border", "borderColor" ,"template" , "position" , "textOffset", "textOffsets", "iconOffset" , "allDesktops", "overrideRedirect", "pickBroadest" , "hideOnStart", "lowerOnStart", "persistent", "iconRoot"- , "alpha", "commands", "verbose", "signal"+ , "alpha", "commands", "verbose", "signal", "textOutput"+ , "textOutputFormat" ] + pTextOutput = readField textOutput "textOutput"+ pTextOutputFormat = readField textOutputFormat "textOutputFormat" pFont = strField font "font" pFontList = strListField additionalFonts "additionalFonts" pWmClass = strField wmClass "wmClass"
src/Xmobar/Config/Types.hs view
@@ -16,7 +16,7 @@ ( -- * Configuration -- $config Config (..)- , XPosition (..), Align (..), Border(..)+ , XPosition (..), Align (..), Border (..), TextOutputFormat (..) , SignalChan (..) ) where @@ -36,6 +36,8 @@ , bgColor :: String -- ^ Backgroud color , fgColor :: String -- ^ Default font color , position :: XPosition -- ^ Top Bottom or Static+ , textOutput :: Bool -- ^ Write data to stdout instead of X+ , textOutputFormat :: TextOutputFormat -- ^ Which color format to use for stdout: Ansi or Pango , textOffset :: Int -- ^ Offset from top of window for text , textOffsets :: [Int] -- ^ List of offsets for additionalFonts , iconOffset :: Int -- ^ Offset from top of window for icons@@ -95,6 +97,8 @@ | BottomBM Int | FullBM Int deriving ( Read, Show, Eq )++data TextOutputFormat = Plain | Ansi | Pango | Swaybar deriving (Read, Show, Eq) newtype SignalChan = SignalChan { unSignalChan :: Maybe (STM.TMVar SignalType) }
+ src/Xmobar/Plugins/Command.hs view
@@ -0,0 +1,54 @@+------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Plugins.Command+-- Copyright: (c) 2018, 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Sun Dec 02, 2018 05:29+--+--+-- The basic Command plugin+--+------------------------------------------------------------------------------+++module Xmobar.Plugins.Command where++import Control.Exception (handle, SomeException(..))+import System.Process+import System.Exit+import System.IO (hClose, hGetLine)++import Xmobar.Run.Exec++data Command = Com Program Args Alias Rate+ | ComX Program Args String Alias Rate+ deriving (Show,Read,Eq)++type Args = [String]+type Program = String+type Alias = String+type Rate = Int++instance Exec Command where+ alias (ComX p _ _ a _) =+ if p /= "" then (if a == "" then p else a) else ""+ alias (Com p a al r) = alias (ComX p a "" al r)+ start (Com p as al r) cb =+ start (ComX p as ("Could not execute command " ++ p) al r) cb+ start (ComX prog args msg _ r) cb = if r > 0 then go else exec+ where go = doEveryTenthSeconds r exec+ exec = do+ (i,o,e,p) <- runInteractiveProcess prog args Nothing Nothing+ exit <- waitForProcess p+ let closeHandles = hClose o >> hClose i >> hClose e+ getL = handle (\(SomeException _) -> return "")+ (hGetLine o)+ case exit of+ ExitSuccess -> do str <- getL+ closeHandles+ cb str+ _ -> closeHandles >> cb msg
src/Xmobar/Plugins/Monitors/Cpu.hs view
@@ -4,7 +4,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Cpu--- Copyright : (c) 2011, 2017 Jose Antonio Ortega Ruiz+-- Copyright : (c) 2011, 2017, 2022 Jose Antonio Ortega Ruiz -- (c) 2007-2010 Andrea Rossato -- License : BSD-style (see LICENSE) --@@ -30,7 +30,7 @@ import Xmobar.Plugins.Monitors.Common import Data.IORef (newIORef) import System.Console.GetOpt-import Xmobar.App.Timer (doEveryTenthSeconds)+import Xmobar.Run.Timer (doEveryTenthSeconds) import Control.Monad (void) import Xmobar.Plugins.Monitors.Cpu.Common (CpuData(..))
src/Xmobar/Plugins/StdinReader.hs view
@@ -26,7 +26,7 @@ import System.IO import System.IO.Error (isEOFError) import Xmobar.Run.Exec-import Xmobar.X11.Actions (stripActions)+import Xmobar.Run.Actions (stripActions) import Control.Exception import Control.Monad (forever)
src/Xmobar/Plugins/XMonadLog.hs view
@@ -21,14 +21,17 @@ import Graphics.X11 import Graphics.X11.Xlib.Extras import Xmobar.Run.Exec+import Xmobar.Run.Actions (stripActions)+ #ifdef UTF8 #undef UTF8 import Codec.Binary.UTF8.String as UTF8 #define UTF8 #endif+ import Foreign.C (CChar)+import Data.List (intercalate) import Xmobar.X11.Events (nextEvent')-import Xmobar.X11.Actions (stripActions) data XMonadLog = XMonadLog | UnsafeXMonadLog@@ -54,11 +57,12 @@ UnsafeXPropertyLog a -> a NamedXPropertyLog a _ -> a UnsafeNamedXPropertyLog a _ -> a+ stripNL = intercalate " - " . lines sanitize = case x of UnsafeXMonadLog -> id UnsafeXPropertyLog _ -> id UnsafeNamedXPropertyLog _ _ -> id- _ -> stripActions+ _ -> stripActions . stripNL d <- openDisplay "" xlog <- internAtom d atom False
+ src/Xmobar/Run/Actions.hs view
@@ -0,0 +1,43 @@+-----------------------------------------------------------------------------+-- |+-- Module : Xmobar.Run.Actions+-- Copyright : (c) Alexander Polakov+-- License : BSD-style (see LICENSE)+--+-- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>+-- Stability : unstable+-- Portability : unportable+--+-----------------------------------------------------------------------------++module Xmobar.Run.Actions ( Button+ , Action(..)+ , runAction+ , runAction'+ , stripActions) where++import System.Process (system)+import Control.Monad (void)+import Text.Regex (Regex, subRegex, mkRegex, matchRegex)+import Data.Word (Word32)++type Button = Word32++data Action = Spawn [Button] String deriving (Eq, Read, Show)++runAction :: Action -> IO ()+runAction (Spawn _ s) = void $ system (s ++ "&")++-- | Run action with stdout redirected to stderr+runAction' :: Action -> IO ()+runAction' (Spawn _ s) = void $ system (s ++ " 1>&2 &")++stripActions :: String -> String+stripActions s = case matchRegex actionRegex s of+ Nothing -> s+ Just _ -> stripActions strippedOneLevel+ where+ strippedOneLevel = subRegex actionRegex s "[action=\\1\\2]\\3[/action]"++actionRegex :: Regex+actionRegex = mkRegex "<action=`?([^>`]*)`?( +button=[12345]+)?>(.+)</action>"
− src/Xmobar/Run/Command.hs
@@ -1,54 +0,0 @@---------------------------------------------------------------------------------- |--- Module: Xmobar.Plugins.Command--- Copyright: (c) 2018 Jose Antonio Ortega Ruiz--- License: BSD3-style (see LICENSE)------ Maintainer: jao@gnu.org--- Stability: unstable--- Portability: portable--- Created: Sun Dec 02, 2018 05:29--------- The basic Command plugin-------------------------------------------------------------------------------------module Xmobar.Run.Command where--import Control.Exception (handle, SomeException(..))-import System.Process-import System.Exit-import System.IO (hClose, hGetLine)--import Xmobar.Run.Exec--data Command = Com Program Args Alias Rate- | ComX Program Args String Alias Rate- deriving (Show,Read,Eq)--type Args = [String]-type Program = String-type Alias = String-type Rate = Int--instance Exec Command where- alias (ComX p _ _ a _) =- if p /= "" then (if a == "" then p else a) else ""- alias (Com p a al r) = alias (ComX p a "" al r)- start (Com p as al r) cb =- start (ComX p as ("Could not execute command " ++ p) al r) cb- start (ComX prog args msg _ r) cb = if r > 0 then go else exec- where go = doEveryTenthSeconds r exec- exec = do- (i,o,e,p) <- runInteractiveProcess prog args Nothing Nothing- exit <- waitForProcess p- let closeHandles = hClose o >> hClose i >> hClose e- getL = handle (\(SomeException _) -> return "")- (hGetLine o)- case exit of- ExitSuccess -> do str <- getL- closeHandles- cb str- _ -> closeHandles >> cb msg
src/Xmobar/Run/Exec.hs view
@@ -22,7 +22,7 @@ import Prelude import Data.Char -import Xmobar.App.Timer (doEveryTenthSeconds, tenthSeconds)+import Xmobar.Run.Timer (doEveryTenthSeconds, tenthSeconds) import Xmobar.System.Signal class Show e => Exec e where
+ src/Xmobar/Run/Loop.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE CPP #-}++------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Run.Loop+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: unportable+-- Created: Fri Jan 28, 2022 03:20+--+--+-- Running a thread for each defined Command in a loop+--+------------------------------------------------------------------------------++module Xmobar.Run.Loop (LoopFunction, loop) where++import Control.Concurrent (forkIO)+import Control.Exception (bracket_, bracket, handle, SomeException(..))+import Control.Concurrent.STM+import Control.Concurrent.Async (Async, async, cancel)+import Control.Monad (guard, void, unless)+import Data.Maybe (isJust)+import Data.Foldable (for_)++import Xmobar.System.Signal+import Xmobar.Config.Types+import Xmobar.Run.Runnable (Runnable)+import Xmobar.Run.Exec (start, trigger, alias)+import Xmobar.Run.Template+import Xmobar.Run.Timer (withTimer)++#ifdef DBUS+import Xmobar.System.DBus+#endif++newRefreshLock :: IO (TMVar ())+newRefreshLock = newTMVarIO ()++refreshLock :: TMVar () -> IO a -> IO a+refreshLock var = bracket_ lock unlock+ where+ lock = atomically $ takeTMVar var+ unlock = atomically $ putTMVar var ()++refreshLockT :: TMVar () -> STM a -> STM a+refreshLockT var action = do+ takeTMVar var+ r <- action+ putTMVar var ()+ return r++type LoopFunction = TMVar SignalType -> TVar [String] -> IO ()++loop :: Config -> LoopFunction -> IO ()+loop conf looper = withDeferSignals $ do+ cls <- mapM (parseTemplate (commands conf) (sepChar conf))+ (splitTemplate (alignSep conf) (template conf))+ let confSig = unSignalChan (signal conf)+ sig <- maybe newEmptyTMVarIO pure confSig+ unless (isJust confSig) $ setupSignalHandler sig+ refLock <- newRefreshLock+ withTimer (refreshLock refLock) $+ bracket (mapM (mapM $ startCommand sig) cls)+ cleanupThreads+ $ \vars -> do+ tv <- initLoop sig refLock vars+ looper sig tv++cleanupThreads :: [[([Async ()], a)]] -> IO ()+cleanupThreads vars =+ for_ (concat vars) $ \(asyncs, _) ->+ for_ asyncs cancel++-- | Initialises context for an event loop, returning a TVar that+-- will hold the current list of values computed by commands.+initLoop :: TMVar SignalType -> TMVar () -> [[([Async ()], TVar String)]]+ -> IO (TVar [String])+initLoop sig lock vs = do+ tv <- newTVarIO ([] :: [String])+ _ <- forkIO (handle (handler "checker") (checker tv [] vs sig lock))+#ifdef DBUS+ runIPC sig+#endif+ return tv+ where+ handler thing (SomeException e) =+ void $ putStrLn ("Thread " ++ thing ++ " failed: " ++ show e)++-- | Runs a command as an independent thread and returns its Async handles+-- and the TVar the command will be writing to.+startCommand :: TMVar SignalType+ -> (Runnable,String,String)+ -> IO ([Async ()], TVar String)+startCommand sig (com,s,ss)+ | alias com == "" = do var <- newTVarIO is+ atomically $ writeTVar var (s ++ ss)+ return ([], var)+ | otherwise = do var <- newTVarIO is+ let cb str = atomically $ writeTVar var (s ++ str ++ ss)+ a1 <- async $ start com cb+ a2 <- async $ trigger com $ maybe (return ())+ (atomically . putTMVar sig)+ return ([a1, a2], var)+ where is = s ++ "Updating..." ++ ss++-- | Send signal to eventLoop every time a var is updated+checker :: TVar [String]+ -> [String]+ -> [[([Async ()], TVar String)]]+ -> TMVar SignalType+ -> TMVar ()+ -> IO ()+checker tvar ov vs sig pauser = do+ nval <- atomically $ refreshLockT pauser $ do+ nv <- mapM concatV vs+ guard (nv /= ov)+ writeTVar tvar nv+ return nv+ atomically $ putTMVar sig Wakeup+ checker tvar nval vs sig pauser+ where+ concatV = fmap concat . mapM (readTVar . snd)
+ src/Xmobar/Run/Parsers.hs view
@@ -0,0 +1,234 @@+{-# 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 BoxBorder BoxOffset CInt String BoxMargins deriving (Eq, Show)+data TextRenderInfo =+ TextRenderInfo { tColorsString :: String+ , tBgTopOffset :: Int32+ , tBgBottomOffset :: Int32+ , tBoxes :: [Box]+ } deriving Show+type FontIndex = Int++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) f 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)+ s <- manyTill+ (allParsers (TextRenderInfo (fst colorParts) (fromMaybe (-1) $ readMaybe ot) (fromMaybe (-1) $ readMaybe ob) bs) f 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 (fromMaybe alg $ readMaybe [a]) (fromMaybe off $ readMaybe o)) lw fc mgs+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 '#')
src/Xmobar/Run/Template.hs view
@@ -20,8 +20,9 @@ import qualified Data.Map as Map import Text.ParserCombinators.Parsec +import Xmobar.Plugins.Command+ import Xmobar.Run.Exec-import Xmobar.Run.Command import Xmobar.Run.Runnable defaultAlign :: String
+ src/Xmobar/Run/Timer.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE LambdaCase #-}+------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Run.Timer+-- Copyright: (c) 2019, 2020, 2022 Tomáš Janoušek+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: Tomáš Janoušek <tomi@nomi.cz>+-- Stability: unstable+--+-- Timer coalescing for recurring actions.+--+------------------------------------------------------------------------------++module Xmobar.Run.Timer+ ( doEveryTenthSeconds+ , tenthSeconds+ , withTimer+ ) where++import Control.Concurrent (threadDelay)+import Control.Concurrent.Async (withAsync)+import Control.Concurrent.STM+import Control.Exception+import Control.Monad (forever, forM, guard)+import Data.Foldable (foldrM, for_)+import Data.Int (Int64)+import Data.Map (Map)+import qualified Data.Map as M+import Data.Maybe (isJust, fromJust)+import Data.Time.Clock.POSIX (getPOSIXTime)+import Data.Unique+import System.IO.Unsafe (unsafePerformIO)++type Periods = Map Unique Period++data Tick = Tick (TMVar ()) | UnCoalesce++data Period = Period { rate :: Int64, next :: Int64, tick :: TMVar Tick }++data UnCoalesceException = UnCoalesceException deriving Show+instance Exception UnCoalesceException++{-# NOINLINE periodsVar #-}+periodsVar :: TVar (Maybe Periods)+periodsVar = unsafePerformIO $ newTVarIO Nothing++now :: IO Int64+now = do+ posix <- getPOSIXTime+ return $ floor (10 * posix)++newPeriod :: Int64 -> IO (Unique, Period)+newPeriod r = do+ u <- newUnique+ t <- now+ v <- newEmptyTMVarIO+ let t' = t - t `mod` r+ return (u, Period { rate = r, next = t', tick = v })++-- | Perform a given action every N tenths of a second.+--+-- The timer is aligned (coalesced) with other timers to minimize the number+-- of wakeups and unnecessary redraws. If the action takes too long (one+-- second or when the next timer is due), coalescing is disabled for it and it+-- falls back to periodic sleep.+doEveryTenthSeconds :: Int -> IO () -> IO ()+doEveryTenthSeconds r action =+ doEveryTenthSecondsCoalesced r action `catch` \UnCoalesceException ->+ doEveryTenthSecondsSleeping r action++-- | Perform a given action every N tenths of a second,+-- coalesce with other timers using a given Timer instance.+doEveryTenthSecondsCoalesced :: Int -> IO () -> IO ()+doEveryTenthSecondsCoalesced r action = do+ (u, p) <- newPeriod (fromIntegral r)+ bracket_ (push u p) (pop u) $ forever $ bracket (wait p) done $ const action+ where+ push u p = atomically $ modifyTVar' periodsVar $ \case+ Just periods -> Just $ M.insert u p periods+ Nothing -> throw UnCoalesceException+ pop u = atomically $ modifyTVar' periodsVar $ \case+ Just periods -> Just $ M.delete u periods+ Nothing -> Nothing++ wait p = atomically (takeTMVar $ tick p) >>= \case+ Tick doneVar -> return doneVar+ UnCoalesce -> throwIO UnCoalesceException+ done doneVar = atomically $ putTMVar doneVar ()++-- | Perform a given action every N tenths of a second,+-- making no attempt to synchronize with other timers.+doEveryTenthSecondsSleeping :: Int -> IO () -> IO ()+doEveryTenthSecondsSleeping r action = go+ where go = action >> tenthSeconds r >> go++-- | Sleep for a given amount of tenths of a second.+--+-- (Work around the Int max bound: since threadDelay takes an Int, it+-- is not possible to set a thread delay grater than about 45 minutes.+-- With a little recursion we solve the problem.)+tenthSeconds :: Int -> IO ()+tenthSeconds s | s >= x = do threadDelay (x * 100000)+ tenthSeconds (s - x)+ | otherwise = threadDelay (s * 100000)+ where x = (maxBound :: Int) `div` 100000++-- | Start the timer coordination thread and perform a given IO action (this+-- is meant to surround the entire xmobar execution), terminating the timer+-- thread afterwards.+--+-- Additionally, if the timer thread fails, individual+-- 'doEveryTenthSecondsCoalesced' invocations that are waiting to be+-- coordinated by it are notified to fall back to periodic sleeping.+--+-- The timer thread _will_ fail immediately when running in a non-threaded+-- RTS.+withTimer :: (IO () -> IO ()) -> IO a -> IO a+withTimer pauseRefresh action =+ withAsync (timerThread `finally` cleanup) $ const action+ where+ timerThread = do+ atomically $ writeTVar periodsVar $ Just M.empty+ timerLoop pauseRefresh++ cleanup = atomically $ readTVar periodsVar >>= \case+ Just periods -> do+ for_ periods unCoalesceTimer'+ writeTVar periodsVar Nothing+ Nothing -> return ()++timerLoop :: (IO () -> IO ()) -> IO ()+timerLoop pauseRefresh = forever $ do+ tNow <- now+ (toFire, tMaybeNext) <- atomically $ do+ periods <- fromJust <$> readTVar periodsVar+ let toFire = timersToFire tNow periods+ let periods' = advanceTimers tNow periods+ let tMaybeNext = nextFireTime periods'+ writeTVar periodsVar $ Just periods'+ return (toFire, tMaybeNext)+ pauseRefresh $ do+ -- To avoid multiple refreshes, pause refreshing for up to 1 second,+ -- fire timers and wait for them to finish (update their text).+ -- Those that need more time (e.g. weather monitors) will be dropped+ -- from timer coalescing and will fall back to periodic sleep.+ timeoutVar <- registerDelay $ case tMaybeNext of+ Just tNext -> fromIntegral ((tNext - tNow) `max` 10) * 100000+ Nothing -> 1000000+ fired <- fireTimers toFire+ timeouted <- waitForTimers timeoutVar fired+ unCoalesceTimers timeouted+ delayUntilNextFire++advanceTimers :: Int64 -> Periods -> Periods+advanceTimers t = M.map advance+ where+ advance p | next p <= t = p { next = t - t `mod` rate p + rate p }+ | otherwise = p++timersToFire :: Int64 -> Periods -> [(Unique, Period)]+timersToFire t periods = [ (u, p) | (u, p) <- M.toList periods, next p <= t ]++nextFireTime :: Periods -> Maybe Int64+nextFireTime periods+ | M.null periods = Nothing+ | otherwise = Just $ minimum [ next p | p <- M.elems periods ]++fireTimers :: [(Unique, Period)] -> IO [(Unique, TMVar ())]+fireTimers toFire = atomically $ forM toFire $ \(u, p) -> do+ doneVar <- newEmptyTMVar+ putTMVar (tick p) (Tick doneVar)+ return (u, doneVar)++waitForTimers :: TVar Bool -> [(Unique, TMVar ())] -> IO [Unique]+waitForTimers timeoutVar fired = atomically $ do+ timeoutOver <- readTVar timeoutVar+ dones <- forM fired $ \(u, doneVar) -> do+ done <- isJust <$> tryReadTMVar doneVar+ return (u, done)+ guard $ timeoutOver || all snd dones+ return [u | (u, False) <- dones]++-- | Handle slow timers (drop and signal them to stop coalescing).+unCoalesceTimers :: [Unique] -> IO ()+unCoalesceTimers timers = atomically $ do+ periods <- fromJust <$> readTVar periodsVar+ periods' <- foldrM unCoalesceTimer periods timers+ writeTVar periodsVar $ Just periods'++unCoalesceTimer :: Unique -> Periods -> STM Periods+unCoalesceTimer u periods = do+ unCoalesceTimer' (periods M.! u)+ return $ u `M.delete` periods++unCoalesceTimer' :: Period -> STM ()+unCoalesceTimer' p = do+ _ <- tryTakeTMVar (tick p)+ putTMVar (tick p) UnCoalesce++delayUntilNextFire :: IO ()+delayUntilNextFire = do+ Just periods <- readTVarIO periodsVar+ let tMaybeNext = nextFireTime periods+ tNow <- now+ delayVar <- case tMaybeNext of+ Just tNext -> do+ -- Work around the Int max bound: threadDelay takes an Int, we can+ -- only sleep for so long, which is okay, we'll just check timers+ -- sooner and sleep again.+ let maxDelay = (maxBound :: Int) `div` 100000+ delay = (tNext - tNow) `min` fromIntegral maxDelay+ delayUsec = fromIntegral delay * 100000+ registerDelay delayUsec+ Nothing -> newTVarIO False+ atomically $ do+ delayOver <- readTVar delayVar+ periods' <- fromJust <$> readTVar periodsVar+ let tMaybeNext' = nextFireTime periods'+ -- Return also if a new period is added (it may fire sooner).+ guard $ delayOver || tMaybeNext /= tMaybeNext'
src/Xmobar/Run/Types.hs view
@@ -2,7 +2,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Run.Types--- Copyright: (c) 2018 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -19,6 +19,7 @@ module Xmobar.Run.Types(runnableTypes) where import {-# SOURCE #-} Xmobar.Run.Runnable()+import Xmobar.Plugins.Command import Xmobar.Plugins.Monitors import Xmobar.Plugins.Date import Xmobar.Plugins.PipeReader@@ -44,8 +45,6 @@ #ifdef KRAKEN import Xmobar.Plugins.Kraken #endif--import Xmobar.Run.Command -- | An alias for tuple types that is more convenient for long lists. type a :*: b = (a, b)
src/Xmobar/System/Utils.hs view
@@ -3,7 +3,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Utils--- Copyright: (c) 2010, 2018, 2020 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2010, 2018, 2020, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: Jose A Ortega Ruiz <jao@gnu.org>@@ -21,10 +21,19 @@ ( expandHome , changeLoop , safeIndex+ , forkThread ) where import Control.Monad import Control.Concurrent.STM+import Control.Exception (handle, SomeException(..))++#ifdef THREADED_RUNTIME+import Control.Concurrent (forkOS)+#else+import Control.Concurrent (forkIO)+#endif+ import qualified Data.List.NonEmpty as NE import Data.Maybe (fromMaybe) @@ -34,6 +43,18 @@ expandHome :: FilePath -> IO FilePath expandHome ('~':'/':path) = fmap (</> path) (getEnv "HOME") expandHome p = return p++forkThread :: String -> IO () -> IO ()+forkThread name action = do+#ifdef THREADED_RUNTIME+ _ <- forkOS (handle (onError name) action)+#else+ _ <- forkIO (handle (onError name) action)+#endif+ return ()+ where+ onError thing (SomeException e) =+ void $ putStrLn ("Thread " ++ thing ++ " failed: " ++ show e) changeLoop :: Eq a => STM a -> (a -> IO ()) -> IO () changeLoop s f = atomically s >>= go
+ src/Xmobar/Text/Ansi.hs view
@@ -0,0 +1,49 @@+------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Text.Ansi+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Fri Feb 4, 2022 01:10+--+--+-- Codification with ANSI (color) escape codes+--+------------------------------------------------------------------------------++module Xmobar.Text.Ansi (withAnsiColor) where++import Data.List (intercalate)+import Data.Char (toLower)++asInt :: String -> String+asInt x = case (reads $ "0x" ++ x) :: [(Integer, String)] of+ [(v, "") ] -> show v+ _ -> ""++namedColor :: String -> String+namedColor c =+ case map toLower c of+ "black" -> "0"; "red" -> "1"; "green" -> "2"; "yellow" -> "3"; "blue" -> "4";+ "magenta" -> "5"; "cyan" -> "6"; "white" -> "7";+ "brightblack" -> "8"; "brightred" -> "9"; "brightgreen" -> "10";+ "brightyellow" -> "11"; "brightblue" -> "12";+ "brightmagenta" -> "13"; "brightcyan" -> "14"; "brightwhite" -> "15";+ _ -> ""++ansiCode :: String -> String+ansiCode ('#':r:g:[b]) = ansiCode ['#', '0', r, '0', g, '0', b]+ansiCode ('#':r0:r1:g0:g1:b0:[b1]) =+ "2;" ++ intercalate ";" (map asInt [[r0,r1], [g0,g1], [b0,b1]])+ansiCode ('#':n) = ansiCode n+ansiCode c = "5;" ++ if null i then namedColor c else i where i = asInt c++withAnsiColor :: (String, String) -> String -> String+withAnsiColor (fg, bg) s = wrap "38;" fg (wrap "48;" bg s)+ where wrap cd cl w =+ if null cl+ then w+ else "\x1b[" ++ cd ++ ansiCode cl ++ "m" ++ w ++ "\x1b[0m"
+ src/Xmobar/Text/Loop.hs view
@@ -0,0 +1,48 @@+------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Text.Loop+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: unportable+-- Created: Fri Jan 28, 2022 01:21+--+--+-- Text-only event loop+--+------------------------------------------------------------------------------++module Xmobar.Text.Loop (textLoop) where++import Prelude hiding (lookup)+import System.IO (hSetBuffering, stdin, stdout, BufferMode(LineBuffering))++import Control.Concurrent.STM++import Xmobar.System.Signal+import Xmobar.Config.Types (Config)+import Xmobar.Run.Loop (loop)+import Xmobar.Text.Output (initLoop, format)++-- | Starts the main event loop and threads+textLoop :: Config -> IO ()+textLoop conf = do+ hSetBuffering stdin LineBuffering+ hSetBuffering stdout LineBuffering+ initLoop conf+ loop conf (eventLoop conf)++-- | Continuously wait for a signal from a thread or a interrupt handler+eventLoop :: Config -> TMVar SignalType -> TVar [String] -> IO ()+eventLoop cfg signal tv = do+ typ <- atomically $ takeTMVar signal+ case typ of+ Wakeup -> updateString cfg tv >>= putStrLn >> eventLoop cfg signal tv+ _ -> eventLoop cfg signal tv++updateString :: Config -> TVar [String] -> IO String+updateString conf v = do+ s <- readTVarIO v+ format conf (concat s)
+ src/Xmobar/Text/Output.hs view
@@ -0,0 +1,55 @@+-- |+-- Module: Xmobar.Text.Output+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Fri Feb 4, 2022 01:10+--+--+-- Format strings emitted by Commands into output strings+--+------------------------------------------------------------------------------++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.Text.Ansi (withAnsiColor)+import Xmobar.Text.Pango (withPangoMarkup)+import Xmobar.Text.Swaybar (formatSwaybar, prepare)++initLoop :: Config -> IO ()+initLoop conf = case textOutputFormat conf of+ Swaybar -> prepare+ _ -> return ()++formatWithColor :: Config -> Segment -> String+formatWithColor conf (Text s, info, idx, _) =+ case textOutputFormat conf of+ Ansi -> withAnsiColor (fg, bg) s+ Pango -> withPangoMarkup fg bg fn s+ _ -> s+ where (fg, bg) = colorComponents conf (tColorsString info)+ fonts = additionalFonts conf+ fn = if idx < 1 || idx > length fonts+ then font conf+ else fonts !! (idx - 1)+formatWithColor conf (Hspace n, i, x, y) =+ formatWithColor conf (Text $ replicate (fromIntegral n) ' ', i, x, y)+formatWithColor _ _ = ""++format :: Config -> String -> IO String+format conf s = do+ segments <- parseString conf s+ case textOutputFormat conf of+ Swaybar -> return $ formatSwaybar conf segments+ _ -> return (concatMap (formatWithColor conf) segments)
+ src/Xmobar/Text/Pango.hs view
@@ -0,0 +1,48 @@+------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Text.Pango+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Author: Pavel Kalugin+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Fri Feb 4, 2022 01:15+--+--+-- Codification with Pango markup+--+------------------------------------------------------------------------------++module Xmobar.Text.Pango (withPangoColor, withPangoFont, withPangoMarkup) where++import Text.Printf (printf)+import Data.List (isPrefixOf)++replaceAll :: (Eq a) => a -> [a] -> [a] -> [a]+replaceAll c s = concatMap (\x -> if x == c then s else [x])++xmlEscape :: String -> String+xmlEscape s = replaceAll '"' """ $+ replaceAll '\'' "'" $+ replaceAll '<' "<" $+ replaceAll '>' ">" $+ replaceAll '&' "&" s++withPangoColor :: (String, String) -> String -> String+withPangoColor (fg, bg) s =+ printf fmt (xmlEscape fg) (xmlEscape bg) (xmlEscape s)+ where fmt = "<span foreground=\"%s\" background=\"%s\">%s</span>"++fixXft :: String -> String+fixXft font = if "xft:" `isPrefixOf` font then drop 4 font else font++withPangoFont :: String -> String -> String+withPangoFont font txt = printf fmt (fixXft font) (xmlEscape txt)+ where fmt = "<span font=\"%s\">%s</span>"++withPangoMarkup :: String -> String -> String -> String -> String+withPangoMarkup fg bg font txt =+ printf fmt (fixXft font) (xmlEscape fg) (xmlEscape bg) (xmlEscape txt)+ where fmt = "<span font=\"%s\" foreground=\"%s\" background=\"%s\">%s</span>"
+ src/Xmobar/Text/Swaybar.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE DeriveGeneric #-}++------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Text.Swaybar+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Fri Feb 4, 2022 03:58+--+--+-- Segment codification using swaybar-protocol JSON strings+--+------------------------------------------------------------------------------++module Xmobar.Text.Swaybar (prepare, formatSwaybar) where++import Data.Aeson++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.Text.SwaybarClicks (startHandler)+import Xmobar.Text.Pango (withPangoFont)++data Preamble =+ Preamble {version :: !Int, click_events :: Bool} deriving (Eq,Show,Generic)++asString :: ToJSON a => a -> String+asString = toString . encode++preamble :: String+preamble = (asString $ Preamble { version = 1, click_events = True }) ++ "\x0A["++data Block =+ Block { full_text :: !String+ , name :: !String+ , color :: Maybe String+ , background :: Maybe String+ , separator :: !Bool+ , separator_block_width :: !Int+ , border :: Maybe String+ , border_top :: Maybe Int+ , border_bottom :: Maybe Int+ , border_left :: Maybe Int+ , border_right :: Maybe Int+ , markup :: Maybe String+ } deriving (Eq,Show,Generic)+++defaultBlock :: Block+defaultBlock = Block { full_text = ""+ , name = ""+ , color = Nothing+ , background = Nothing+ , separator = False+ , separator_block_width = 0+ , border = Nothing+ , border_top = Nothing+ , border_bottom = Nothing+ , border_left = Nothing+ , border_right = Nothing+ , markup = Nothing+ }++instance ToJSON Block where+ toJSON = genericToJSON defaultOptions+ { omitNothingFields = True }++instance ToJSON Preamble++withBox :: Box -> Block -> Block+withBox (Box b _ n c _) block =+ (case b of+ BBFull -> bl { border_right = w, border_left = w+ , border_bottom = w, border_top = w }+ BBTop -> bl { border_top = w }+ BBBottom -> bl { border_bottom = w }+ BBVBoth -> bl { border_bottom = w, border_top = w }+ BBLeft -> bl { border_left = w }+ BBRight -> bl { border_right = w }+ BBHBoth -> bl { border_right = w, border_left = w }+ ) { border = bc }+ where w = Just (fromIntegral n)+ bc = if null c then Nothing else Just c+ j0 = Just 0+ bl = block { border_right = j0, border_left = j0+ , border_bottom = j0, border_top = j0 }++withFont :: Config -> FontIndex -> Block -> Block+withFont conf idx block =+ if idx < 1 || idx > length fonts then block+ else block { markup = Just $ fonts !! (idx - 1) }+ where fonts = additionalFonts conf++withPango :: Block -> Block+withPango block = case markup block of+ Nothing -> block+ Just fnt -> block { full_text = txt fnt, markup = Just "pango"}+ where txt fn = withPangoFont fn (full_text block)++formatSwaybar' :: Config -> Segment -> Block+formatSwaybar' conf (Text txt, info, idx, as) =+ foldr withBox (withFont conf idx block) (tBoxes info)+ where (fg, bg) = colorComponents conf (tColorsString info)+ block = defaultBlock { full_text = txt+ , color = Just fg+ , background = Just bg+ , name = show as+ }+formatSwaybar' conf (Hspace n, info, i, a) =+ formatSwaybar' conf (Text (replicate (fromIntegral n) ' '), info, i, a)+formatSwaybar' _ _ = defaultBlock++collectBlock :: Block -> [Block] -> [Block]+collectBlock b [] = [b]+collectBlock b (h:bs) =+ if b {full_text = ""} == h {full_text = ""} then+ h {full_text = full_text b ++ full_text h} : bs+ else b:h:bs++collectSegment :: Config -> Segment -> [Block] -> [Block]+collectSegment config segment blocks =+ if null $ full_text b then blocks else collectBlock b blocks+ where b = formatSwaybar' config segment++formatSwaybar :: Config -> [Segment] -> String+formatSwaybar conf segs = asString (map withPango blocks) ++ ","+ where blocks = foldr (collectSegment conf) [] segs++prepare :: IO ()+prepare = startHandler >> putStrLn preamble
+ src/Xmobar/Text/SwaybarClicks.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE DeriveGeneric #-}++------------------------------------------------------------------------------+-- |+-- Module: Xmobar.Text.SwaybarClicks+-- Copyright: (c) 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Fri Feb 4, 2022 03:58+--+--+-- Handling of "click" events sent by swaybar via stdin+--+------------------------------------------------------------------------------+++module Xmobar.Text.SwaybarClicks (startHandler) where++import Control.Monad (when)+++import Data.Aeson++-- import qualified Data.ByteString.Lazy as BL++import GHC.Generics++import Xmobar.System.Utils (forkThread)+import Xmobar.Run.Actions (Action (..), runAction')++import Data.ByteString.Lazy.UTF8 (fromString)++data Click =+ Click { name :: String , button :: Int } deriving (Eq,Show,Generic)++instance FromJSON Click++runClickAction :: Int -> Action -> IO ()+runClickAction b a@(Spawn bs _) =+ when (fromIntegral b `elem` bs) (runAction' a)++handleClick :: Maybe Click -> IO ()+handleClick Nothing = return ()+handleClick (Just click) = do+ let mas = read (name click) :: Maybe [Action]+ b = button click+ maybe (return ()) (mapM_ (runClickAction b)) mas++toClick :: String -> Maybe Click+toClick (',':s) = toClick s+toClick s = decode (fromString s)++readClicks :: IO ()+readClicks = getLine >>= handleClick . toClick >> readClicks++startHandler :: IO ()+startHandler = forkThread "Swaybar event handler" readClicks
− src/Xmobar/X11/Actions.hs
@@ -1,34 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Xmobar.Actions--- Copyright : (c) Alexander Polakov--- License : BSD-style (see LICENSE)------ Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>--- Stability : unstable--- Portability : unportable-----------------------------------------------------------------------------------module Xmobar.X11.Actions (Action(..), runAction, stripActions) where--import System.Process (system)-import Control.Monad (void)-import Text.Regex (Regex, subRegex, mkRegex, matchRegex)-import Graphics.X11.Types (Button)--data Action = Spawn [Button] String- deriving (Eq, Show)--runAction :: Action -> IO ()-runAction (Spawn _ s) = void $ system (s ++ "&")--stripActions :: String -> String-stripActions s = case matchRegex actionRegex s of- Nothing -> s- Just _ -> stripActions strippedOneLevel- where- strippedOneLevel = subRegex actionRegex s "[action=\\1\\2]\\3[/action]"--actionRegex :: Regex-actionRegex = mkRegex "<action=`?([^>`]*)`?( +button=[12345]+)?>(.+)</action>"
src/Xmobar/X11/Bitmap.hs view
@@ -2,7 +2,7 @@ ----------------------------------------------------------------------------- -- | -- Module : X11.Bitmap--- Copyright : (C) 2013, 2015, 2017, 2018 Alexander Polakov+-- Copyright : (C) 2013, 2015, 2017, 2018, 2022 Alexander Polakov -- License : BSD3 -- -- Maintainer : jao@gnu.org@@ -23,9 +23,9 @@ import System.Directory (doesFileExist) import System.FilePath ((</>)) import System.Mem.Weak ( addFinalizer )+import Xmobar.Run.Actions (Action)+import Xmobar.Run.Parsers (TextRenderInfo(..), Widget(..)) import Xmobar.X11.ColorCache-import Xmobar.X11.Parsers (TextRenderInfo(..), Widget(..))-import Xmobar.X11.Actions (Action) #ifdef XPM import Xmobar.X11.XPMFile(readXPMFile)
src/Xmobar/X11/Draw.hs view
@@ -4,7 +4,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.X11.Draw--- Copyright: (c) 2018, 2020 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2020, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -28,17 +28,16 @@ import Data.List ((\\)) import qualified Data.List.NonEmpty as NE -import Graphics.X11.Xlib hiding (textExtents, textWidth)+import Graphics.X11.Xlib hiding (textExtents, textWidth, Segment) import Graphics.X11.Xlib.Extras import Xmobar.Config.Types+import Xmobar.Run.Parsers hiding (parseString) import qualified Xmobar.X11.Bitmap as B-import Xmobar.X11.Actions (Action(..)) import Xmobar.X11.Types import Xmobar.X11.Text import Xmobar.X11.ColorCache import Xmobar.X11.Window (drawBorder)-import Xmobar.X11.Parsers hiding (parseString) import Xmobar.System.Utils (safeIndex) #ifdef XFT@@ -50,7 +49,7 @@ fi = fromIntegral -- | Draws in and updates the window-drawInWin :: Rectangle -> [[(Widget, TextRenderInfo, Int, Maybe [Action])]] -> X ()+drawInWin :: Rectangle -> [[Segment]] -> X () drawInWin wr@(Rectangle _ _ wid ht) ~[left,center,right] = do r <- ask let (c,d) = (config &&& display) r@@ -71,6 +70,7 @@ #endif withColors d [bgColor c, borderColor c] $ \[bgcolor, bdcolor] -> do gc <- liftIO $ createGC d w+ liftIO $ setGraphicsExposures d gc False #if XFT when (alpha c == 255) $ do #else@@ -89,8 +89,8 @@ -- free up everything (we do not want to leak memory!) liftIO $ freeGC d gc liftIO $ freePixmap d p- -- resync- liftIO $ sync d False+ -- resync (discard events, we don't read/process events from this display conn)+ liftIO $ sync d True verticalOffset :: (Integral b, Integral a, MonadIO m) => a -> Widget -> XFont -> Int -> Config -> m b@@ -105,8 +105,19 @@ | otherwise = return $ fi (ht `div` 2) - 1 verticalOffset _ (Hspace _) _ voffs _ = return $ fi voffs -printString :: Display -> Drawable -> XFont -> GC -> String -> String- -> Position -> Position -> Position -> Position -> String -> Int -> IO ()+printString :: Display+ -> Drawable+ -> XFont+ -> GC+ -> String+ -> String+ -> Position+ -> Position+ -> Position+ -> Position+ -> String+ -> Int+ -> IO () printString d p (Core fs) gc fc bc x y _ _ s a = do setFont d gc $ fontFromFontStruct fs withColors d [fc, bc] $ \[fc', bc'] -> do@@ -133,8 +144,14 @@ #endif -- | An easy way to print the stuff we need to print-printStrings :: Drawable -> GC -> NE.NonEmpty XFont -> NE.NonEmpty Int -> Position- -> Align -> [((Position, Position), Box)] -> [(Widget, TextRenderInfo, Int, Position)] -> X ()+printStrings :: Drawable+ -> GC+ -> NE.NonEmpty XFont+ -> NE.NonEmpty Int+ -> Position+ -> Align+ -> [((Position, Position), Box)]+ -> [(Widget, TextRenderInfo, Int, Position)] -> X () printStrings _ _ _ _ _ _ _ [] = return () printStrings dr gc fontlist voffs offs a boxes sl@((s,c,i,l):xs) = do r <- ask@@ -149,9 +166,7 @@ C -> (remWidth + offs) `div` 2 R -> remWidth L -> offs- (fc,bc) = case break (==',') (tColorsString c) of- (f,',':b) -> (f, b )- (f, _) -> (f, bgColor conf)+ (fc,bc) = colorComponents conf (tColorsString c) valign <- verticalOffset ht s fontst voff conf let (ht',ay) = case (tBgTopOffset c, tBgBottomOffset c) of (-1,_) -> (0, -1)@@ -165,14 +180,20 @@ (Hspace _) -> liftIO $ return () let triBoxes = tBoxes c dropBoxes = filter (\(_,b) -> b `notElem` triBoxes) boxes- boxes' = map (\((x1,_),b) -> ((x1, offset + l), b)) (filter (\(_,b) -> b `elem` triBoxes) boxes)+ boxes' = map (\((x1,_),b) -> ((x1, offset + l), b))+ (filter (\(_,b) -> b `elem` triBoxes) boxes) ++ map ((offset, offset + l),) (triBoxes \\ map snd boxes) if Prelude.null xs then liftIO $ drawBoxes d dr gc (fromIntegral ht) (dropBoxes ++ boxes') else liftIO $ drawBoxes d dr gc (fromIntegral ht) dropBoxes printStrings dr gc fontlist voffs (offs + l) a boxes' xs -drawBoxes :: Display -> Drawable -> GC -> Position -> [((Position, Position), Box)] -> IO ()+drawBoxes :: Display+ -> Drawable+ -> GC+ -> Position+ -> [((Position, Position), Box)]+ -> IO () drawBoxes _ _ _ _ [] = return () drawBoxes d dr gc ht (b:bs) = do let (xx, Box bb offset lineWidth fc mgs) = b@@ -195,9 +216,18 @@ _ -> drawBoxBorder d dr gc bb offset ht xx lw mgs drawBoxes d dr gc ht bs -drawBoxBorder :: Display -> Drawable -> GC -> BoxBorder -> BoxOffset -> Position- -> (Position, Position) -> Position -> BoxMargins -> IO ()-drawBoxBorder d dr gc pos (BoxOffset alg offset) ht (x1,x2) lw (BoxMargins mt mr mb ml) = do+drawBoxBorder :: Display+ -> Drawable+ -> GC+ -> BoxBorder+ -> BoxOffset+ -> Position+ -> (Position, Position)+ -> Position+ -> BoxMargins+ -> IO ()+drawBoxBorder+ d dr gc pos (BoxOffset alg offset) ht (x1,x2) lw (BoxMargins mt mr mb ml) = do let (p1,p2) = case alg of L -> (0, -offset) C -> (offset, -offset)
+ src/Xmobar/X11/Loop.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE CPP #-}++------------------------------------------------------------------------------+-- |+-- Module: Xmobar.App.X11EventLoop+-- Copyright: (c) 2018, 2020, 2022 Jose Antonio Ortega Ruiz+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: jao@gnu.org+-- Stability: unstable+-- Portability: portable+-- Created: Sat Nov 24, 2018 19:40+--+--+-- Event loop+--+------------------------------------------------------------------------------++module Xmobar.X11.Loop (x11Loop) where++import Prelude hiding (lookup)+import Graphics.X11.Xlib hiding (textExtents, textWidth, Segment)+import Graphics.X11.Xlib.Extras+import Graphics.X11.Xinerama+import Graphics.X11.Xrandr++import Control.Arrow ((&&&))+import Control.Monad.Reader+import Control.Concurrent+import Control.Concurrent.STM++import Data.Bits+import Data.Map hiding (foldr, map, filter)+import qualified Data.Map as Map+import Data.List.NonEmpty (NonEmpty(..))++import Data.Maybe (fromJust, isJust)+import qualified Data.List.NonEmpty as NE++import Xmobar.System.Signal+import Xmobar.Config.Types ( persistent+ , font+ , additionalFonts+ , textOffset+ , textOffsets+ , position+ , iconRoot+ , Config+ , Align(..)+ , XPosition(..))++import Xmobar.Run.Actions+import Xmobar.Run.Parsers+import Xmobar.X11.Window+import Xmobar.X11.Text+import Xmobar.X11.Draw+import Xmobar.X11.Bitmap as Bitmap+import Xmobar.X11.Types+import Xmobar.System.Utils (safeIndex, forkThread)++import Xmobar.Run.Loop (loop)++#ifndef THREADED_RUNTIME+import Xmobar.X11.Events(nextEvent')+#endif++#ifdef XFT+import Graphics.X11.Xft+#endif++runX :: XConf -> X () -> IO ()+runX xc f = runReaderT f xc++-- | Starts the main event loop and threads+x11Loop :: Config -> IO ()+x11Loop conf = do+ initThreads+ d <- openDisplay ""+ fs <- initFont d (font conf)+ fl <- mapM (initFont d) (additionalFonts conf)+ let ic = Map.empty+ to = textOffset conf+ ts = textOffsets conf ++ replicate (length fl) (-1)+#ifdef XFT+ xftInitFtLibrary+#endif+ (r,w) <- createWin d fs conf+ loop conf (startLoop (XConf d r w (fs :| fl) (to :| ts) ic conf))++startLoop :: XConf -> TMVar SignalType -> TVar [String] -> IO ()+startLoop xcfg@(XConf _ _ w _ _ _ _) sig tv = do+ forkThread "X event handler" (x11EventLoop w sig)+ signalLoop xcfg [] sig tv++-- | Translates X11 events received by w to signals handled by signalLoop+x11EventLoop :: Window -> TMVar SignalType -> IO ()+x11EventLoop w signal =+ allocaXEvent $ \e -> do+ dpy <- openDisplay ""+ xrrSelectInput dpy (defaultRootWindow dpy) rrScreenChangeNotifyMask+ selectInput dpy w (exposureMask .|. structureNotifyMask .|. buttonPressMask)++ forever $ do+#ifdef THREADED_RUNTIME+ nextEvent dpy e+#else+ nextEvent' dpy e+#endif+ ev <- getEvent e+ case ev of+ ConfigureEvent {} -> atomically $ putTMVar signal Reposition+ ExposeEvent {} -> atomically $ putTMVar signal Wakeup+ RRScreenChangeNotifyEvent {} -> atomically $ putTMVar signal Reposition+ ButtonEvent {} -> atomically $+ putTMVar signal (Action (ev_button ev) (fi $ ev_x ev))+ _ -> return ()++-- | Continuously wait for a signal from a thread or an interrupt handler+signalLoop :: XConf+ -> [([Action], Position, Position)]+ -> TMVar SignalType+ -> TVar [String]+ -> IO ()+signalLoop xc@(XConf d r w fs vos is cfg) as signal tv = do+ typ <- atomically $ takeTMVar signal+ case typ of+ Wakeup -> do+ str <- updateString cfg tv+ xc' <- updateCache d w is (iconRoot cfg) str >>=+ \c -> return xc { iconS = c }+ as' <- updateActions xc r str+ runX xc' $ drawInWin r str+ signalLoop xc' as' signal tv++ Reposition ->+ reposWindow cfg++ ChangeScreen -> do+ ncfg <- updateConfigPosition cfg+ reposWindow ncfg++ Hide t -> hide (t*100*1000)+ Reveal t -> reveal (t*100*1000)+ Toggle t -> toggle t++ TogglePersistent -> signalLoop+ xc { config = cfg { persistent = not $ persistent cfg } } as signal tv++ Action but x -> action but x++ where+ isPersistent = not $ persistent cfg+ loopOn = signalLoop xc as signal tv+ hide t+ | t == 0 =+ when isPersistent (hideWindow d w) >> loopOn+ | otherwise = do+ void $ forkIO+ $ threadDelay t >> atomically (putTMVar signal $ Hide 0)+ loopOn++ reveal t+ | t == 0 = do+ when isPersistent (showWindow r cfg d w)+ loopOn+ | otherwise = do+ void $ forkIO+ $ threadDelay t >> atomically (putTMVar signal $ Reveal 0)+ loopOn++ toggle t = do+ ismapped <- isMapped d w+ atomically (putTMVar signal $ if ismapped then Hide t else Reveal t)+ loopOn++ reposWindow rcfg = do+ r' <- repositionWin d w (NE.head fs) rcfg+ signalLoop (XConf d r' w fs vos is rcfg) as signal tv++ updateConfigPosition ocfg =+ case position ocfg of+ OnScreen n o -> do+ srs <- getScreenInfo d+ return (if n == length srs+ then+ (ocfg {position = OnScreen 1 o})+ else+ (ocfg {position = OnScreen (n+1) o}))+ o -> return (ocfg {position = OnScreen 1 o})++ action button x = do+ mapM_ runAction $+ filter (\(Spawn b _) -> button `elem` b) $+ concatMap (\(a,_,_) -> a) $+ filter (\(_, from, to) -> x >= from && x <= to) as+ loopOn++updateString :: Config -> TVar [String] -> IO [[Segment]]+updateString conf v = do+ s <- readTVarIO v+ let l:c:r:_ = s ++ repeat ""+ liftIO $ mapM (parseString conf) [l, c, r]++updateActions :: XConf -> Rectangle -> [[Segment]]+ -> IO [([Action], Position, Position)]+updateActions conf (Rectangle _ _ wid _) ~[left,center,right] = do+ let (d,fs) = (display &&& fontListS) conf+ strLn :: [Segment] -> IO [(Maybe [Action], Position, Position)]+ strLn = liftIO . mapM getCoords+ iconW i = maybe 0 Bitmap.width (lookup i $ iconS conf)+ getCoords (Text s,_,i,a) =+ textWidth d (safeIndex fs i) s >>= \tw -> return (a, 0, fi tw)+ getCoords (Icon s,_,_,a) = return (a, 0, fi $ iconW s)+ getCoords (Hspace w,_,_,a) = return (a, 0, fi w)+ partCoord off xs = map (\(a, x, x') -> (fromJust a, x, x')) $+ filter (\(a, _,_) -> isJust a) $+ scanl (\(_,_,x') (a,_,w') -> (a, x', x' + w'))+ (Nothing, 0, off)+ xs+ totSLen = foldr (\(_,_,len) -> (+) len) 0+ remWidth xs = fi wid - totSLen xs+ offs = 1+ offset a xs = case a of+ C -> (remWidth xs + offs) `div` 2+ R -> remWidth xs+ L -> offs+ fmap concat $ mapM (\(a,xs) ->+ (\xs' -> partCoord (offset a xs') xs') <$> strLn xs) $+ zip [L,C,R] [left,center,right]
− src/Xmobar/X11/Parsers.hs
@@ -1,227 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}---------------------------------------------------------------------------------- |--- Module : Xmobar.Parsers--- Copyright : (c) Andrea Rossato--- License : BSD-style (see LICENSE)------ Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>--- Stability : unstable--- Portability : unportable------ Parsing for template substrings-----------------------------------------------------------------------------------module Xmobar.X11.Parsers (parseString, Box(..), BoxBorder(..), BoxOffset(..),- BoxMargins(..), TextRenderInfo(..), Widget(..)) where--import Xmobar.Config.Types-import Xmobar.X11.Actions--import Control.Monad (guard, mzero)-import Data.Maybe (fromMaybe)-import Data.Int (Int32)-import Text.ParserCombinators.Parsec-import Text.Read (readMaybe)-import Graphics.X11.Types (Button)-import Foreign.C.Types (CInt)--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 BoxBorder BoxOffset CInt String BoxMargins deriving (Eq, Show)-data TextRenderInfo =- TextRenderInfo { tColorsString :: String- , tBgTopOffset :: Int32- , tBgBottomOffset :: Int32- , tBoxes :: [Box]- } deriving Show-type FontIndex = Int---- | Runs the string parser-parseString :: Config -> String- -> IO [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 []--allParsers :: TextRenderInfo- -> FontIndex- -> Maybe [Action]- -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 [[(Widget, TextRenderInfo, FontIndex, Maybe [Action])]]-stringParser c f a = manyTill (allParsers c f a) eof---- | Parses a maximal string without markup.-textParser :: TextRenderInfo -> FontIndex -> Maybe [Action]- -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-iconParser c f a = do- string "<icon="- i <- manyTill (noneOf ">") (try (string "/>"))- return [(Icon i, c, f, a)]--hspaceParser :: TextRenderInfo -> FontIndex -> Maybe [Action]- -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-colorParser (TextRenderInfo _ _ _ bs) f 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)- s <- manyTill- (allParsers (TextRenderInfo (fst colorParts) (fromMaybe (-1) $ readMaybe ot) (fromMaybe (-1) $ readMaybe ob) bs) f a)- (try $ string "</fc>")- return (concat s)---- | Parses a string wrapped in a box specification.-boxParser :: TextRenderInfo -> FontIndex -> Maybe [Action]- -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 (fromMaybe alg $ readMaybe [a]) (fromMaybe off $ readMaybe o)) lw fc mgs-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 [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]-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 '#')
src/Xmobar/X11/Window.hs view
@@ -84,7 +84,7 @@ TopW a i -> Rectangle (ax a i) ry (nw i) h TopSize a i ch -> Rectangle (ax a i) ry (nw i) (mh ch) Bottom -> Rectangle rx ny rw h- BottomH ch -> Rectangle rx ny rw (mh ch)+ BottomH ch -> Rectangle rx (ny' ch) rw (mh ch) BottomW a i -> Rectangle (ax a i) ny (nw i) h BottomP l r -> Rectangle (rx + fi l) ny (rw - fi l - fi r) h BottomSize a i ch -> Rectangle (ax a i) (ny' ch) (nw i) (mh ch)
xmobar.cabal view
@@ -1,6 +1,6 @@ name: xmobar-version: 0.41-homepage: http://xmobar.org+version: 0.42+homepage: https://github.com/jaor/xmobar synopsis: A Minimalistic Text Based Status Bar description: Xmobar is a minimalistic text based status bar. .@@ -110,31 +110,38 @@ Xmobar.Config.Types, Xmobar.Config.Parse, Xmobar.Run.Types,+ Xmobar.Run.Timer, Xmobar.Run.Template, Xmobar.Run.Exec,- Xmobar.Run.Command, Xmobar.Run.Runnable- Xmobar.App.EventLoop,+ Xmobar.Run.Actions,+ Xmobar.Run.Parsers,+ Xmobar.Run.Loop, Xmobar.App.Config, Xmobar.App.Main, Xmobar.App.Opts, Xmobar.App.Compile,- Xmobar.App.Timer, Xmobar.System.Utils, Xmobar.System.StatFS, Xmobar.System.Environment, Xmobar.System.Localize, Xmobar.System.Signal, Xmobar.System.Kbd,- Xmobar.X11.Actions,+ Xmobar.Text.Ansi,+ Xmobar.Text.Loop,+ Xmobar.Text.Pango,+ Xmobar.Text.Swaybar,+ Xmobar.Text.SwaybarClicks,+ Xmobar.Text.Output, Xmobar.X11.Events,- Xmobar.X11.Parsers,+ Xmobar.X11.Loop, Xmobar.X11.Types, Xmobar.X11.Text, Xmobar.X11.Bitmap, Xmobar.X11.ColorCache, Xmobar.X11.Window, Xmobar.X11.Draw,+ Xmobar.Plugins.Command, Xmobar.Plugins.BufferedPipeReader, Xmobar.Plugins.CommandReader, Xmobar.Plugins.Date,@@ -179,24 +186,25 @@ ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind build-depends:- base >= 4.11.0 && < 4.16,- containers,- regex-compat,- process,- old-locale,- bytestring >= 0.10.8.2,- directory,- unix,- time,- filepath,- transformers,- X11 >= 1.6.1,- mtl >= 2.1 && < 2.3,- parsec == 3.1.*,- parsec-numbers >= 0.1.0,- stm >= 2.3 && < 2.6,- extensible-exceptions == 0.1.*,- async+ X11 >= 1.6.1,+ aeson >= 1.4.7.1,+ async,+ base >= 4.11.0 && < 4.16,+ bytestring >= 0.10.8.2,+ containers,+ directory,+ extensible-exceptions == 0.1.*,+ filepath,+ mtl >= 2.1 && < 2.3,+ old-locale,+ parsec == 3.1.*,+ parsec-numbers >= 0.1.0,+ process,+ regex-compat,+ stm >= 2.3 && < 2.6,+ time,+ transformers,+ unix if impl(ghc < 8.0.2) -- Disable building with GHC before 8.0.2.@@ -381,7 +389,7 @@ Xmobar.Plugins.Monitors.CpuSpec Xmobar.Plugins.Monitors.Common.Run Xmobar.Run.Exec- Xmobar.App.Timer+ Xmobar.Run.Timer Xmobar.System.Signal if flag(with_alsa) || flag(all_extensions)