Initial commit

This commit is contained in:
Kristofers Solo 2022-04-27 11:41:37 +03:00
commit f1d310a07d
700 changed files with 101758 additions and 0 deletions

24
.zshenv Normal file
View File

@ -0,0 +1,24 @@
typeset -U PATH path
# Other XDG paths
export XDG_DATA_HOME=${XDG_DATA_HOME:="$HOME/.local/share"}
export XDG_CACHE_HOME=${XDG_CACHE_HOME:="$HOME/.cache"}
export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:="$HOME/.config"}
# Disable files
export LESSHISTFILE=-
# Fixing paths
export XINITRC="$XDG_CONFIG_HOME"/X11/xinitrc
export ZDOTDIR=$HOME/.config/zsh
export HISTFILE="$XDG_DATA_HOME"/zsh/history
# Default Apps
export EDITOR="nvim"
export VISUAL="nvim"
export READER="zathura"
export TERMINAL="alacritty"
export BROWSER="vivaldi"
export VIDEO="mpv"
export IMAGE="nsxiv"
export WM="awesome"

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# Kristofers Solo config files
## Dependencies
* [omnipause](https://github.com/mel00010/OmniPause)
* [pulsemixer](https://github.com/GeorgeFilipkin/pulsemixer)
* [Image preview for lf](https://github.com/cirala/lfimg)

881
alacritty/alacritty.yml Normal file
View File

@ -0,0 +1,881 @@
# Configuration for Alacritty, the GPU enhanced terminal emulator.
# Import additional configuration files
#
# Imports are loaded in order, skipping all missing files, with the importing
# file being loaded last. If a field is already present in a previous import, it
# will be replaced.
#
# All imports must either be absolute paths starting with `/`, or paths relative
# to the user's home directory starting with `~/`.
#import:
# - /path/to/alacritty.yml
# Any items in the `env` entry below will be added as
# environment variables. Some entries may override variables
# set by alacritty itself.
env:
# TERM variable
#
# This value is used to set the `$TERM` environment variable for
# each instance of Alacritty. If it is not present, alacritty will
# check the local terminfo database and use `alacritty` if it is
# available, otherwise `xterm-256color` is used.
TERM: alacritty
# Background opacity
#
# Window opacity as a floating point number from `0.0` to `1.0`.
# The value `0.0` is completely transparent and `1.0` is opaque.
# background_opacity: 0.9
window:
# Window dimensions (changes require restart)
#
# Number of lines/columns (not pixels) in the terminal. The number of columns
# must be at least `2`, while using a value of `0` for columns and lines will
# fall back to the window manager's recommended size.
dimensions:
columns: 0
lines: 0
opacity: 0.9
# Window position (changes require restart)
#
# Specified in number of pixels.
# If the position is not set, the window manager will handle the placement.
#position:
# x: 0
# y: 0
# Window padding (changes require restart)
#
# Blank space added around the window in pixels. This padding is scaled
# by DPI and the specified value is always added at both opposing sides.
padding:
x: 0
y: 0
# Spread additional padding evenly around the terminal content.
dynamic_padding: true
# Window decorations
#
# Values for `decorations`:
# - full: Borders and title bar
# - none: Neither borders nor title bar
#
# Values for `decorations` (macOS only):
# - transparent: Title bar, transparent background and title bar buttons
# - buttonless: Title bar, transparent background and no title bar buttons
decorations: none
# Startup Mode (changes require restart)
#
# Values for `startup_mode`:
# - Windowed
# - Maximized
# - Fullscreen
#
# Values for `startup_mode` (macOS only):
# - SimpleFullscreen
startup_mode: Windowed
# Window title
title: Alacritty
# Allow terminal applications to change Alacritty's window title.
dynamic_title: true
# Window class (Linux/BSD only):
# class:
# Application instance name
# instance: Alacritty
# General application class
# general: Alacritty
# GTK theme variant (Linux/BSD only)
#
# Override the variant of the GTK theme. Commonly supported values are `dark`
# and `light`. Set this to `None` to use the default theme variant.
gtk_theme_variant: dark
scrolling:
# Maximum number of lines in the scrollback buffer.
# Specifying '0' will disable scrolling.
history: 10000
# Scrolling distance multiplier.
multiplier: 3
# Font configuration
font:
# Normal (roman) font face
normal:
# Font family
#
# Default:
# - (macOS) Menlo
# - (Linux/BSD) monospace
# - (Windows) Consolas
family: JetBrainsMono NF
# The `style` can be specified to pick a specific face.
style: Regular
# Bold font face
bold:
# Font family
#
# If the bold family is not specified, it will fall back to the
# value specified for the normal font.
family: JetBrainsMono NF
# The `style` can be specified to pick a specific face.
style: Bold
# Italic font face
italic:
# Font family
#
# If the italic family is not specified, it will fall back to the
# value specified for the normal font.
family: JetBrainsMono NF
# The `style` can be specified to pick a specific face.
style: Italic
# Bold italic font face
bold_italic:
# Font family
#
# If the bold italic family is not specified, it will fall back to the
# value specified for the normal font.
family: JetBrainsMono NF
# The `style` can be specified to pick a specific face.
style: Bold Italic
# Point size
size: 9.0
# Offset is the extra space around each character. `offset.y` can be thought
# of as modifying the line spacing, and `offset.x` as modifying the letter
# spacing.
offset:
x: 0
y: -1
# Glyph offset determines the locations of the glyphs within their cells with
# the default being at the bottom. Increasing `x` moves the glyph to the
# right, increasing `y` moves the glyph upward.
glyph_offset:
x: 0
y: 0
# Thin stroke font rendering (macOS only)
#
# Thin strokes are suitable for retina displays, but for non-retina screens
# it is recommended to set `use_thin_strokes` to `false`.
use_thin_strokes: false
# If `true`, bold text is drawn using the bright color variants.
draw_bold_text_with_bright_colors: true
# Colors (Tomorrow Night)
colors:
# Default colors
primary:
background: '#1d1f21'
foreground: '#c5c8c6'
# Bright and dim foreground colors
#
# The dimmed foreground color is calculated automatically if it is not
# present. If the bright foreground color is not set, or
# `draw_bold_text_with_bright_colors` is `false`, the normal foreground
# color will be used.
dim_foreground: '#828482'
bright_foreground: '#eaeaea'
# Cursor colors
#
# Colors which should be used to draw the terminal cursor.
#
# Allowed values are CellForeground/CellBackground, which reference the
# affected cell, or hexadecimal colors like #ff00ff.
cursor:
text: CellBackground
cursor: CellForeground
# Vi mode cursor colors
#
# Colors for the cursor when the vi mode is active.
#
# Allowed values are CellForeground/CellBackground, which reference the
# affected cell, or hexadecimal colors like #ff00ff.
vi_mode_cursor:
text: CellBackground
cursor: CellForeground
# Search colors
#
# Colors used for the search bar and match highlighting.
search:
# Allowed values are CellForeground/CellBackground, whichq reference the
# affected cell, or hexadecimal colors like #ff00ff.
# matches:
# foreground: '#000000'
# background: '#ffffff'
# focused_match:
# foreground: '#ffffff'
# background: '#000000'
bar:
background: '#282828'
foreground: '#EBEBE9'
# Keyboard regex hints
hints:
# First character in the hint label
#
# Allowed values are CellForeground/CellBackground, which reference the
# affected cell, or hexadecimal colors like #ff00ff.
start:
foreground: '#1d1f21'
background: '#e9ff5e'
# All characters after the first one in the hint label
#
# Allowed values are CellForeground/CellBackground, which reference the
# affected cell, or hexadecimal colors like #ff00ff.
end:
foreground: '#e9ff5e'
background: '#1d1f21'
# Line indicator
#
# Color used for the indicator displaying the position in history during
# search and vi mode.
#
# By default, these will use the opposing primary color.
#line_indicator:
# foreground: None
# background: None
# Selection colors
#
# Colors which should be used to draw the selection area.
#
# Allowed values are CellForeground/CellBackground, which reference the
# affected cell, or hexadecimal colors like #ff00ff.
selection:
text: CellBackground
background: CellForeground
# Normal colors
normal:
black: '#313539'
red: '#b02626'
green: '#40a62f'
yellow: '#f1e635'
blue: '#314ad0'
magenta: '#b30ad0'
cyan: '#32d0fc'
white: '#acadb1'
# Bright colors
bright:
black: '#717174'
red: '#b02626'
green: '#40a62f'
yellow: '#f1e635'
blue: '#314ad0'
magenta: '#b30ad0'
cyan: '#32d0fc'
white: '#acadb1'
# Dim colors
#
# If the dim colors are not set, they will be calculated automatically based
# on the `normal` colors.
dim:
black: '#676f78'
red: '#b55454'
green: '#78a670'
yellow: '#faf380'
blue: '#707fd0'
magenta: '#c583d0'
cyan: '#8adaf1'
white: '#e0e3e7'
# Indexed Colors
#
# The indexed colors include all colors from 16 to 256.
# When these are not set, they're filled with sensible defaults.
#
# Example:
# `- { index: 16, color: '#ff00ff' }`
#
#indexed_colors: []
# Transparent cell backgrounds
#
# Whether or not `window.opacity` applies to all cell backgrounds or only to
# the default background. When set to `true` all cells will be transparent
# regardless of their background color.
transparent_background_colors: false
# Bell
#
# The bell is rung every time the BEL control character is received.
#bell:
# Visual Bell Animation
#
# Animation effect for flashing the screen when the visual bell is rung.
#
# Values for `animation`:
# - Ease
# - EaseOut
# - EaseOutSine
# - EaseOutQuad
# - EaseOutCubic
# - EaseOutQuart
# - EaseOutQuint
# - EaseOutExpo
# - EaseOutCirc
# - Linear
#animation: EaseOutExpo
# Duration of the visual bell flash in milliseconds. A `duration` of `0` will
# disable the visual bell animation.
#duration: 0
# Visual bell animation color.
#color: '#ffffff'
# Bell Command
#
# This program is executed whenever the bell is rung.
#
# When set to `command: None`, no command will be executed.
#
# Example:
# command:
# program: notify-send
# args: ["Hello, World!"]
#
#command: None
selection:
# This string contains all characters that are used as separators for
# "semantic words" in Alacritty.
semantic_escape_chars: ",│`|:\"' ()[]{}<>\t"
# When set to `true`, selected text will be copied to the primary clipboard.
save_to_clipboard: true
cursor:
# Cursor style
style:
# Cursor shape
#
# Values for `shape`:
# - ▇ Block
# - _ Underline
# - | Beam
shape: Beam
# Cursor blinking state
#
# Values for `blinking`:
# - Never: Prevent the cursor from ever blinking
# - Off: Disable blinking by default
# - On: Enable blinking by default
# - Always: Force the cursor to always blink
#blinking: Off
# Vi mode cursor style
#
# If the vi mode cursor style is `None` or not specified, it will fall back to
# the style of the active value of the normal cursor.
#
# See `cursor.style` for available options.
vi_mode_style: Block
# Cursor blinking interval in milliseconds.
#blink_interval: 750
# If this is `true`, the cursor will be rendered as a hollow box when the
# window is not focused.
unfocused_hollow: false
# Thickness of the cursor relative to the cell width as floating point number
# from `0.0` to `1.0`.
#thickness: 0.15
# Live config reload (changes require restart)
#live_config_reload: true
# Shell
#
# You can set `shell.program` to the path of your favorite shell, e.g.
# `/bin/fish`. Entries in `shell.args` are passed unmodified as arguments to the
# shell.
#
# Default:
# - (macOS) /bin/bash --login
# - (Linux/BSD) user login shell
# - (Windows) powershell
shell:
program: /bin/zsh
# args:
# - --login
# Startup directory
#
# Directory the shell is started in. If this is unset, or `None`, the working
# directory of the parent process will be used.
#working_directory: None
# Send ESC (\x1b) before characters when alt is pressed.
#alt_send_esc: true
# Offer IPC using `alacritty msg` (unix only)
#ipc_socket: true
#mouse:
# Click settings
#
# The `double_click` and `triple_click` settings control the time
# alacritty should wait for accepting multiple clicks as one double
# or triple click.
#double_click: { threshold: 300 }
#triple_click: { threshold: 300 }
# If this is `true`, the cursor is temporarily hidden when typing.
#hide_when_typing: false
# Regex hints
#
# Terminal hints can be used to find text in the visible part of the terminal
# and pipe it to other applications.
#hints:
# Keys used for the hint labels.
#alphabet: "jfkdls;ahgurieowpq"
# List with all available hints
#
# Each hint must have a `regex` and either an `action` or a `command` field.
# The fields `mouse`, `binding` and `post_processing` are optional.
#
# The fields `command`, `binding.key`, `binding.mods`, `binding.mode` and
# `mouse.mods` accept the same values as they do in the `key_bindings` section.
#
# The `mouse.enabled` field controls if the hint should be underlined while
# the mouse with all `mouse.mods` keys held or the vi mode cursor is above it.
#
# If the `post_processing` field is set to `true`, heuristics will be used to
# shorten the match if there are characters likely not to be part of the hint
# (e.g. a trailing `.`). This is most useful for URIs.
#
# Values for `action`:
# - Copy
# Copy the hint's text to the clipboard.
# - Paste
# Paste the hint's text to the terminal or search.
# - Select
# Select the hint's text.
# - MoveViModeCursor
# Move the vi mode cursor to the beginning of the hint.
#enabled:
# - regex: "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)\
# [^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^⟨⟩`]+"
# command: xdg-open
# post_processing: true
# mouse:
# enabled: true
# mods: None
# binding:
# key: U
# mods: Control|Shift
# Mouse bindings
#
# Mouse bindings are specified as a list of objects, much like the key
# bindings further below.
#
# To trigger mouse bindings when an application running within Alacritty
# captures the mouse, the `Shift` modifier is automatically added as a
# requirement.
#
# Each mouse binding will specify a:
#
# - `mouse`:
#
# - Middle
# - Left
# - Right
# - Numeric identifier such as `5`
#
# - `action` (see key bindings for actions not exclusive to mouse mode)
#
# - Mouse exclusive actions:
#
# - ExpandSelection
# Expand the selection to the current mouse cursor location.
#
# And optionally:
#
# - `mods` (see key bindings)
mouse_bindings:
# - { mouse: Right, action: ExpandSelection }
- { mouse: Middle, mode: ~Vi, action: PasteSelection }
# Key bindings
#
# Key bindings are specified as a list of objects. For example, this is the
# default paste binding:
#
# `- { key: V, mods: Control|Shift, action: Paste }`
#
# Each key binding will specify a:
#
# - `key`: Identifier of the key pressed
#
# - A-Z
# - F1-F24
# - Key0-Key9
#
# A full list with available key codes can be found here:
# https://docs.rs/glutin/*/glutin/event/enum.VirtualKeyCode.html#variants
#
# Instead of using the name of the keys, the `key` field also supports using
# the scancode of the desired key. Scancodes have to be specified as a
# decimal number. This command will allow you to display the hex scancodes
# for certain keys:
#
# `showkey --scancodes`.
#
# Then exactly one of:
#
# - `chars`: Send a byte sequence to the running application
#
# The `chars` field writes the specified string to the terminal. This makes
# it possible to pass escape sequences. To find escape codes for bindings
# like `PageUp` (`"\x1b[5~"`), you can run the command `showkey -a` outside
# of tmux. Note that applications use terminfo to map escape sequences back
# to keys. It is therefore required to update the terminfo when changing an
# escape sequence.
#
# - `action`: Execute a predefined action
#
# - ToggleViMode
# - SearchForward
# Start searching toward the right of the search origin.
# - SearchBackward
# Start searching toward the left of the search origin.
# - Copy
# - Paste
# - IncreaseFontSize
# - DecreaseFontSize
# - ResetFontSize
# - ScrollPageUp
# - ScrollPageDown
# - ScrollHalfPageUp
# - ScrollHalfPageDown
# - ScrollLineUp
# - ScrollLineDown
# - ScrollToTop
# - ScrollToBottom
# - ClearHistory
# Remove the terminal's scrollback history.
# - Hide
# Hide the Alacritty window.
# - Minimize
# Minimize the Alacritty window.
# - Quit
# Quit Alacritty.
# - ToggleFullscreen
# - SpawnNewInstance
# Spawn a new instance of Alacritty.
# - CreateNewWindow
# Create a new Alacritty window from the current process.
# - ClearLogNotice
# Clear Alacritty's UI warning and error notice.
# - ClearSelection
# Remove the active selection.
# - ReceiveChar
# - None
#
# - Vi mode exclusive actions:
#
# - Open
# Perform the action of the first matching hint under the vi mode cursor
# with `mouse.enabled` set to `true`.
# - ToggleNormalSelection
# - ToggleLineSelection
# - ToggleBlockSelection
# - ToggleSemanticSelection
# Toggle semantic selection based on `selection.semantic_escape_chars`.
#
# - Vi mode exclusive cursor motion actions:
#
# - Up
# One line up.
# - Down
# One line down.
# - Left
# One character left.
# - Right
# One character right.
# - First
# First column, or beginning of the line when already at the first column.
# - Last
# Last column, or beginning of the line when already at the last column.
# - FirstOccupied
# First non-empty cell in this terminal row, or first non-empty cell of
# the line when already at the first cell of the row.
# - High
# Top of the screen.
# - Middle
# Center of the screen.
# - Low
# Bottom of the screen.
# - SemanticLeft
# Start of the previous semantically separated word.
# - SemanticRight
# Start of the next semantically separated word.
# - SemanticLeftEnd
# End of the previous semantically separated word.
# - SemanticRightEnd
# End of the next semantically separated word.
# - WordLeft
# Start of the previous whitespace separated word.
# - WordRight
# Start of the next whitespace separated word.
# - WordLeftEnd
# End of the previous whitespace separated word.
# - WordRightEnd
# End of the next whitespace separated word.
# - Bracket
# Character matching the bracket at the cursor's location.
# - SearchNext
# Beginning of the next match.
# - SearchPrevious
# Beginning of the previous match.
# - SearchStart
# Start of the match to the left of the vi mode cursor.
# - SearchEnd
# End of the match to the right of the vi mode cursor.
#
# - Search mode exclusive actions:
# - SearchFocusNext
# Move the focus to the next search match.
# - SearchFocusPrevious
# Move the focus to the previous search match.
# - SearchConfirm
# - SearchCancel
# - SearchClear
# Reset the search regex.
# - SearchDeleteWord
# Delete the last word in the search regex.
# - SearchHistoryPrevious
# Go to the previous regex in the search history.
# - SearchHistoryNext
# Go to the next regex in the search history.
#
# - macOS exclusive actions:
# - ToggleSimpleFullscreen
# Enter fullscreen without occupying another space.
#
# - Linux/BSD exclusive actions:
#
# - CopySelection
# Copy from the selection buffer.
# - PasteSelection
# Paste from the selection buffer.
#
# - `command`: Fork and execute a specified command plus arguments
#
# The `command` field must be a map containing a `program` string and an
# `args` array of command line parameter strings. For example:
# `{ program: "alacritty", args: ["-e", "vttest"] }`
#
# And optionally:
#
# - `mods`: Key modifiers to filter binding actions
#
# - Command
# - Control
# - Option
# - Super
# - Shift
# - Alt
#
# Multiple `mods` can be combined using `|` like this:
# `mods: Control|Shift`.
# Whitespace and capitalization are relevant and must match the example.
#
# - `mode`: Indicate a binding for only specific terminal reported modes
#
# This is mainly used to send applications the correct escape sequences
# when in different modes.
#
# - AppCursor
# - AppKeypad
# - Search
# - Alt
# - Vi
#
# A `~` operator can be used before a mode to apply the binding whenever
# the mode is *not* active, e.g. `~Alt`.
#
# Bindings are always filled by default, but will be replaced when a new
# binding with the same triggers is defined. To unset a default binding, it can
# be mapped to the `ReceiveChar` action. Alternatively, you can use `None` for
# a no-op if you do not wish to receive input characters for that binding.
#
# If the same trigger is assigned to multiple actions, all of them are executed
# in the order they were defined in.
key_bindings:
#- { key: Paste, action: Paste }
#- { key: Copy, action: Copy }
# - { key: L, mods: Control, action: clear }
#- { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" }
- { key: Up, mods: Shift, mode: ~Alt, action: ScrollPageUp }
- { key: Down, mods: Shift, mode: ~Alt, action: ScrollPageDown }
- { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop }
- { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom }
# - { key: Delete, actions: Del }
# - { key: Key9, mods: Control|Shift, action: CreateNewWindow, }
# Vi Mode
- { key: Space, mods: Shift|Control, mode: ~Search, action: ToggleViMode }
- { key: Space, mods: Shift|Control, mode: Vi|~Search, action: ScrollToBottom }
# - { key: Escape, mode: ~Search, action: ToggleViMode }
- { key: Escape, mode: Vi|~Search, action: ClearSelection }
- { key: I, mode: Vi|~Search, action: ToggleViMode }
- { key: I, mode: Vi|~Search, action: ScrollToBottom }
- { key: C, mods: Control, mode: Vi|~Search, action: ToggleViMode }
- { key: Y, mods: Control, mode: Vi|~Search, action: ScrollLineUp }
- { key: E, mods: Control, mode: Vi|~Search, action: ScrollLineDown }
- { key: G, mode: Vi|~Search, action: ScrollToTop }
- { key: G, mods: Shift, mode: Vi|~Search, action: ScrollToBottom }
- { key: B, mods: Control, mode: Vi|~Search, action: ScrollPageUp }
- { key: F, mods: Control, mode: Vi|~Search, action: ScrollPageDown }
- { key: U, mods: Control, mode: Vi|~Search, action: ScrollHalfPageUp }
- { key: D, mods: Control, mode: Vi|~Search, action: ScrollHalfPageDown }
- { key: Y, mode: Vi|~Search, action: Copy }
- { key: Y, mode: Vi|~Search, action: ClearSelection }
- { key: Copy, mode: Vi|~Search, action: ClearSelection }
- { key: V, mode: Vi|~Search, action: ToggleNormalSelection }
- { key: V, mods: Shift, mode: Vi|~Search, action: ToggleLineSelection }
- { key: V, mods: Control, mode: Vi|~Search, action: ToggleBlockSelection }
- { key: V, mods: Alt, mode: Vi|~Search, action: ToggleSemanticSelection }
- { key: Return, mode: Vi|~Search, action: Open }
- { key: K, mode: Vi|~Search, action: Up }
- { key: J, mode: Vi|~Search, action: Down }
- { key: H, mode: Vi|~Search, action: Left }
- { key: L, mode: Vi|~Search, action: Right }
- { key: Up, mode: Vi|~Search, action: Up }
- { key: Down, mode: Vi|~Search, action: Down }
- { key: Left, mode: Vi|~Search, action: Left }
- { key: Right, mode: Vi|~Search, action: Right }
- { key: Key0, mode: Vi|~Search, action: First }
- { key: Key4, mods: Shift, mode: Vi|~Search, action: Last }
- { key: Key6, mods: Shift, mode: Vi|~Search, action: FirstOccupied }
- { key: H, mods: Shift, mode: Vi|~Search, action: High }
- { key: M, mods: Shift, mode: Vi|~Search, action: Middle }
- { key: L, mods: Shift, mode: Vi|~Search, action: Low }
- { key: B, mode: Vi|~Search, action: SemanticLeft }
- { key: W, mode: Vi|~Search, action: SemanticRight }
- { key: E, mode: Vi|~Search, action: SemanticRightEnd }
- { key: B, mods: Shift, mode: Vi|~Search, action: WordLeft }
- { key: W, mods: Shift, mode: Vi|~Search, action: WordRight }
- { key: E, mods: Shift, mode: Vi|~Search, action: WordRightEnd }
- { key: Key5, mods: Shift, mode: Vi|~Search, action: Bracket }
- { key: Slash, mode: Vi|~Search, action: SearchForward }
- { key: Slash, mods: Shift, mode: Vi|~Search, action: SearchBackward }
- { key: N, mode: Vi|~Search, action: SearchNext }
- { key: N, mods: Shift, mode: Vi|~Search, action: SearchPrevious }
# Search Mode
#- { key: Return, mode: Search|Vi, action: SearchConfirm }
#- { key: Escape, mode: Search, action: SearchCancel }
#- { key: C, mods: Control, mode: Search, action: SearchCancel }
#- { key: U, mods: Control, mode: Search, action: SearchClear }
#- { key: W, mods: Control, mode: Search, action: SearchDeleteWord }
#- { key: P, mods: Control, mode: Search, action: SearchHistoryPrevious }
#- { key: N, mods: Control, mode: Search, action: SearchHistoryNext }
#- { key: Up, mode: Search, action: SearchHistoryPrevious }
#- { key: Down, mode: Search, action: SearchHistoryNext }
#- { key: Return, mode: Search|~Vi, action: SearchFocusNext }
#- { key: Return, mods: Shift, mode: Search|~Vi, action: SearchFocusPrevious }
# (Windows, Linux, and BSD only)
- { key: V, mods: Control|Shift, mode: ~Vi, action: Paste }
- { key: C, mods: Control|Shift, action: Copy }
- { key: F, mods: Control|Shift, mode: ~Search, action: SearchForward }
- { key: B, mods: Control|Shift, mode: ~Search, action: SearchBackward }
#- { key: C, mods: Control|Shift, mode: Vi|~Search, action: ClearSelection }
#- { key: Insert, mods: Shift, action: PasteSelection }
- { key: Key0, mods: Control, action: ResetFontSize }
- { key: Equals, mods: Control, action: IncreaseFontSize }
# - { key: Plus, mods: Control, action: IncreaseFontSize }
- { key: NumpadAdd, mods: Control, action: IncreaseFontSize }
- { key: Minus, mods: Control, action: DecreaseFontSize }
- { key: NumpadSubtract, mods: Control, action: DecreaseFontSize }
- { key: Q, mods: Control|Shift, action: Quit }
# (Windows only)
- { key: F11, action: ToggleFullscreen }
# (macOS only)
#- { key: K, mods: Command, mode: ~Vi|~Search, chars: "\x0c" }
#- { key: K, mods: Command, mode: ~Vi|~Search, action: ClearHistory }
#- { key: Key0, mods: Command, action: ResetFontSize }
#- { key: Equals, mods: Command, action: IncreaseFontSize }
#- { key: Plus, mods: Command, action: IncreaseFontSize }
#- { key: NumpadAdd, mods: Command, action: IncreaseFontSize }
#- { key: Minus, mods: Command, action: DecreaseFontSize }
#- { key: NumpadSubtract, mods: Command, action: DecreaseFontSize }
#- { key: V, mods: Command, action: Paste }
#- { key: C, mods: Command, action: Copy }
#- { key: C, mods: Command, mode: Vi|~Search, action: ClearSelection }
#- { key: H, mods: Command, action: Hide }
#- { key: H, mods: Command|Alt, action: HideOtherApplications }
#- { key: M, mods: Command, action: Minimize }
#- { key: Q, mods: Command, action: Quit }
#- { key: W, mods: Command, action: Quit }
#- { key: N, mods: Command, action: SpawnNewInstance }
#- { key: F, mods: Command|Control, action: ToggleFullscreen }
#- { key: F, mods: Command, mode: ~Search, action: SearchForward }
#- { key: B, mods: Command, mode: ~Search, action: SearchBackward }
#debug:
# Display the time it takes to redraw each frame.
#render_timer: false
# Keep the log file after quitting Alacritty.
#persistent_logging: false
# Log level
#
# Values for `log_level`:
# - Off
# - Error
# - Warn
# - Info
# - Debug
# - Trace
#log_level: Warn
# Print all received window events.
#print_events: false

View File

@ -0,0 +1 @@
@streetturtle

View File

@ -0,0 +1 @@
github: streetturtle

View File

@ -0,0 +1,30 @@
# This is a basic workflow to help you get started with Actions
name: luacheck
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches:
- '*'
paths:
- '**.lua'
pull_request:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- name: Run Luacheck
uses: nebularg/actions-luacheck@v1.1.0

View File

@ -0,0 +1,43 @@
name: update site
on:
push:
branches:
- 'master'
paths:
- '**/README.md'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Generate md
run: ./scripts/update_site.sh
- name: Push to gh-pages branch
run: |
git config --global user.name 'GitHub Action'
git config --global user.email 'action@github.com'
git add ./_widgets
git add ./assets/img/widgets
git stash
git fetch
echo "git checkout gh-pages"
git checkout gh-pages
rm -rf ./_widgets
rm -rf ./assets/img/widgets
ls -alF
echo "git stash pop"
git checkout stash -- ./_widgets
git checkout stash -- ./assets/img/widgets
git add ./_widgets
git add ./assets/img/widgets
git commit -m "update from master"
git push origin gh-pages

48
awesome/awesome-wm-widgets/.gitignore vendored Normal file
View File

@ -0,0 +1,48 @@
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# IDEA files
.idea
# vscode files
.history
/_site/
/.jekyll-cache/

View File

@ -0,0 +1,24 @@
self = false
globals = {
"screen",
"mouse",
"root",
"client"
}
read_globals = {
"awesome",
"button",
"dbus",
"drawable",
"drawin",
"key",
"keygrabber",
"mousegrabber",
"selection",
"tag",
"window",
"table.unpack",
"math.atan2",
}

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2017
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,63 @@
<p align="center">
<img src="https://github.com/streetturtle/awesome-wm-widgets/raw/master/awesome-o.png" alt="logo" style="max-width:100%;">
</p>
<p align="center">
<img src="https://img.shields.io/github/stars/streetturtle/awesome-wm-widgets.svg">
<img src="https://img.shields.io/github/forks/streetturtle/awesome-wm-widgets.svg">
<img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/streetturtle/awesome-wm-widgets">
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/streetturtle/awesome-wm-widgets/luacheck">
<a href="https://www.buymeacoffee.com/streetturtle"><img src="https://img.shields.io/badge/-buy%20me%20a%20coffee-3B4252?style=flat&logo=Buy-Me-A-Coffee"></a>
<a href="https://twitter.com/intent/tweet?text=Check%20out%20these%20awesome%20widgets%20for%20Awesome Window Manager%20&url=https://github.com/streetturtle/awesome-wm-widgets">
<img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social">
</a>
</p>
Set of widgets compatible with Awesome Window Manager v.4.3+.
## Screenshots
Spotify, CPU, RAM, brightness-arc, volume-arc and battery-arc widgets:
<p align="center">
<img src="https://github.com/streetturtle/awesome-wm-widgets/raw/master/Screenshot%20from%202019-03-01%2014-28-18.png">
</p>
Brightness, volume and battery widgets:
<p align="center">
<img src="https://github.com/streetturtle/awesome-wm-widgets/raw/master/widgets-icons.png">
</p>
![screenshot](./screenshot.png)
Some more screenshots in this reddit [post](https://www.reddit.com/r/unixporn/comments/8qijmx/awesomewm_dark_theme/)
# Installation
Clone the repo under **~/.config/awesome/**, then follow an Installation section of widget's readme file.
# Stargazers
[![Stargazers over time](https://starchart.cc/streetturtle/awesome-wm-widgets.svg)](https://starchart.cc/streetturtle/awesome-wm-widgets)
# Troubleshooting
In case of any doubts/questions/problems:
- create an [issue](https://github.com/streetturtle/awesome-wm-widgets/issues/new/choose)
- raise a question on [Discussions](https://github.com/streetturtle/awesome-wm-widgets/discussions)!
- ping me on AwesomeWM's discord, here's an [invite](https://discord.gg/XYvn8R5)
# Support
If you find anything useful here, you can:
- star a repo - this really motivates me to work on this project
- or <a class="social-link" href="https://www.buymeacoffee.com/streetturtle"><img style="display:inline" src="https://img.shields.io/badge/-buy%20me%20a%20coffee-3B4252?style=flat&logo=Buy-Me-A-Coffee"></a>
- or even become a [sponsor](https://github.com/sponsors/streetturtle)
# Contributors
<a href="https://github.com/streetturtle/awesome-wm-widgets/graphs/contributors">
<img src="https://contrib.rocks/image?repo=streetturtle/awesome-wm-widgets" />
</a>

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -0,0 +1,27 @@
# APT widget
Widget which shows a list of APT packages to be updated:
![screenshot](./screenshots/screenshot.gif)
Features:
- scrollable list !!! (thanks to this [post](https://www.reddit.com/r/awesomewm/comments/isx89x/scrolling_a_layout_fixed_flexed_layout_widget/) of reddit)
- update single package
- update multiple packages
## Installation
Clone the repo under ~/.config/awesome/ folder, then in rc.lua add the following:
```lua
local apt_widget = require("awesome-wm-widgets.apt-widget.apt-widget")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
apt_widget(),
...
```

View File

@ -0,0 +1,349 @@
-------------------------------------------------
-- APT Widget for Awesome Window Manager
-- Lists containers and allows to manage them
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/apt-widget
-- @author Pavel Makhov
-- @copyright 2021 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local wibox = require("wibox")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
local HOME_DIR = os.getenv("HOME")
local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/apt-widget'
local ICONS_DIR = WIDGET_DIR .. '/icons/'
local LIST_PACKAGES = [[sh -c "apt list --upgradable 2>/dev/null"]]
--- Utility function to show warning messages
local function show_warning(message)
naughty.notify{
preset = naughty.config.presets.critical,
title = 'Docker Widget',
text = message}
end
local wibox_popup = wibox {
ontop = true,
visible = false,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 4)
end,
border_width = 1,
border_color = beautiful.bg_focus,
max_widget_size = 500,
height = 500,
width = 300,
}
local apt_widget = wibox.widget {
{
{
id = 'icon',
widget = wibox.widget.imagebox
},
margins = 4,
layout = wibox.container.margin
},
layout = wibox.layout.fixed.horizontal,
set_icon = function(self, new_icon)
self:get_children_by_id("icon")[1].image = new_icon
end
}
--- Parses the line and creates the package table out of it
--- yaru-theme-sound/focal-updates,focal-updates 20.04.10.1 all [upgradable from: 20.04.8]
local parse_package = function(line)
local name,_,nv,type,ov = line:match('(.*)%/(.*)%s(.*)%s(.*)%s%[upgradable from: (.*)]')
if name == nil then return nil end
local package = {
name = name,
new_version = nv,
type = type,
old_version = ov
}
return package
end
local function worker(user_args)
local args = user_args or {}
local icon = args.icon or ICONS_DIR .. 'white-black.svg'
apt_widget:set_icon(icon)
local pointer = 0
local min_widgets = 5
local carousel = false
local function rebuild_widget(containers, errors, _, _)
local to_update = {}
if errors ~= '' then
show_warning(errors)
return
end
local rows = wibox.layout.fixed.vertical()
rows:connect_signal("button::press", function(_,_,_,button)
if carousel then
if button == 4 then -- up scrolling
local cnt = #rows.children
local first_widget = rows.children[1]
rows:insert(cnt+1, first_widget)
rows:remove(1)
elseif button == 5 then -- down scrolling
local cnt = #rows.children
local last_widget = rows.children[cnt]
rows:insert(1, last_widget)
rows:remove(cnt+1)
end
else
if button == 5 then -- up scrolling
if pointer < #rows.children and ((#rows.children - pointer) >= min_widgets) then
pointer = pointer + 1
rows.children[pointer].visible = false
end
elseif button == 4 then -- down scrolling
if pointer > 0 then
rows.children[pointer].visible = true
pointer = pointer - 1
end
end
end
end)
for line in containers:gmatch("[^\r\n]+") do
local package = parse_package(line)
if package ~= nil then
local refresh_button = wibox.widget {
{
{
id = 'icon',
image = ICONS_DIR .. 'refresh-cw.svg',
resize = false,
widget = wibox.widget.imagebox
},
margins = 4,
widget = wibox.container.margin
},
shape = gears.shape.circle,
opacity = 0.5,
widget = wibox.container.background
}
local old_cursor, old_wibox
refresh_button:connect_signal("mouse::enter", function(c)
c:set_opacity(1)
c:emit_signal('widget::redraw_needed')
local wb = mouse.current_wibox
old_cursor, old_wibox = wb.cursor, wb
wb.cursor = "hand1"
end)
refresh_button:connect_signal("mouse::leave", function(c)
c:set_opacity(0.5)
c:emit_signal('widget::redraw_needed')
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
end)
local row = wibox.widget {
{
{
{
{
id = 'checkbox',
checked = false,
color = beautiful.bg_normal,
paddings = 2,
shape = gears.shape.circle,
forced_width = 20,
forced_height = 20,
check_color = beautiful.fg_urgent,
border_color = beautiful.bg_urgent,
border_width = 1,
widget = wibox.widget.checkbox
},
valign = 'center',
layout = wibox.container.place,
},
{
{
id = 'name',
markup = '<b>' .. package['name'] .. '</b>',
widget = wibox.widget.textbox
},
halign = 'left',
layout = wibox.container.place
},
{
refresh_button,
halign = 'right',
valign = 'center',
fill_horizontal = true,
layout = wibox.container.place,
},
spacing = 8,
layout = wibox.layout.fixed.horizontal
},
margins = 8,
layout = wibox.container.margin
},
id = 'row',
bg = beautiful.bg_normal,
widget = wibox.container.background,
click = function(self, checked)
local a = self:get_children_by_id('checkbox')[1]
if checked == nil then
a:set_checked(not a.checked)
else
a:set_checked(checked)
end
if a.checked then
to_update[package['name']] = self
else
to_update[package['name']] = false
end
end,
update = function(self)
refresh_button:get_children_by_id('icon')[1]:set_image(ICONS_DIR .. 'watch.svg')
self:get_children_by_id('name')[1]:set_opacity(0.4)
self:get_children_by_id('name')[1]:emit_signal('widget::redraw_needed')
spawn.easy_async(
string.format([[sh -c 'yes | aptdcon --hide-terminal -u %s']], package['name']),
function(stdout, stderr) -- luacheck:ignore 212
rows:remove_widgets(self)
end)
end
}
row:connect_signal("mouse::enter", function(c)
c:set_bg(beautiful.bg_focus)
end)
row:connect_signal("mouse::leave", function(c)
c:set_bg(beautiful.bg_normal)
end)
row:connect_signal("button::press", function(c, _, _, button)
if button == 1 then c:click() end
end)
refresh_button:buttons(awful.util.table.join(awful.button({}, 1, function()
row:update()
end)))
rows:add(row)
end
end
local header_checkbox = wibox.widget {
checked = false,
color = beautiful.bg_normal,
paddings = 2,
shape = gears.shape.circle,
forced_width = 20,
forced_height = 20,
check_color = beautiful.fg_urgent,
border_color = beautiful.bg_urgent,
border_width = 1,
widget = wibox.widget.checkbox
}
header_checkbox:connect_signal("button::press", function(c)
c:set_checked(not c.checked)
local cbs = rows.children
for _,v in ipairs(cbs) do
v:click(c.checked)
end
end)
local header_refresh_icon = wibox.widget {
image = ICONS_DIR .. 'refresh-cw.svg',
resize = false,
widget = wibox.widget.imagebox
}
header_refresh_icon:buttons(awful.util.table.join(awful.button({}, 1, function()
print(#to_update)
for _,v in pairs(to_update) do
if v ~= nil then
v:update()
end
end
end)))
local header_row = wibox.widget {
{
{
{
header_checkbox,
valign = 'center',
layout = wibox.container.place,
},
{
{
id = 'name',
markup = '<b>' .. #rows.children .. '</b> packages to update',
widget = wibox.widget.textbox
},
halign = 'center',
layout = wibox.container.place
},
{
header_refresh_icon,
halign = 'right',
valign = 'center',
layout = wibox.container.place,
},
layout = wibox.layout.align.horizontal
},
margins = 8,
layout = wibox.container.margin
},
bg = beautiful.bg_normal,
widget = wibox.container.background
}
wibox_popup:setup {
header_row,
rows,
layout = wibox.layout.fixed.vertical
}
end
apt_widget:buttons(
awful.util.table.join(
awful.button({}, 1, function()
if wibox_popup.visible then
wibox_popup.visible = not wibox_popup.visible
else
spawn.easy_async(LIST_PACKAGES,
function(stdout, stderr)
rebuild_widget(stdout, stderr)
wibox_popup.visible = true
awful.placement.top(wibox_popup, { margins = { top = 20 }, parent = mouse})
end)
end
end)
)
)
return apt_widget
end
return setmetatable(apt_widget, { __call = function(_, ...) return worker(...) end })

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="circle_of_friends__x5F__black"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="425.197px"
height="425.197px" viewBox="0 0 425.197 425.197" enable-background="new 0 0 425.197 425.197" xml:space="preserve">
<g>
<path d="M354.331,212.595c0,78.279-63.45,141.735-141.729,141.735c-78.279,0-141.735-63.456-141.735-141.735
c0-78.274,63.457-141.728,141.735-141.728C290.881,70.867,354.331,134.32,354.331,212.595z"/>
<path fill="#FFFFFF" d="M139.043,212.595c0,10.064-8.159,18.225-18.23,18.225c-10.059,0-18.218-8.16-18.218-18.225
c0-10.06,8.159-18.219,18.218-18.219C130.884,194.376,139.043,202.535,139.043,212.595z M242.717,301.201
c5.033,8.709,16.173,11.696,24.889,6.67c8.715-5.033,11.701-16.179,6.669-24.895c-5.032-8.715-16.173-11.695-24.888-6.663
C240.671,281.346,237.685,292.486,242.717,301.201z M274.274,142.219c5.032-8.717,2.052-19.86-6.669-24.887
c-8.71-5.032-19.855-2.046-24.889,6.667c-5.032,8.715-2.046,19.857,6.67,24.889C258.102,153.92,269.248,150.934,274.274,142.219z
M212.602,160.632c27.153,0,49.434,20.814,51.761,47.364l26.372-0.416c-1.252-19.727-9.809-37.469-22.995-50.551
c-6.98,2.693-15.079,2.327-22.066-1.71c-6.992-4.037-11.359-10.871-12.514-18.275c-6.554-1.78-13.448-2.733-20.558-2.733
c-12.471,0-24.259,2.916-34.727,8.103l12.832,23.043C197.357,162.367,204.784,160.632,212.602,160.632z M160.633,212.595
c0-17.577,8.734-33.121,22.097-42.52l-13.54-22.634c-15.684,10.474-27.367,26.451-32.296,45.183
c5.833,4.697,9.57,11.897,9.57,19.972c0,8.08-3.738,15.28-9.57,19.978c4.929,18.731,16.612,34.708,32.296,45.188l13.54-22.634
C169.367,245.722,160.633,230.184,160.633,212.595z M212.602,264.568c-7.817,0-15.244-1.734-21.895-4.83l-12.832,23.043
c10.468,5.191,22.255,8.104,34.727,8.104c7.109,0,14.004-0.946,20.558-2.729c1.154-7.409,5.521-14.243,12.514-18.273
c6.987-4.037,15.086-4.404,22.066-1.711c13.187-13.088,21.743-30.83,22.995-50.557l-26.372-0.409
C262.035,243.749,239.755,264.568,212.602,264.568z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-help-circle"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>

After

Width:  |  Height:  |  Size: 365 B

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="circle_of_friends__x5F__orange"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="425.197px"
height="425.197px" viewBox="0 0 425.197 425.197" enable-background="new 0 0 425.197 425.197" xml:space="preserve">
<g>
<path fill="#E95420" d="M354.331,212.595c0,78.279-63.45,141.735-141.729,141.735c-78.279,0-141.735-63.456-141.735-141.735
c0-78.274,63.457-141.728,141.735-141.728C290.881,70.867,354.331,134.32,354.331,212.595z"/>
<path fill="#FFFFFF" d="M139.043,212.595c0,10.064-8.159,18.225-18.23,18.225c-10.059,0-18.218-8.16-18.218-18.225
c0-10.06,8.159-18.219,18.218-18.219C130.884,194.376,139.043,202.535,139.043,212.595z M242.717,301.201
c5.033,8.709,16.173,11.696,24.889,6.67c8.715-5.033,11.701-16.179,6.669-24.895c-5.032-8.715-16.173-11.695-24.888-6.663
C240.671,281.346,237.685,292.486,242.717,301.201z M274.274,142.219c5.032-8.717,2.052-19.86-6.669-24.887
c-8.71-5.032-19.855-2.046-24.889,6.667c-5.032,8.715-2.046,19.857,6.67,24.889C258.102,153.92,269.248,150.934,274.274,142.219z
M212.602,160.632c27.153,0,49.434,20.814,51.761,47.364l26.372-0.416c-1.252-19.727-9.809-37.469-22.995-50.551
c-6.98,2.693-15.079,2.327-22.066-1.71c-6.992-4.037-11.359-10.871-12.514-18.275c-6.554-1.78-13.448-2.733-20.558-2.733
c-12.471,0-24.259,2.916-34.727,8.103l12.832,23.043C197.357,162.367,204.784,160.632,212.602,160.632z M160.633,212.595
c0-17.577,8.734-33.121,22.097-42.52l-13.54-22.634c-15.684,10.474-27.367,26.451-32.296,45.183
c5.833,4.697,9.57,11.897,9.57,19.972c0,8.08-3.738,15.28-9.57,19.978c4.929,18.731,16.612,34.708,32.296,45.188l13.54-22.634
C169.367,245.722,160.633,230.184,160.633,212.595z M212.602,264.568c-7.817,0-15.244-1.734-21.895-4.83l-12.832,23.043
c10.468,5.191,22.255,8.104,34.727,8.104c7.109,0,14.004-0.946,20.558-2.729c1.154-7.409,5.521-14.243,12.514-18.273
c6.987-4.037,15.086-4.404,22.066-1.711c13.187-13.088,21.743-30.83,22.995-50.557l-26.372-0.409
C262.035,243.749,239.755,264.568,212.602,264.568z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-refresh-cw"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>

After

Width:  |  Height:  |  Size: 395 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-watch"><circle cx="12" cy="12" r="7"></circle><polyline points="12 9 12 12 13.5 13.5"></polyline><path d="M16.51 17.35l-.35 3.83a2 2 0 0 1-2 1.82H9.83a2 2 0 0 1-2-1.82l-.35-3.83m.01-10.7l.35-3.83A2 2 0 0 1 9.83 1h4.35a2 2 0 0 1 2 1.82l.35 3.83"></path></svg>

After

Width:  |  Height:  |  Size: 457 B

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="circle_of_friends__x5F__white"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="425.197px"
height="425.197px" viewBox="0 0 425.197 425.197" enable-background="new 0 0 425.197 425.197" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M354.331,212.595c0,78.279-63.45,141.735-141.729,141.735c-78.279,0-141.735-63.456-141.735-141.735
c0-78.274,63.457-141.728,141.735-141.728C290.881,70.867,354.331,134.32,354.331,212.595z"/>
<path d="M139.043,212.595c0,10.064-8.159,18.225-18.23,18.225c-10.059,0-18.218-8.16-18.218-18.225
c0-10.06,8.159-18.219,18.218-18.219C130.884,194.376,139.043,202.535,139.043,212.595z M242.717,301.201
c5.033,8.709,16.173,11.696,24.889,6.67c8.715-5.033,11.701-16.179,6.669-24.895c-5.032-8.715-16.173-11.695-24.888-6.663
C240.671,281.346,237.685,292.486,242.717,301.201z M274.274,142.219c5.032-8.717,2.052-19.86-6.669-24.887
c-8.71-5.032-19.855-2.046-24.889,6.667c-5.032,8.715-2.046,19.857,6.67,24.889C258.102,153.92,269.248,150.934,274.274,142.219z
M212.602,160.632c27.153,0,49.434,20.814,51.761,47.364l26.372-0.416c-1.252-19.727-9.809-37.469-22.995-50.551
c-6.98,2.693-15.079,2.327-22.066-1.71c-6.992-4.037-11.359-10.871-12.514-18.275c-6.554-1.78-13.448-2.733-20.558-2.733
c-12.471,0-24.259,2.916-34.727,8.103l12.832,23.043C197.357,162.367,204.784,160.632,212.602,160.632z M160.633,212.595
c0-17.577,8.734-33.121,22.097-42.52l-13.54-22.634c-15.684,10.474-27.367,26.451-32.296,45.183
c5.833,4.697,9.57,11.897,9.57,19.972c0,8.08-3.738,15.28-9.57,19.978c4.929,18.731,16.612,34.708,32.296,45.188l13.54-22.634
C169.367,245.722,160.633,230.184,160.633,212.595z M212.602,264.568c-7.817,0-15.244-1.734-21.895-4.83l-12.832,23.043
c10.468,5.191,22.255,8.104,34.727,8.104c7.109,0,14.004-0.946,20.558-2.729c1.154-7.409,5.521-14.243,12.514-18.273
c6.987-4.037,15.086-4.404,22.066-1.711c13.187-13.088,21.743-30.83,22.995-50.557l-26.372-0.409
C262.035,243.749,239.755,264.568,212.602,264.568z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="circle_of_friends__x5F__white_x26_orange"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="425.197px"
height="425.197px" viewBox="0 0 425.197 425.197" enable-background="new 0 0 425.197 425.197" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M354.331,212.595c0,78.279-63.45,141.735-141.729,141.735c-78.279,0-141.735-63.456-141.735-141.735
c0-78.274,63.457-141.728,141.735-141.728C290.881,70.867,354.331,134.32,354.331,212.595z"/>
<path fill="#E95420" d="M139.043,212.595c0,10.064-8.159,18.225-18.23,18.225c-10.059,0-18.218-8.16-18.218-18.225
c0-10.06,8.159-18.219,18.218-18.219C130.884,194.376,139.043,202.535,139.043,212.595z M242.717,301.201
c5.033,8.709,16.173,11.696,24.889,6.67c8.715-5.033,11.701-16.179,6.669-24.895c-5.032-8.715-16.173-11.695-24.888-6.663
C240.671,281.346,237.685,292.486,242.717,301.201z M274.274,142.219c5.032-8.717,2.052-19.86-6.669-24.887
c-8.71-5.032-19.855-2.046-24.889,6.667c-5.032,8.715-2.046,19.857,6.67,24.889C258.102,153.92,269.248,150.934,274.274,142.219z
M212.602,160.632c27.153,0,49.434,20.814,51.761,47.364l26.372-0.416c-1.252-19.727-9.809-37.469-22.995-50.551
c-6.98,2.693-15.079,2.327-22.066-1.71c-6.992-4.037-11.359-10.871-12.514-18.275c-6.554-1.78-13.448-2.733-20.558-2.733
c-12.471,0-24.259,2.916-34.727,8.103l12.832,23.043C197.357,162.367,204.784,160.632,212.602,160.632z M160.633,212.595
c0-17.577,8.734-33.121,22.097-42.52l-13.54-22.634c-15.684,10.474-27.367,26.451-32.296,45.183
c5.833,4.697,9.57,11.897,9.57,19.972c0,8.08-3.738,15.28-9.57,19.978c4.929,18.731,16.612,34.708,32.296,45.188l13.54-22.634
C169.367,245.722,160.633,230.184,160.633,212.595z M212.602,264.568c-7.817,0-15.244-1.734-21.895-4.83l-12.832,23.043
c10.468,5.191,22.255,8.104,34.727,8.104c7.109,0,14.004-0.946,20.558-2.729c1.154-7.409,5.521-14.243,12.514-18.273
c6.987-4.037,15.086-4.404,22.066-1.711c13.187-13.088,21.743-30.83,22.995-50.557l-26.372-0.409
C262.035,243.749,239.755,264.568,212.602,264.568z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

View File

@ -0,0 +1,75 @@
# Battery widget
Simple and easy-to-install widget for Awesome Window Manager.
This widget consists of:
- an icon which shows the battery level:
![Battery Widget](./bat-wid-1.png)
- a pop-up window, which shows up when you hover over an icon:
![Battery Widget](./bat-wid-2.png)
Alternatively you can use a tooltip (check the code):
![Battery Widget](./bat-wid-22.png)
- a pop-up warning message which appears on bottom right corner when battery level is less that 15% (you can get the image [here](https://vk.com/images/stickers/1933/512.png)):
![Battery Widget](./bat-wid-3.png)
Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder.
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `font` | Play 8 | Fond |
| `path_to_icons` | `/usr/share/icons/Arc/status/symbolic/` | Path to the folder with icons* |
| `show_current_level`| false | Show current charge level |
| `margin_right`|0| The right margin of the widget|
| `margin_left`|0| The left margin of the widget|
| `display_notification` | `false` | Display a notification on mouseover |
| `notification_position` | `top_right` | The notification position |
| `timeout` | 10 | How often in seconds the widget refreshes |
| `warning_msg_title` | _Huston, we have a problem_ | Title of the warning popup |
| `warning_msg_text` | _Battery is dying_ | Text of the warning popup |
| `warning_msg_position` | `bottom_right` | Position of the warning popup |
| `warning_msg_icon` | ~/.config/awesome/awesome-wm-widgets/battery-widget/spaceman.jpg | Icon of the warning popup |
| `enable_battery_warning` | `true` | Display low battery warning |
*Note: the widget expects following icons to be present in the folder:
- battery-caution-charging-symbolic.svg
- battery-empty-charging-symbolic.svg
- battery-full-charged-symbolic.svg
- battery-full-symbolic.svg
- battery-good-symbolic.svg
- battery-low-symbolic.svg
- battery-caution-symbolic.svg
- battery-empty-symbolic.svg
- battery-full-charging-symbolic.svg
- battery-good-charging-symbolic.svg
- battery-low-charging-symbolic.svg
- battery-missing-symbolic.svg
## Installation
This widget reads the output of acpi tool.
- install `acpi` and check the output:
```bash
$ sudo apt-get install acpi
$ acpi
Battery 0: Discharging, 66%, 02:34:06 remaining
```
```lua
local battery_widget = require("awesome-wm-widgets.battery-widget.battery")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
battery_widget(),
...
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,200 @@
-------------------------------------------------
-- Battery Widget for Awesome Window Manager
-- Shows the battery status using the ACPI tool
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/battery-widget
-- @author Pavel Makhov
-- @copyright 2017 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local naughty = require("naughty")
local watch = require("awful.widget.watch")
local wibox = require("wibox")
local gfs = require("gears.filesystem")
local dpi = require('beautiful').xresources.apply_dpi
-- acpi sample outputs
-- Battery 0: Discharging, 75%, 01:51:38 remaining
-- Battery 0: Charging, 53%, 00:57:43 until charged
local HOME = os.getenv("HOME")
local WIDGET_DIR = HOME .. '/.config/awesome/awesome-wm-widgets/battery-widget'
local battery_widget = {}
local function worker(user_args)
local args = user_args or {}
local font = args.font or 'Play 8'
local path_to_icons = args.path_to_icons or "/usr/share/icons/Arc/status/symbolic/"
local show_current_level = args.show_current_level or false
local margin_left = args.margin_left or 0
local margin_right = args.margin_right or 0
local display_notification = args.display_notification or false
local display_notification_onClick = args.display_notification_onClick or true
local position = args.notification_position or "top_right"
local timeout = args.timeout or 10
local warning_msg_title = args.warning_msg_title or 'Huston, we have a problem'
local warning_msg_text = args.warning_msg_text or 'Battery is dying'
local warning_msg_position = args.warning_msg_position or 'bottom_right'
local warning_msg_icon = args.warning_msg_icon or WIDGET_DIR .. '/spaceman.jpg'
local enable_battery_warning = args.enable_battery_warning
if enable_battery_warning == nil then
enable_battery_warning = true
end
if not gfs.dir_readable(path_to_icons) then
naughty.notify{
title = "Battery Widget",
text = "Folder with icons doesn't exist: " .. path_to_icons,
preset = naughty.config.presets.critical
}
end
local icon_widget = wibox.widget {
{
id = "icon",
widget = wibox.widget.imagebox,
resize = false
},
valign = 'center',
layout = wibox.container.place,
}
local level_widget = wibox.widget {
font = font,
widget = wibox.widget.textbox
}
battery_widget = wibox.widget {
icon_widget,
level_widget,
layout = wibox.layout.fixed.horizontal,
}
-- Popup with battery info
-- One way of creating a pop-up notification - naughty.notify
local notification
local function show_battery_status(batteryType)
awful.spawn.easy_async([[bash -c 'acpi']],
function(stdout, _, _, _)
naughty.destroy(notification)
notification = naughty.notify{
text = stdout,
title = "Battery status",
icon = path_to_icons .. batteryType .. ".svg",
icon_size = dpi(16),
position = position,
timeout = 5, hover_timeout = 0.5,
width = 200,
screen = mouse.screen
}
end
)
end
-- Alternative to naughty.notify - tooltip. You can compare both and choose the preferred one
--battery_popup = awful.tooltip({objects = {battery_widget}})
-- To use colors from beautiful theme put
-- following lines in rc.lua before require("battery"):
-- beautiful.tooltip_fg = beautiful.fg_normal
-- beautiful.tooltip_bg = beautiful.bg_normal
local function show_battery_warning()
naughty.notify {
icon = warning_msg_icon,
icon_size = 100,
text = warning_msg_text,
title = warning_msg_title,
timeout = 25, -- show the warning for a longer time
hover_timeout = 0.5,
position = warning_msg_position,
bg = "#F06060",
fg = "#EEE9EF",
width = 300,
screen = mouse.screen
}
end
local last_battery_check = os.time()
local batteryType = "battery-good-symbolic"
watch("acpi -i", timeout,
function(widget, stdout)
local battery_info = {}
local capacities = {}
for s in stdout:gmatch("[^\r\n]+") do
local status, charge_str, _ = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?(.*)')
if status ~= nil then
table.insert(battery_info, {status = status, charge = tonumber(charge_str)})
else
local cap_str = string.match(s, '.+:.+last full capacity (%d+)')
table.insert(capacities, tonumber(cap_str))
end
end
local capacity = 0
for _, cap in ipairs(capacities) do
capacity = capacity + cap
end
local charge = 0
local status
for i, batt in ipairs(battery_info) do
if capacities[i] ~= nil then
if batt.charge >= charge then
status = batt.status -- use most charged battery status
-- this is arbitrary, and maybe another metric should be used
end
charge = charge + batt.charge * capacities[i]
end
end
charge = charge / capacity
if show_current_level then
level_widget.text = string.format('%d%%', charge)
end
if (charge >= 0 and charge < 15) then
batteryType = "battery-empty%s-symbolic"
if enable_battery_warning and status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then
-- if 5 minutes have elapsed since the last warning
last_battery_check = os.time()
show_battery_warning()
end
elseif (charge >= 15 and charge < 40) then batteryType = "battery-caution%s-symbolic"
elseif (charge >= 40 and charge < 60) then batteryType = "battery-low%s-symbolic"
elseif (charge >= 60 and charge < 80) then batteryType = "battery-good%s-symbolic"
elseif (charge >= 80 and charge <= 100) then batteryType = "battery-full%s-symbolic"
end
if status == 'Charging' then
batteryType = string.format(batteryType, '-charging')
else
batteryType = string.format(batteryType, '')
end
widget.icon:set_image(path_to_icons .. batteryType .. ".svg")
-- Update popup text
-- battery_popup.text = string.gsub(stdout, "\n$", "")
end,
icon_widget)
if display_notification then
battery_widget:connect_signal("mouse::enter", function() show_battery_status(batteryType) end)
battery_widget:connect_signal("mouse::leave", function() naughty.destroy(notification) end)
elseif display_notification_onClick then
battery_widget:connect_signal("button::press", function(_,_,_,button)
if (button == 3) then show_battery_status(batteryType) end
end)
battery_widget:connect_signal("mouse::leave", function() naughty.destroy(notification) end)
end
return wibox.container.margin(battery_widget, margin_left, margin_right)
end
return setmetatable(battery_widget, { __call = function(_, ...) return worker(...) end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,72 @@
# Batteryarc widget
[![GitHub issues by-label](https://img.shields.io/github/issues-raw/streetturtle/awesome-wm-widgets/batteryarc)](https://github.com/streetturtle/awesome-wm-widgets/labels/batteryarc)
This widget is more informative version of [battery widget](https://github.com/streetturtle/awesome-wm-widgets/tree/master/battery-widget).
Depending of the battery status it could look following ways:
- ![10_d](./10_d.png) - less than 15 percent
- ![10_c](./10_c.png) - less than 15 percent, charging
- ![20_d](./20_d.png) - between 15 and 40 percent
- ![20_c](./20_c.png) - between 15 and 40 percent, charging
- ![80_d](./80_d.png) - more than 40 percent
- ![80_c](./80_c.png) - more than 40 percent, charging
If a battery level is low then warning popup will show up:
![warning](./warning.png)
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `font` | Play 6 | Font |
| `arc_thickness` | 2 | Thickness of the arc |
| `show_current_level`| false | Show current charge level |
| `size`| 18 | Size of the widget |
| `timeout` | 10 | How often in seconds the widget refreshes |
| `main_color` | `beautiful.fg_color` | Color of the text with the current charge level and the arc |
| `bg_color` | `#ffffff11` | Color of the charge level background |
| `low_level_color` | `#e53935` | Arc color when battery charge is less that 15% |
| `medium_level_color` | `#c0ca33` | Arc color when battery charge is between 15% and 40% |
| `charging_color` | `#43a047` | Color of the circle inside the arc when charging |
| `warning_msg_title` | _Huston, we have a problem_ | Title of the warning popup |
| `warning_msg_text` | _Battery is dying_ | Text of the warning popup |
| `warning_msg_position` | `bottom_right` | Position of the warning popup |
| `warning_msg_icon` | ~/.config/awesome/awesome-wm-widgets/batteryarc-widget/spaceman.jpg | Icon of the warning popup |
| `enable_battery_warning` | `true` | Display low battery warning |
| `show_notification_mode` | `on_hover` | How to trigger a notification with the battery status: `on_hover`, `on_click` or `off` |
## Requirements
This widget requires the `acpi` command to be available to retrieve battery and
power information.
## Installation
Clone repo, include widget and use it in **rc.lua**:
```lua
local batteryarc_widget = require("awesome-wm-widgets.batteryarc-widget.batteryarc")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
--[[default]]
batteryarc_widget(),
--[[or customized]]
batteryarc_widget({
show_current_level = true,
arc_thickness = 1,
}),
}
...
```
## Troubleshooting
In case of any doubts or questions please raise an [issue](https://github.com/streetturtle/awesome-wm-widgets/issues/new).

View File

@ -0,0 +1,168 @@
-------------------------------------------------
-- Battery Arc Widget for Awesome Window Manager
-- Shows the battery level of the laptop
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/batteryarc-widget
-- @author Pavel Makhov
-- @copyright 2020 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local beautiful = require("beautiful")
local naughty = require("naughty")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local HOME = os.getenv("HOME")
local WIDGET_DIR = HOME .. '/.config/awesome/awesome-wm-widgets/batteryarc-widget'
local batteryarc_widget = {}
local function worker(user_args)
local args = user_args or {}
local font = args.font or 'Play 6'
local arc_thickness = args.arc_thickness or 2
local show_current_level = args.show_current_level or false
local size = args.size or 18
local timeout = args.timeout or 10
local show_notification_mode = args.show_notification_mode or 'on_hover' -- on_hover / on_click
local main_color = args.main_color or beautiful.fg_color
local bg_color = args.bg_color or '#ffffff11'
local low_level_color = args.low_level_color or '#e53935'
local medium_level_color = args.medium_level_color or '#c0ca33'
local charging_color = args.charging_color or '#43a047'
local warning_msg_title = args.warning_msg_title or 'Houston, we have a problem'
local warning_msg_text = args.warning_msg_text or 'Battery is dying'
local warning_msg_position = args.warning_msg_position or 'bottom_right'
local warning_msg_icon = args.warning_msg_icon or WIDGET_DIR .. '/spaceman.jpg'
local enable_battery_warning = args.enable_battery_warning
if enable_battery_warning == nil then
enable_battery_warning = true
end
local text = wibox.widget {
font = font,
align = 'center',
valign = 'center',
widget = wibox.widget.textbox
}
local text_with_background = wibox.container.background(text)
batteryarc_widget = wibox.widget {
text_with_background,
max_value = 100,
rounded_edge = true,
thickness = arc_thickness,
start_angle = 4.71238898, -- 2pi*3/4
forced_height = size,
forced_width = size,
bg = bg_color,
paddings = 2,
widget = wibox.container.arcchart
}
local last_battery_check = os.time()
--[[ Show warning notification ]]
local function show_battery_warning()
naughty.notify {
icon = warning_msg_icon,
icon_size = 100,
text = warning_msg_text,
title = warning_msg_title,
timeout = 25, -- show the warning for a longer time
hover_timeout = 0.5,
position = warning_msg_position,
bg = "#F06060",
fg = "#EEE9EF",
width = 300,
}
end
local function update_widget(widget, stdout)
local charge = 0
local status
for s in stdout:gmatch("[^\r\n]+") do
local cur_status, charge_str, _ = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?(.*)')
if cur_status ~= nil and charge_str ~=nil then
local cur_charge = tonumber(charge_str)
if cur_charge > charge then
status = cur_status
charge = cur_charge
end
end
end
widget.value = charge
if status == 'Charging' then
text_with_background.bg = charging_color
text_with_background.fg = '#000000'
else
text_with_background.bg = '#00000000'
text_with_background.fg = main_color
end
if show_current_level == true then
--- if battery is fully charged (100) there is not enough place for three digits, so we don't show any text
text.text = charge == 100
and ''
or string.format('%d', charge)
else
text.text = ''
end
if charge < 15 then
widget.colors = { low_level_color }
if enable_battery_warning and status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then
-- if 5 minutes have elapsed since the last warning
last_battery_check = os.time()
show_battery_warning()
end
elseif charge > 15 and charge < 40 then
widget.colors = { medium_level_color }
else
widget.colors = { main_color }
end
end
watch("acpi", timeout, update_widget, batteryarc_widget)
-- Popup with battery info
local notification
local function show_battery_status()
awful.spawn.easy_async([[bash -c 'acpi']],
function(stdout, _, _, _)
naughty.destroy(notification)
notification = naughty.notify {
text = stdout,
title = "Battery status",
timeout = 5,
width = 200,
}
end)
end
if show_notification_mode == 'on_hover' then
batteryarc_widget:connect_signal("mouse::enter", function() show_battery_status() end)
batteryarc_widget:connect_signal("mouse::leave", function() naughty.destroy(notification) end)
elseif show_notification_mode == 'on_click' then
batteryarc_widget:connect_signal('button::press', function(_, _, _, button)
if (button == 1) then show_battery_status() end
end)
end
return batteryarc_widget
end
return setmetatable(batteryarc_widget, { __call = function(_, ...)
return worker(...)
end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,69 @@
# Bitbucket widget
The widget shows the number of pull requests assigned to the user and when clicked shows them in the list with some additional information. When item in the list is clicked - it opens the pull request in the browser.
## How it works
Widget uses cURL to query Bitbucket's [REST API](https://developer.atlassian.com/bitbucket/api/2/reference/). In order to be authenticated, widget uses a [netrc](https://ec.haxx.se/usingcurl/usingcurl-netrc) feature of the cURL, which is basically allows storing basic auth credentials in a **.netrc** file in home folder.
Bitbucket allows using [App Passwords](https://confluence.atlassian.com/bitbucket/app-passwords-828781300.html) (available in the account settings) - simply generate one for the widget and use it as password in **.netrc** file.
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `icon` | `~/.config/awesome/awesome-wm-widgets/bitbucket-widget/bitbucket-icon-gradient-blue.svg` | Path to the icon |
| `host` | Required | e.g _http://api.bitbucket.org_ |
| `uuid` | Required | e.g _{123e4567-e89b-12d3-a456-426614174000}_ |
| `workspace` | Required | Workspace ID|
| `repo_slug` | Required | Repository slug |
| `timeout` | 60 | How often in seconds the widget refreshes |
Note:
- host most likely should start with _api._
- to get your UUID you may call `curl -s -n 'https://api.bitbucket.org/2.0/user'`
## Installation
Create a **.netrc** file in you home directory with following content:
```bash
machine api.bitbucket.org
login mikey@tmnt.com
password cowabunga
```
Then change file's permissions to 600 (so only you can read/write it):
```bash
chmod 600 ~/.netrc
```
And test if it works by calling the API:
```bash
curl -s -n 'https://api.bitbucket.org/2.0/repositories/'
```
Also, to properly setup required parameters you can use `test_bitbucket_api.sh` script - it uses the same curl call as widget.
Then clone/download repo and use widget in **rc.lua**:
```lua
local bitbucket_widget = require("awesome-wm-widgets.bitbucket-widget.bitbucket")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
-- default
bitbucket_widget({
host = 'https://api.bitbucket.org',
uuid = '{123e4567-e89b-12d3-a456-426614174000}',
workspace = 'workspace',
repo_slug = 'slug'
}}),
...
```

View File

@ -0,0 +1 @@
<svg id="Logos" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" viewBox="0 0 80 80"><defs><style>.cls-1{fill:none;}.cls-2{fill:#2684ff;}.cls-3{fill:url(#New_Gradient_Swatch_1);}</style><linearGradient id="New_Gradient_Swatch_1" x1="71.61" y1="36.15" x2="41.78" y2="59.43" gradientUnits="userSpaceOnUse"><stop offset="0.18" stop-color="#0052cc"/><stop offset="1" stop-color="#2684ff"/></linearGradient></defs><title>bitbucket-icon-gradient-blue</title><polygon class="cls-1" points="33.81 48.88 46.36 48.88 49.39 31.2 30.47 31.2 33.81 48.88"/><path class="cls-2" d="M12,13.06a1.92,1.92,0,0,0-1.9,2.23l8.14,49.56A2.62,2.62,0,0,0,20.78,67H60a1.93,1.93,0,0,0,1.9-1.62L70,15.3a1.92,1.92,0,0,0-1.9-2.23ZM46.36,48.88H33.81L30.47,31.2H49.39Z"/><path class="cls-3" d="M67.44,31.2h-18l-3,17.68H33.81L19.1,66.4a2.61,2.61,0,0,0,1.68.63H60a1.93,1.93,0,0,0,1.9-1.62Z"/></svg>

After

Width:  |  Height:  |  Size: 914 B

View File

@ -0,0 +1,371 @@
-------------------------------------------------
-- Bitbucket Widget for Awesome Window Manager
-- Shows the number of currently assigned pull requests
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/bitbucket-widget
-- @author Pavel Makhov
-- @copyright 2020 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local json = require("json")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
local gfs = require("gears.filesystem")
local HOME_DIR = os.getenv("HOME")
local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/bitbucket-widget/'
local GET_PRS_CMD= [[bash -c "curl -s --show-error -n ]]
.. [['%s/2.0/repositories/%s/%s/pullrequests]]
.. [[?fields=values.participants.approved,values.title,values.links.html,values.author.display_name,]]
.. [[values.author.uuid,values.author.links.avatar,values.source.branch,values.destination.branch,]]
.. [[values.comment_count,values.created_on&q=reviewers.uuid+%%3D+%%22%s%%22+AND+state+%%3D+%%22OPEN%%22']]
.. [[ | jq '.[] '"]]
local DOWNLOAD_AVATAR_CMD = [[bash -c "curl -L -n --create-dirs -o %s/.cache/awmw/bitbucket-widget/avatars/%s %s"]]
local bitbucket_widget = wibox.widget {
{
{
id = 'icon',
widget = wibox.widget.imagebox
},
margins = 4,
layout = wibox.container.margin
},
{
id = "txt",
widget = wibox.widget.textbox
},
{
id = "new_pr",
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.horizontal,
set_text = function(self, new_value)
self.txt.text = new_value
end,
set_icon = function(self, new_value)
self:get_children_by_id('icon')[1]:set_image(new_value)
end
}
local function show_warning(message)
naughty.notify{
preset = naughty.config.presets.critical,
title = 'Bitbucket Widget',
text = message}
end
local popup = awful.popup{
ontop = true,
visible = false,
shape = gears.shape.rounded_rect,
border_width = 1,
border_color = beautiful.bg_focus,
maximum_width = 400,
offset = { y = 5 },
widget = {}
}
--- Converts string representation of date (2020-06-02T11:25:27Z) to date
local function parse_date(date_str)
local pattern = "(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)%Z"
local y, m, d, h, min, sec, _ = date_str:match(pattern)
return os.time{year = y, month = m, day = d, hour = h, min = min, sec = sec}
end
--- Converts seconds to "time ago" represenation, like '1 hour ago'
local function to_time_ago(seconds)
local days = seconds / 86400
if days > 1 then
days = math.floor(days + 0.5)
return days .. (days == 1 and ' day' or ' days') .. ' ago'
end
local hours = (seconds % 86400) / 3600
if hours > 1 then
hours = math.floor(hours + 0.5)
return hours .. (hours == 1 and ' hour' or ' hours') .. ' ago'
end
local minutes = ((seconds % 86400) % 3600) / 60
if minutes > 1 then
minutes = math.floor(minutes + 0.5)
return minutes .. (minutes == 1 and ' minute' or ' minutes') .. ' ago'
end
end
local function ellipsize(text, length)
return (text:len() > length and length > 0)
and text:sub(0, length - 3) .. '...'
or text
end
local function count_approves(participants)
local res = 0
for i = 1, #participants do
if participants[i]['approved'] then res = res + 1 end
end
return res
end
local function worker(user_args)
local args = user_args or {}
local icon = args.icon or WIDGET_DIR .. '/bitbucket-icon-gradient-blue.svg'
local host = args.host or show_warning('Bitbucket host is not set')
local uuid = args.uuid or show_warning('UUID is not set')
local workspace = args.workspace or show_warning('Workspace is not set')
local repo_slug = args.repo_slug or show_warning('Repo slug is not set')
local timeout = args.timeout or 60
local current_number_of_prs
local to_review_rows = {layout = wibox.layout.fixed.vertical}
local my_review_rows = {layout = wibox.layout.fixed.vertical}
local rows = {layout = wibox.layout.fixed.vertical}
bitbucket_widget:set_icon(icon)
local update_widget = function(widget, stdout, stderr, _, _)
if stderr ~= '' then
show_warning(stderr)
return
end
local result = json.decode(stdout)
current_number_of_prs = rawlen(result)
if current_number_of_prs == 0 then
widget:set_visible(false)
return
end
widget:set_visible(true)
widget:set_text(current_number_of_prs)
for i = 0, #rows do rows[i]=nil end
for i = 0, #to_review_rows do to_review_rows[i]=nil end
table.insert(to_review_rows, {
{
markup = '<span size="large" color="#ffffff">PRs to review</span>',
align = 'center',
forced_height = 20,
widget = wibox.widget.textbox
},
bg = beautiful.bg_normal,
widget = wibox.container.background
})
for i = 0, #my_review_rows do my_review_rows[i]=nil end
table.insert(my_review_rows, {
{
markup = '<span size="large" color="#ffffff">My PRs</span>',
align = 'center',
forced_height = 20,
widget = wibox.widget.textbox
},
bg = beautiful.bg_normal,
widget = wibox.container.background
})
local current_time = os.time(os.date("!*t"))
for _, pr in ipairs(result) do
local path_to_avatar = os.getenv("HOME") ..'/.cache/awmw/bitbucket-widget/avatars/' .. pr.author.uuid
local number_of_approves = count_approves(pr.participants)
local row = wibox.widget {
{
{
{
{
resize = true,
image = path_to_avatar,
forced_width = 40,
forced_height = 40,
widget = wibox.widget.imagebox
},
id = 'avatar',
margins = 8,
layout = wibox.container.margin
},
{
{
id = 'title',
markup = '<b>' .. ellipsize(pr.title, 50) .. '</b>',
widget = wibox.widget.textbox,
forced_width = 400
},
{
{
{
{
text = ellipsize(pr.source.branch.name, 30),
widget = wibox.widget.textbox
},
{
text = '->',
widget = wibox.widget.textbox
},
{
text = pr.destination.branch.name,
widget = wibox.widget.textbox
},
spacing = 8,
layout = wibox.layout.fixed.horizontal
},
{
{
text = pr.author.display_name,
widget = wibox.widget.textbox
},
{
text = to_time_ago(os.difftime(current_time, parse_date(pr.created_on))),
widget = wibox.widget.textbox
},
spacing = 8,
expand = 'none',
layout = wibox.layout.fixed.horizontal
},
forced_width = 285,
layout = wibox.layout.fixed.vertical
},
{
{
{
image = WIDGET_DIR .. '/check.svg',
resize = false,
widget = wibox.widget.imagebox
},
{
text = number_of_approves,
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.horizontal
},
{
{
image = WIDGET_DIR .. '/message-circle.svg',
resize = false,
widget = wibox.widget.imagebox
},
{
text = pr.comment_count,
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.horizontal
},
layout = wibox.layout.fixed.vertical
},
layout = wibox.layout.fixed.horizontal
},
spacing = 8,
layout = wibox.layout.fixed.vertical
},
spacing = 8,
layout = wibox.layout.fixed.horizontal
},
margins = 8,
layout = wibox.container.margin
},
bg = beautiful.bg_normal,
widget = wibox.container.background
}
if not gfs.file_readable(path_to_avatar) then
local cmd = string.format(DOWNLOAD_AVATAR_CMD, HOME_DIR, pr.author.uuid, pr.author.links.avatar.href)
spawn.easy_async(cmd, function() row:get_children_by_id('avatar')[1]:set_image(path_to_avatar) end)
end
row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end)
row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end)
row:get_children_by_id('title')[1]:buttons(
awful.util.table.join(
awful.button({}, 1, function()
spawn.with_shell("xdg-open " .. pr.links.html.href)
popup.visible = false
end)
)
)
row:get_children_by_id('avatar')[1]:buttons(
awful.util.table.join(
awful.button({}, 1, function()
spawn.with_shell(
string.format('xdg-open "https://bitbucket.org/%s/%s/pull-requests?state=OPEN&author=%s"',
workspace, repo_slug, pr.author.uuid)
)
popup.visible = false
end)
)
)
local old_cursor, old_wibox
row:get_children_by_id('title')[1]:connect_signal("mouse::enter", function()
local wb = mouse.current_wibox
old_cursor, old_wibox = wb.cursor, wb
wb.cursor = "hand1"
end)
row:get_children_by_id('title')[1]:connect_signal("mouse::leave", function()
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
end)
row:get_children_by_id('avatar')[1]:connect_signal("mouse::enter", function()
local wb = mouse.current_wibox
old_cursor, old_wibox = wb.cursor, wb
wb.cursor = "hand1"
end)
row:get_children_by_id('avatar')[1]:connect_signal("mouse::leave", function()
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
end)
if (pr.author.uuid == '{' .. uuid .. '}') then
table.insert(my_review_rows, row)
else
table.insert(to_review_rows, row)
end
end
table.insert(rows, to_review_rows)
if (#my_review_rows > 1) then
table.insert(rows, my_review_rows)
end
popup:setup(rows)
end
bitbucket_widget:buttons(
awful.util.table.join(
awful.button({}, 1, function()
if popup.visible then
popup.visible = not popup.visible
else
popup:move_next_to(mouse.current_widget_geometry)
end
end)
)
)
watch(string.format(GET_PRS_CMD, host, workspace, repo_slug, uuid, uuid),
timeout, update_widget, bitbucket_widget)
return bitbucket_widget
end
return setmetatable(bitbucket_widget, { __call = function(_, ...) return worker(...) end })

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#A3BE8C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></svg>

After

Width:  |  Height:  |  Size: 257 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clipboard"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>

After

Width:  |  Height:  |  Size: 366 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>

After

Width:  |  Height:  |  Size: 346 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-git-pull-request"><circle cx="18" cy="18" r="3"></circle><circle cx="6" cy="6" r="3"></circle><path d="M13 6h3a2 2 0 0 1 2 2v7"></path><line x1="6" y1="9" x2="6" y2="21"></line></svg>

After

Width:  |  Height:  |  Size: 382 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-circle"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>

After

Width:  |  Height:  |  Size: 423 B

View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
HOST='https://api.bitbucket.org'
ACCOUNT_ID=''
WORKSPACE=''
REPO_SLUG=''
curl -s -n "${HOST}/2.0/repositories/${WORKSPACE}/${REPO_SLUG}/pullrequests?fields=values.title,values.links.html,values.author.display_name,values.author.links.avatar&q=reviewers.account_id+%3D+%22${ACCOUNT_ID}%22"

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ECEFF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>

After

Width:  |  Height:  |  Size: 308 B

View File

@ -0,0 +1,93 @@
# Brightness widget
This widget represents current brightness level, depending on config parameters could be an arcchart or icon with text: ![Brightness widget](./br-wid-1.png)
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `type`| `arc` | The widget type. Could be `arc` or `icon_and_text` |
| `program` | `light` | The program used to control the brightness, either `light`, `xbacklight`, or `brightnessctl`. |
| `step` | 5 | Step |
| `base` | 20 | Base level to set brightness to on left click. |
| `path_to_icon` | `/usr/share/icons/Arc/status/symbolic/display-brightness-symbolic.svg` | Path to the icon |
| `font` | `Play 9` | Font |
| `timeout` | 1 | How often in seconds the widget refreshes. Check the note below |
| `tooltip` | false | Display brightness level in a tooltip when the mouse cursor hovers the widget |
_Note:_ If brightness is controlled only by the widget (either by a mouse, or by a shortcut, then the `timeout` could be quite big, as there is no reason to synchronize the brightness level).
## Installation
To choose the right `program` argument, first you need to check which of them works better for you.
- using `xbacklight`:
Install (on Ubuntu it's available in the apt repository) it and check if it works by running:
```bash
xbacklight -get
```
If there is no output it means that it doesn't work, you can either try to fix it, or try to use `light`.
- using `light` command:
Install (on Ubuntu it's available in the apt repository) from the repo: [github.com/haikarainen/light](https://github.com/haikarainen/light) and check if it works by running
```bash
light -G
49.18
light -A 5
```
If you're on Ubuntu/debian and if the brightness level doesn't change, try to do this: https://github.com/haikarainen/light/issues/113#issuecomment-632638436.
- using `brightnessctl`:
On Ubuntu it is available in the apt repository. Install and check the ouptut of the following command.
```bash
brightnessctl --list
```
Then clone this repo under **~/.config/awesome/**:
```bash
git clone https://github.com/streetturtle/awesome-wm-widgets.git ~/.config/awesome/awesome-wm-widgets
```
Require widget at the beginning of **rc.lua**:
```lua
local brightness_widget = require("awesome-wm-widgets.brightness-widget.brightness")
```
Add the widget to the tasklist:
```lua
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
-- default
brightness_widget(),
-- or customized
brightness_widget{
type = 'icon_and_text',
program = 'xbacklight',
step = 2,
}
}
...
```
## Controls
In order to change brightness by shortcuts you can add them to the `globalkeys` table in the **rc.lua**:
```lua
awful.key({ modkey }, ";", function () brightness_widget:inc() end, {description = "increase brightness", group = "custom"}),
awful.key({ modkey, "Shift"}, ";", function () brightness_widget:dec() end, {description = "decrease brightness", group = "custom"}),
```
On a laptop you can use `XF86MonBrightnessUp` and `XF86MonBrightnessDown` keys.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,186 @@
-------------------------------------------------
-- Brightness Widget for Awesome Window Manager
-- Shows the brightness level of the laptop display
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/brightness-widget
-- @author Pavel Makhov
-- @copyright 2021 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/brightness-widget/'
local get_brightness_cmd
local set_brightness_cmd
local inc_brightness_cmd
local dec_brightness_cmd
local brightness_widget = {}
local function show_warning(message)
naughty.notify{
preset = naughty.config.presets.critical,
title = 'Brightness Widget',
text = message}
end
local function worker(user_args)
local args = user_args or {}
local type = args.type or 'arc' -- arc or icon_and_text
local path_to_icon = args.path_to_icon or ICON_DIR .. 'brightness.svg'
local font = args.font or 'Play 9'
local timeout = args.timeout or 100
local program = args.program or 'light'
local step = args.step or 5
local base = args.base or 20
local current_level = 0 -- current brightness value
local tooltip = args.tooltip or false
if program == 'light' then
get_brightness_cmd = 'light -G'
set_brightness_cmd = 'light -S %d' -- <level>
inc_brightness_cmd = 'light -A ' .. step
dec_brightness_cmd = 'light -U ' .. step
elseif program == 'xbacklight' then
get_brightness_cmd = 'xbacklight -get'
set_brightness_cmd = 'xbacklight -set %d' -- <level>
inc_brightness_cmd = 'xbacklight -inc ' .. step
dec_brightness_cmd = 'xbacklight -dec ' .. step
elseif program == 'brightnessctl' then
get_brightness_cmd = 'bash -c "brightnessctl -m | cut -d, -f4 | tr -d %"'
set_brightness_cmd = 'brightnessctl set %d%%' -- <level>
inc_brightness_cmd = 'brightnessctl set +' .. step .. '%'
dec_brightness_cmd = 'brightnessctl set ' .. step .. '-%'
else
show_warning(program .. " command is not supported by the widget")
return
end
if type == 'icon_and_text' then
brightness_widget.widget = wibox.widget {
{
{
image = path_to_icon,
resize = false,
widget = wibox.widget.imagebox,
},
valign = 'center',
layout = wibox.container.place
},
{
id = 'txt',
font = font,
widget = wibox.widget.textbox
},
spacing = 4,
layout = wibox.layout.fixed.horizontal,
set_value = function(self, level)
self:get_children_by_id('txt')[1]:set_text(level .. '%')
end
}
elseif type == 'arc' then
brightness_widget.widget = wibox.widget {
{
{
image = path_to_icon,
resize = true,
widget = wibox.widget.imagebox,
},
valign = 'center',
layout = wibox.container.place
},
max_value = 100,
thickness = 2,
start_angle = 4.71238898, -- 2pi*3/4
forced_height = 18,
forced_width = 18,
paddings = 2,
widget = wibox.container.arcchart,
set_value = function(self, level)
self:set_value(level)
end
}
else
show_warning(type .. " type is not supported by the widget")
return
end
local update_widget = function(widget, stdout, _, _, _)
local brightness_level = tonumber(string.format("%.0f", stdout))
current_level = brightness_level
widget:set_value(brightness_level)
end
function brightness_widget:set(value)
current_level = value
spawn.easy_async(string.format(set_brightness_cmd, value), function()
spawn.easy_async(get_brightness_cmd, function(out)
update_widget(brightness_widget.widget, out)
end)
end)
end
local old_level = 0
function brightness_widget:toggle()
if old_level < 0.1 then
-- avoid toggling between '0' and 'almost 0'
old_level = 1
end
if current_level < 0.1 then
-- restore previous level
current_level = old_level
else
-- save current brightness for later
old_level = current_level
current_level = 0
end
brightness_widget:set(current_level)
end
function brightness_widget:inc()
spawn.easy_async(inc_brightness_cmd, function()
spawn.easy_async(get_brightness_cmd, function(out)
update_widget(brightness_widget.widget, out)
end)
end)
end
function brightness_widget:dec()
spawn.easy_async(dec_brightness_cmd, function()
spawn.easy_async(get_brightness_cmd, function(out)
update_widget(brightness_widget.widget, out)
end)
end)
end
brightness_widget.widget:buttons(
awful.util.table.join(
awful.button({}, 1, function() brightness_widget:set(base) end),
awful.button({}, 3, function() brightness_widget:toggle() end),
awful.button({}, 4, function() brightness_widget:inc() end),
awful.button({}, 5, function() brightness_widget:dec() end)
)
)
watch(get_brightness_cmd, timeout, update_widget, brightness_widget.widget)
if tooltip then
awful.tooltip {
objects = { brightness_widget.widget },
timer_function = function()
return current_level .. " %"
end,
}
end
return brightness_widget.widget
end
return setmetatable(brightness_widget, { __call = function(_, ...)
return worker(...)
end })

View File

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.91 r13725"
version="1.0"
sodipodi:docname="display-brightness-symbolic.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
style="display:inline">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#e7e7e7"
borderopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="44.218752"
inkscape:cx="12.155025"
inkscape:cy="7.6228779"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:showpageshadow="false"
showguides="false"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1029"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true">
<sodipodi:guide
orientation="1,0"
position="0,112"
id="guide2383" />
<sodipodi:guide
orientation="0,1"
position="26.278146,128"
id="guide2385" />
<sodipodi:guide
orientation="1,0"
position="128,54.082119"
id="guide2387" />
<sodipodi:guide
orientation="0,1"
position="78.156291,0"
id="guide2389" />
<sodipodi:guide
orientation="0,1"
position="60.863576,64.084768"
id="guide2391" />
<inkscape:grid
type="xygrid"
id="grid3672"
visible="true"
enabled="true"
empspacing="8"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Icon"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
transform="translate(0,-6)">
<path
style="color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -12,6 -1,3 2,0 -1,-3 z m -5.65625,2.34375 1.40625,2.8125 1.40625,-1.40625 -2.8125,-1.40625 z m 11.3125,0 L -9.15625,9.75 -7.75,11.15625 -6.34375,8.34375 z M -12,10 c -2.209139,0 -4,1.790861 -4,4 0,2.209139 1.790861,4 4,4 2.209139,0 4,-1.790861 4,-4 0,-2.209139 -1.790861,-4 -4,-4 z m 0,1.5 c 1.380712,0 2.5,1.119288 2.5,2.5 0,1.380712 -1.119288,2.5 -2.5,2.5 -1.380712,0 -2.5,-1.119288 -2.5,-2.5 0,-1.380712 1.119288,-2.5 2.5,-2.5 z m -5,1.5 -3,1 3,1 0,-2 z m 10,0 0,2 3,-1 -3,-1 z m -9.25,3.84375 -1.40625,2.8125 2.8125,-1.40625 -1.40625,-1.40625 z m 8.5,0 -1.40625,1.40625 2.8125,1.40625 L -7.75,16.84375 z M -13,19 l 1,3 1,-3 -2,0 z"
id="path3085"
inkscape:connector-curvature="0" />
<path
id="path3102"
d="m 8,30 c -2.209139,0 -4,1.790861 -4,4 0,2.209139 1.790861,4 4,4 2.209139,0 4,-1.790861 4,-4 0,-2.209139 -1.790861,-4 -4,-4 z m 0,2 c 1.1045695,0 2,0.89543 2,2 0,1.104569 -0.8954305,2 -2,2 -1.1045695,0 -2,-0.895431 -2,-2 0,-1.10457 0.8954305,-2 2,-2 z"
style="opacity:0.35;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
inkscape:transform-center-y="-6.5"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3104"
d="m 6,29 4,0 -2,-3 z"
style="fill:#808080;stroke:none" />
<path
inkscape:transform-center-y="-2.4999999"
inkscape:transform-center-x="-5.1291655"
style="fill:#808080;stroke:none"
d="m 11.330127,29.767949 2,3.464102 L 14.928204,30 z"
id="path3106"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3108"
d="m 13.330127,34.767949 -2,3.464102 L 14.928203,38 z"
style="fill:#808080;stroke:none"
inkscape:transform-center-x="-5.129165"
inkscape:transform-center-y="2.5" />
<path
inkscape:transform-center-y="6.5"
style="fill:#808080;stroke:none"
d="m 10,39 -4.0000002,0 2.0000001,3 z"
id="path3110"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
inkscape:transform-center-x="5.1291651"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3112"
d="M 4.6698729,38.232051 2.6698728,34.767949 1.0717967,38 z"
style="fill:#808080;stroke:none"
inkscape:transform-center-y="2.5" />
<path
inkscape:transform-center-y="-2.5"
style="fill:#808080;stroke:none"
d="M 2.6698727,33.232051 4.669873,29.767949 1.0717967,30 z"
id="path3114"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc"
inkscape:transform-center-x="5.129165" />
<path
style="color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 5.84375 0 L 5.09375 2.96875 L 2.15625 2.15625 L 2.96875 5.09375 L 0 5.84375 L 2.1875 8 L 0 10.15625 L 2.96875 10.90625 L 2.15625 13.84375 L 5.09375 13.03125 L 5.84375 16 L 8 13.8125 L 10.15625 16 L 10.90625 13.03125 L 13.84375 13.84375 L 13.03125 10.90625 L 16 10.15625 L 13.8125 8 L 16 5.84375 L 13.03125 5.09375 L 13.84375 2.15625 L 10.90625 2.96875 L 10.15625 0 L 8 2.1875 L 5.84375 0 z M 8 3 C 10.761424 3 13 5.2385763 13 8 C 13 10.761424 10.761424 13 8 13 L 8 3 z "
transform="translate(0,6)"
id="path3075" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,89 @@
# Calendar Widget
Calendar widget for Awesome WM - slightly improved version of the `wibox.widget.calendar`.
## Features
### Customization
| Name | Default | Description |
|---|---|---|
| theme | `naughty` | The theme to use |
| placement | `top` | The position of the popup |
| radius | 8 | The popup radius |
| start_sunday | false | Start the week on Sunday |
- themes:
| Name | Screenshot |
|---|---|
| nord | ![nord_theme](./nord.png) |
| outrun | ![outrun_theme](./outrun.png) |
| light | ![outrun_theme](./light.png) |
| dark | ![outrun_theme](./dark.png) |
| naughty (default) | from local theme |
- setup widget placement
top center - in case you clock is centered:
![calendar_top](./calendar_top.png)
top right - for default awesome config:
![calendar_top_right](./calendar_top_right.png)
bottom right - in case your wibar at the bottom:
![calendar_bottom_right](./calendar_bottom_right.png)
- setup first day of week
By setting `start_sunday` to true:
![calendar_start_sunday](./calendar_start_sunday.png)
- mouse support:
move to the next and previous month. Using mouse buttons or scroll wheel.
You can configure this by specifying the button to move to next/previous.
Usually these are configured as follows. If you want to use other mouse buttons, you can find their number using `xev`.
| number | button |
|--------|---------------|
| 4 | scroll up |
| 5 | scroll down |
| 1 | left click |
| 2 | right click |
| 3 | middles click |
By default `previous_month_button` is 5, `next_month_button` is 4.
## How to use
This widget needs an 'anchor' - another widget which triggers visibility of the calendar. Default `mytextclock` is the perfect candidate!
Just after mytextclock is instantiated, create the widget and add the mouse listener to it.
```lua
local calendar_widget = require("awesome-wm-widgets.calendar-widget.calendar")
-- ...
-- Create a textclock widget
mytextclock = wibox.widget.textclock()
-- default
local cw = calendar_widget()
-- or customized
local cw = calendar_widget({
theme = 'outrun',
placement = 'bottom_right',
start_sunday = true,
radius = 8,
-- with customized next/previous (see table above)
previous_month_button = 1,
next_month_button = 3,
})
mytextclock:connect_signal("button::press",
function(_, _, _, button)
if button == 1 then cw.toggle() end
end)
```

View File

@ -0,0 +1,253 @@
-------------------------------------------------
-- Calendar Widget for Awesome Window Manager
-- Shows the current month and supports scroll up/down to switch month
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/calendar-widget
-- @author Pavel Makhov
-- @copyright 2019 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local beautiful = require("beautiful")
local wibox = require("wibox")
local gears = require("gears")
local naughty = require("naughty")
local calendar_widget = {}
local function worker(user_args)
local calendar_themes = {
nord = {
bg = '#2E3440',
fg = '#D8DEE9',
focus_date_bg = '#88C0D0',
focus_date_fg = '#000000',
weekend_day_bg = '#3B4252',
weekday_fg = '#88C0D0',
header_fg = '#E5E9F0',
border = '#4C566A'
},
outrun = {
bg = '#0d0221',
fg = '#D8DEE9',
focus_date_bg = '#650d89',
focus_date_fg = '#2de6e2',
weekend_day_bg = '#261447',
weekday_fg = '#2de6e2',
header_fg = '#f6019d',
border = '#261447'
},
dark = {
bg = '#000000',
fg = '#ffffff',
focus_date_bg = '#ffffff',
focus_date_fg = '#000000',
weekend_day_bg = '#444444',
weekday_fg = '#ffffff',
header_fg = '#ffffff',
border = '#333333'
},
light = {
bg = '#ffffff',
fg = '#000000',
focus_date_bg = '#000000',
focus_date_fg = '#ffffff',
weekend_day_bg = '#AAAAAA',
weekday_fg = '#000000',
header_fg = '#000000',
border = '#CCCCCC'
},
monokai = {
bg = '#272822',
fg = '#F8F8F2',
focus_date_bg = '#AE81FF',
focus_date_fg = '#ffffff',
weekend_day_bg = '#75715E',
weekday_fg = '#FD971F',
header_fg = '#F92672',
border = '#75715E'
},
naughty = {
bg = beautiful.notification_bg or beautiful.bg,
fg = beautiful.notification_fg or beautiful.fg,
focus_date_bg = beautiful.notification_fg or beautiful.fg,
focus_date_fg = beautiful.notification_bg or beautiful.bg,
weekend_day_bg = beautiful.bg_focus,
weekday_fg = beautiful.fg,
header_fg = beautiful.fg,
border = beautiful.border_normal
}
}
local args = user_args or {}
if args.theme ~= nil and calendar_themes[args.theme] == nil then
naughty.notify({
preset = naughty.config.presets.critical,
title = 'Calendar Widget',
text = 'Theme "' .. args.theme .. '" not found, fallback to default'})
args.theme = 'naughty'
end
local theme = args.theme or 'naughty'
local placement = args.placement or 'top'
local radius = args.radius or 8
local next_month_button = args.next_month_button or 4
local previous_month_button = args.previous_month_button or 5
local start_sunday = args.start_sunday or false
local styles = {}
local function rounded_shape(size)
return function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, size)
end
end
styles.month = {
padding = 4,
bg_color = calendar_themes[theme].bg,
border_width = 0,
}
styles.normal = {
markup = function(t) return t end,
shape = rounded_shape(4)
}
styles.focus = {
fg_color = calendar_themes[theme].focus_date_fg,
bg_color = calendar_themes[theme].focus_date_bg,
markup = function(t) return '<b>' .. t .. '</b>' end,
shape = rounded_shape(4)
}
styles.header = {
fg_color = calendar_themes[theme].header_fg,
bg_color = calendar_themes[theme].bg,
markup = function(t) return '<b>' .. t .. '</b>' end
}
styles.weekday = {
fg_color = calendar_themes[theme].weekday_fg,
bg_color = calendar_themes[theme].bg,
markup = function(t) return '<b>' .. t .. '</b>' end,
}
local function decorate_cell(widget, flag, date)
if flag == 'monthheader' and not styles.monthheader then
flag = 'header'
end
-- highlight only today's day
if flag == 'focus' then
local today = os.date('*t')
if not (today.month == date.month and today.year == date.year) then
flag = 'normal'
end
end
local props = styles[flag] or {}
if props.markup and widget.get_text and widget.set_markup then
widget:set_markup(props.markup(widget:get_text()))
end
-- Change bg color for weekends
local d = { year = date.year, month = (date.month or 1), day = (date.day or 1) }
local weekday = tonumber(os.date('%w', os.time(d)))
local default_bg = (weekday == 0 or weekday == 6)
and calendar_themes[theme].weekend_day_bg
or calendar_themes[theme].bg
local ret = wibox.widget {
{
{
widget,
halign = 'center',
widget = wibox.container.place
},
margins = (props.padding or 2) + (props.border_width or 0),
widget = wibox.container.margin
},
shape = props.shape,
shape_border_color = props.border_color or '#000000',
shape_border_width = props.border_width or 0,
fg = props.fg_color or calendar_themes[theme].fg,
bg = props.bg_color or default_bg,
widget = wibox.container.background
}
return ret
end
local cal = wibox.widget {
date = os.date('*t'),
font = beautiful.get_font(),
fn_embed = decorate_cell,
long_weekdays = true,
start_sunday = start_sunday,
widget = wibox.widget.calendar.month
}
local popup = awful.popup {
ontop = true,
visible = false,
shape = rounded_shape(radius),
offset = { y = 5 },
border_width = 1,
border_color = calendar_themes[theme].border,
widget = cal
}
popup:buttons(
awful.util.table.join(
awful.button({}, next_month_button, function()
local a = cal:get_date()
a.month = a.month + 1
cal:set_date(nil)
cal:set_date(a)
popup:set_widget(cal)
end),
awful.button({}, previous_month_button, function()
local a = cal:get_date()
a.month = a.month - 1
cal:set_date(nil)
cal:set_date(a)
popup:set_widget(cal)
end)
)
)
function calendar_widget.toggle()
if popup.visible then
-- to faster render the calendar refresh it and just hide
cal:set_date(nil) -- the new date is not set without removing the old one
cal:set_date(os.date('*t'))
popup:set_widget(nil) -- just in case
popup:set_widget(cal)
popup.visible = not popup.visible
else
if placement == 'top' then
awful.placement.top(popup, { margins = { top = 30 }, parent = awful.screen.focused() })
elseif placement == 'top_right' then
awful.placement.top_right(popup, { margins = { top = 30, right = 10}, parent = awful.screen.focused() })
elseif placement == 'bottom_right' then
awful.placement.bottom_right(popup, { margins = { bottom = 30, right = 10},
parent = awful.screen.focused() })
else
awful.placement.top(popup, { margins = { top = 30 }, parent = awful.screen.focused() })
end
popup.visible = true
end
end
return calendar_widget
end
return setmetatable(calendar_widget, { __call = function(_, ...)
return worker(...)
end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -0,0 +1,51 @@
# Cmus widget
Cmus widget that shows the current playing track.
![widget](./screenshots/cmus-widget.png)
Left click toggles playback.
## Installation
Clone the repo under **~/.config/awesome/** and add widget in **rc.lua**:
```lua
local cmus_widget = require('awesome-wm-widgets.cmus-widget.cmus')
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
-- default
cmus_widget(),
-- customized
cmus_widget{
space = 5,
timeout = 5
},
```
### Shortcuts
To improve responsiveness of the widget when playback is changed by a shortcut use corresponding methods of the widget:
```lua
awful.key({ modkey, "Shift" },
"p",
function() cmus_widget:play_pause() end,
{description = "play/pause cmus", group = "custom"}),
```
## Customization
It is possible to customize the widget by providing a table with all or some of the following config parameters:
### Generic parameter
| Name | Default | Description |
|---|---|---|
| `font` | `Play 9` | Font used for the track title |
| `path_to_icons` | `/usr/share/icons/Arc/actions/symbolic/` | Alternative path for the icons |
| `timeout`| `10` | Refresh cooldown |
| `space` | `3` | Space between icon and track title |

View File

@ -0,0 +1,127 @@
-------------------------------------------------
-- Cmus Widget for Awesome Window Manager
-- Show what's playing, play/pause, etc
-- @author Augusto Gunsch
-- @copyright 2022 Augusto Gunsch
-------------------------------------------------
local awful = require("awful")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local cmus_widget = {}
local function show_warning(message)
naughty.notify{
preset = naughty.config.presets.critical,
title = "Cmus Widget",
text = message}
end
local function worker(user_args)
local args = user_args or {}
local font = args.font or "Play 9"
local path_to_icons = args.path_to_icons or "/usr/share/icons/Arc/actions/symbolic/"
local timeout = args.timeout or 10
local space = args.space or 3
cmus_widget.widget = wibox.widget {
{
{
id = "playback_icon",
resize = false,
widget = wibox.widget.imagebox,
},
layout = wibox.container.place
},
{
id = "text",
font = font,
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.horizontal,
update_icon = function(self, name)
self:get_children_by_id("playback_icon")[1]:set_image(path_to_icons .. name)
end,
set_title = function(self, title)
self:get_children_by_id("text")[1]:set_text(title)
end
}
function update_widget(widget, stdout, _, _, code)
if code == 0 then
local cmus_info = {}
for s in stdout:gmatch("[^\r\n]+") do
local key, val = string.match(s, "^tag (%a+) (.+)$")
if key and val then
cmus_info[key] = val
else
local key, val = string.match(s, "^set (%a+) (.+)$")
if key and val then
cmus_info[key] = val
else
local key, val = string.match(s, "^(%a+) (.+)$")
if key and val then
cmus_info[key] = val
end
end
end
end
local title = cmus_info.title
if not title and cmus_info.file then
title = cmus_info.file:gsub("%..-$", "")
title = title:gsub("^.+/", "")
end
if title then
if cmus_info["status"] == "playing" then
widget:update_icon("media-playback-start-symbolic.svg")
elseif cmus_info["status"] == "paused" then
widget:update_icon("media-playback-pause-symbolic.svg")
else
widget:update_icon("media-playback-stop-symbolic.svg")
end
widget:set_title(title)
widget.visible = true
else
widget.visible = false
widget.width = 0
end
else
widget.visible = false
end
end
function cmus_widget:play_pause()
spawn("cmus-remote -u")
spawn.easy_async("cmus-remote -Q",
function(stdout, _, _, code)
update_widget(cmus_widget.widget, stdout, _, _, code)
end)
end
cmus_widget.widget:buttons(
awful.util.table.join(
awful.button({}, 1, function() cmus_widget:play_pause() end)
)
)
watch("cmus-remote -Q", timeout, update_widget, cmus_widget.widget)
return cmus_widget.widget
end
return setmetatable(cmus_widget, { __call = function(_, ...)
return worker(...)
end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -0,0 +1,71 @@
# CPU widget
[![GitHub issues by-label](https://img.shields.io/github/issues-raw/streetturtle/awesome-wm-widgets/cpu)](https://github.com/streetturtle/awesome-wm-widgets/labels/cpu)
This widget shows the average CPU load among all cores of the machine:
![screenshot](./cpu.gif)
## How it works
To measure the load I took Paul Colby's bash [script](http://colby.id.au/calculating-cpu-usage-from-proc-stat/) and rewrote it in Lua, which was quite simple.
So awesome simply reads the first line of /proc/stat:
```bash
$ cat /proc/stat | grep '^cpu '
cpu 197294 718 50102 2002182 3844 0 2724 0 0 0
```
and calculates the percentage.
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `width` | 50 | Width of the widget |
| `step_width` | 2 | Width of the step |
| `step_spacing` | 1 | Space size between steps |
| `color` | `beautiful.fg_normal` | Color of the graph |
| `enable_kill_button` | `false` | Show button which kills the process |
| `process_info_max_length` | `-1` | Truncate the process information. Some processes may have a very long list of parameters which won't fit in the screen, this options allows to truncate it to the given length. |
| `timeout` | 1 | How often in seconds the widget refreshes |
### Example
```lua
cpu_widget({
width = 70,
step_width = 2,
step_spacing = 0,
color = '#434c5e'
})
```
The config above results in the following widget:
![custom](./custom.png)
## Installation
Clone/download repo and use widget in **rc.lua**:
```lua
local cpu_widget = require("awesome-wm-widgets.cpu-widget.cpu-widget")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
-- default
cpu_widget(),
-- or custom
cpu_widget({
width = 70,
step_width = 2,
step_spacing = 0,
color = '#434c5e'
})
...
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -0,0 +1,339 @@
-------------------------------------------------
-- CPU Widget for Awesome Window Manager
-- Shows the current CPU utilization
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/cpu-widget
-- @author Pavel Makhov
-- @copyright 2020 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local watch = require("awful.widget.watch")
local wibox = require("wibox")
local beautiful = require("beautiful")
local gears = require("gears")
local CMD = [[sh -c "grep '^cpu.' /proc/stat; ps -eo '%p|%c|%C|' -o "%mem" -o '|%a' --sort=-%cpu ]]
.. [[| head -11 | tail -n +2"]]
-- A smaller command, less resource intensive, used when popup is not shown.
local CMD_slim = [[grep --max-count=1 '^cpu.' /proc/stat]]
local HOME_DIR = os.getenv("HOME")
local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/cpu-widget'
local cpu_widget = {}
local cpu_rows = {
spacing = 4,
layout = wibox.layout.fixed.vertical,
}
local is_update = true
local process_rows = {
layout = wibox.layout.fixed.vertical,
}
-- Splits the string by separator
-- @return table with separated substrings
local function split(string_to_split, separator)
if separator == nil then separator = "%s" end
local t = {}
for str in string.gmatch(string_to_split, "([^".. separator .."]+)") do
table.insert(t, str)
end
return t
end
-- Checks if a string starts with a another string
local function starts_with(str, start)
return str:sub(1, #start) == start
end
local function create_textbox(args)
return wibox.widget{
text = args.text,
align = args.align or 'left',
markup = args.markup,
forced_width = args.forced_width or 40,
widget = wibox.widget.textbox
}
end
local function create_process_header(params)
local res = wibox.widget{
create_textbox{markup = '<b>PID</b>'},
create_textbox{markup = '<b>Name</b>'},
{
create_textbox{markup = '<b>%CPU</b>'},
create_textbox{markup = '<b>%MEM</b>'},
params.with_action_column and create_textbox{forced_width = 20} or nil,
layout = wibox.layout.align.horizontal
},
layout = wibox.layout.ratio.horizontal
}
res:ajust_ratio(2, 0.2, 0.47, 0.33)
return res
end
local function create_kill_process_button()
return wibox.widget{
{
id = "icon",
image = WIDGET_DIR .. '/window-close-symbolic.svg',
resize = false,
opacity = 0.1,
widget = wibox.widget.imagebox
},
widget = wibox.container.background
}
end
local function worker(user_args)
local args = user_args or {}
local width = args.width or 50
local step_width = args.step_width or 2
local step_spacing = args.step_spacing or 1
local color = args.color or beautiful.fg_normal
local background_color = args.background_color or "#00000000"
local enable_kill_button = args.enable_kill_button or false
local process_info_max_length = args.process_info_max_length or -1
local timeout = args.timeout or 1
local cpugraph_widget = wibox.widget {
max_value = 100,
background_color = background_color,
forced_width = width,
step_width = step_width,
step_spacing = step_spacing,
widget = wibox.widget.graph,
color = "linear:0,0:0,20:0,#FF0000:0.3,#FFFF00:0.6," .. color
}
-- This timer periodically executes the heavy command while the popup is open.
-- It is stopped when the popup is closed and only the slim command is run then.
-- This greatly improves performance while the popup is closed at the small cost
-- of a slightly longer popup opening time.
local popup_timer = gears.timer {
timeout = timeout
}
local popup = awful.popup{
ontop = true,
visible = false,
shape = gears.shape.rounded_rect,
border_width = 1,
border_color = beautiful.bg_normal,
maximum_width = 300,
offset = { y = 5 },
widget = {}
}
-- Do not update process rows when mouse cursor is over the widget
popup:connect_signal("mouse::enter", function() is_update = false end)
popup:connect_signal("mouse::leave", function() is_update = true end)
cpugraph_widget:buttons(
awful.util.table.join(
awful.button({}, 1, function()
if popup.visible then
popup.visible = not popup.visible
-- When the popup is not visible, stop the timer
popup_timer:stop()
else
popup:move_next_to(mouse.current_widget_geometry)
-- Restart the timer, when the popup becomes visible
-- Emit the signal to start the timer directly and not wait the timeout first
popup_timer:start()
popup_timer:emit_signal("timeout")
end
end)
)
)
--- By default graph widget goes from left to right, so we mirror it and push up a bit
cpu_widget = wibox.widget {
{
cpugraph_widget,
reflection = {horizontal = true},
layout = wibox.container.mirror
},
bottom = 2,
color = background_color,
widget = wibox.container.margin
}
-- This part runs constantly, also when the popup is closed.
-- It updates the graph widget in the bar.
local maincpu = {}
watch(CMD_slim, timeout, function(widget, stdout)
local _, user, nice, system, idle, iowait, irq, softirq, steal, _, _ =
stdout:match('(%w+)%s+(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)')
local total = user + nice + system + idle + iowait + irq + softirq + steal
local diff_idle = idle - tonumber(maincpu['idle_prev'] == nil and 0 or maincpu['idle_prev'])
local diff_total = total - tonumber(maincpu['total_prev'] == nil and 0 or maincpu['total_prev'])
local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10
maincpu['total_prev'] = total
maincpu['idle_prev'] = idle
widget:add_value(diff_usage)
end,
cpugraph_widget
)
-- This part runs whenever the timer is fired.
-- It therefore only runs when the popup is open.
local cpus = {}
popup_timer:connect_signal('timeout', function()
awful.spawn.easy_async(CMD, function(stdout, _, _, _)
local i = 1
local j = 1
for line in stdout:gmatch("[^\r\n]+") do
if starts_with(line, 'cpu') then
if cpus[i] == nil then cpus[i] = {} end
local name, user, nice, system, idle, iowait, irq, softirq, steal, _, _ =
line:match('(%w+)%s+(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)')
local total = user + nice + system + idle + iowait + irq + softirq + steal
local diff_idle = idle - tonumber(cpus[i]['idle_prev'] == nil and 0 or cpus[i]['idle_prev'])
local diff_total = total - tonumber(cpus[i]['total_prev'] == nil and 0 or cpus[i]['total_prev'])
local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10
cpus[i]['total_prev'] = total
cpus[i]['idle_prev'] = idle
local row = wibox.widget
{
create_textbox{text = name},
create_textbox{text = math.floor(diff_usage) .. '%'},
{
max_value = 100,
value = diff_usage,
forced_height = 20,
forced_width = 150,
paddings = 1,
margins = 4,
border_width = 1,
border_color = beautiful.bg_focus,
background_color = beautiful.bg_normal,
bar_border_width = 1,
bar_border_color = beautiful.bg_focus,
color = "linear:150,0:0,0:0,#D08770:0.3,#BF616A:0.6," .. beautiful.fg_normal,
widget = wibox.widget.progressbar,
},
layout = wibox.layout.ratio.horizontal
}
row:ajust_ratio(2, 0.15, 0.15, 0.7)
cpu_rows[i] = row
i = i + 1
else
if is_update == true then
local columns = split(line, '|')
local pid = columns[1]
local comm = columns[2]
local cpu = columns[3]
local mem = columns[4]
local cmd = columns[5]
local kill_proccess_button = enable_kill_button and create_kill_process_button() or nil
local pid_name_rest = wibox.widget{
create_textbox{text = pid},
create_textbox{text = comm},
{
create_textbox{text = cpu, align = 'center'},
create_textbox{text = mem, align = 'center'},
kill_proccess_button,
layout = wibox.layout.fixed.horizontal
},
layout = wibox.layout.ratio.horizontal
}
pid_name_rest:ajust_ratio(2, 0.2, 0.47, 0.33)
local row = wibox.widget {
{
pid_name_rest,
top = 4,
bottom = 4,
widget = wibox.container.margin
},
widget = wibox.container.background
}
row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end)
row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end)
if enable_kill_button then
row:connect_signal("mouse::enter", function() kill_proccess_button.icon.opacity = 1 end)
row:connect_signal("mouse::leave", function() kill_proccess_button.icon.opacity = 0.1 end)
kill_proccess_button:buttons(
awful.util.table.join( awful.button({}, 1, function()
row:set_bg('#ff0000')
awful.spawn.with_shell('kill -9 ' .. pid)
end) ) )
end
awful.tooltip {
objects = { row },
mode = 'outside',
preferred_positions = {'bottom'},
timer_function = function()
local text = cmd
if process_info_max_length > 0 and text:len() > process_info_max_length then
text = text:sub(0, process_info_max_length - 3) .. '...'
end
return text
:gsub('%s%-', '\n\t-') -- put arguments on a new line
:gsub(':/', '\n\t\t:/') -- java classpath uses : to separate jars
end,
}
process_rows[j] = row
j = j + 1
end
end
end
popup:setup {
{
cpu_rows,
{
orientation = 'horizontal',
forced_height = 15,
color = beautiful.bg_focus,
widget = wibox.widget.separator
},
create_process_header{with_action_column = enable_kill_button},
process_rows,
layout = wibox.layout.fixed.vertical,
},
margins = 8,
widget = wibox.container.margin
}
end)
end)
return cpu_widget
end
return setmetatable(cpu_widget, { __call = function(_, ...)
return worker(...)
end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg7384"
version="1.1"
height="16"
width="16"
inkscape:version="0.48.5 r10040"
sodipodi:docname="window-close-symbolic.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="723"
id="namedview15"
showgrid="true"
inkscape:zoom="14.75"
inkscape:cx="14.600061"
inkscape:cy="10.005214"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="1"
inkscape:current-layer="svg7384">
<inkscape:grid
type="xygrid"
id="grid2992" />
</sodipodi:namedview>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7386" />
<g
transform="translate(-60,-518)"
id="layer9"
style="display:inline" />
<g
transform="translate(-60,-518)"
id="layer10" />
<g
transform="translate(-60,-518)"
id="layer11" />
<g
id="g2996"
transform="matrix(0.75,0,0,0.75,2,2.0546875)">
<g
id="layer12"
transform="translate(-60,-518)">
<g
style="display:inline"
id="layer4-4-1"
transform="translate(19,-242)">
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#bebebe;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.78124988;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Andale Mono;-inkscape-font-specification:Andale Mono"
id="path10839-9"
d="m 45,764 1,0 c 0.01037,-1.2e-4 0.02079,-4.6e-4 0.03125,0 0.254951,0.0112 0.50987,0.12858 0.6875,0.3125 L 49,766.59375 51.3125,764.3125 C 51.578125,764.082 51.759172,764.007 52,764 l 1,0 0,1 c 0,0.28647 -0.03434,0.55065 -0.25,0.75 l -2.28125,2.28125 2.25,2.25 C 52.906938,770.46942 52.999992,770.7347 53,771 l 0,1 -1,0 c -0.265301,-10e-6 -0.530586,-0.0931 -0.71875,-0.28125 L 49,769.4375 46.71875,771.71875 C 46.530586,771.90694 46.26529,772 46,772 l -1,0 0,-1 c -3e-6,-0.26529 0.09306,-0.53058 0.28125,-0.71875 l 2.28125,-2.25 L 45.28125,765.75 C 45.070508,765.55537 44.97809,765.28075 45,765 l 0,-1 z"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
<g
transform="translate(-60,-518)"
id="layer13" />
<g
transform="translate(-60,-518)"
id="layer14" />
<g
transform="translate(-60,-518)"
id="layer15" />
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,38 @@
# Docker Widget
[![GitHub issues by-label](https://img.shields.io/github/issues-raw/streetturtle/awesome-wm-widgets/docker)](https://github.com/streetturtle/awesome-wm-widgets/labels/docker)
![Twitter URL](https://img.shields.io/twitter/url?url=https%3A%2F%2Fgithub.com%2Fstreetturtle%2Fawesome-wm-widgets%2Fedit%2Fmaster%2Fdocker-widget)
The widget allows to manage docker containers, namely start/stop/pause/unpause:
<p align="center">
<img src="https://github.com/streetturtle/awesome-wm-widgets/raw/master/docker-widget/docker.gif"/>
</p>
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `icon` | `./docker-widget/icons/docker.svg` | Path to the icon |
| `number_of_containers` | `-1` | Number of last created containers to show |
## Installation
Clone the repo under **~/.config/awesome/** and add widget in **rc.lua**:
```lua
local docker_widget = require("awesome-wm-widgets.docker-widget.docker")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
-- default
docker_widget(),
-- customized
docker_widget{
number_of_containers = 5
},
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 KiB

View File

@ -0,0 +1,377 @@
-------------------------------------------------
-- Docker Widget for Awesome Window Manager
-- Lists containers and allows to manage them
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/docker-widget
-- @author Pavel Makhov
-- @copyright 2020 Pavel Makhov
-------------------------------------------------
local awful = require("awful")
local wibox = require("wibox")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
local HOME_DIR = os.getenv("HOME")
local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/docker-widget'
local ICONS_DIR = WIDGET_DIR .. '/icons/'
local LIST_CONTAINERS_CMD = [[bash -c "docker container ls -a -s -n %s]]
.. [[ --format '{{.Names}}::{{.ID}}::{{.Image}}::{{.Status}}::{{.Size}}'"]]
--- Utility function to show warning messages
local function show_warning(message)
naughty.notify{
preset = naughty.config.presets.critical,
title = 'Docker Widget',
text = message}
end
local popup = awful.popup{
ontop = true,
visible = false,
shape = gears.shape.rounded_rect,
border_width = 1,
border_color = beautiful.bg_focus,
maximum_width = 400,
offset = { y = 5 },
widget = {}
}
local docker_widget = wibox.widget {
{
{
id = 'icon',
widget = wibox.widget.imagebox
},
margins = 4,
layout = wibox.container.margin
},
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 4)
end,
widget = wibox.container.background,
set_icon = function(self, new_icon)
self:get_children_by_id("icon")[1].image = new_icon
end
}
local parse_container = function(line)
local name, id, image, status, how_long, size = line:match('(.*)::(.*)::(.*)::(%w*) (.*)::(.*)')
local actual_status
if status == 'Up' and how_long:find('Paused') then actual_status = 'Paused'
else actual_status = status end
how_long = how_long:gsub('%s?%(.*%)%s?', '')
local container = {
name = name,
id = id,
image = image,
status = actual_status,
how_long = how_long,
size = size,
is_up = function() return status == 'Up' end,
is_paused = function() return actual_status:find('Paused') end,
is_exited = function() return status == 'Exited' end
}
return container
end
local status_to_icon_name = {
Up = ICONS_DIR .. 'play.svg',
Exited = ICONS_DIR .. 'square.svg',
Paused = ICONS_DIR .. 'pause.svg'
}
local function worker(user_args)
local args = user_args or {}
local icon = args.icon or ICONS_DIR .. 'docker.svg'
local number_of_containers = args.number_of_containers or -1
docker_widget:set_icon(icon)
local rows = {
{ widget = wibox.widget.textbox },
layout = wibox.layout.fixed.vertical,
}
local function rebuild_widget(containers, errors, _, _)
if errors ~= '' then
show_warning(errors)
return
end
for i = 0, #rows do rows[i]=nil end
for line in containers:gmatch("[^\r\n]+") do
local container = parse_container(line)
local status_icon = wibox.widget {
image = status_to_icon_name[container['status']],
resize = false,
widget = wibox.widget.imagebox
}
local start_stop_button
if container.is_up() or container.is_exited() then
start_stop_button = wibox.widget {
{
{
id = 'icon',
image = ICONS_DIR .. (container:is_up() and 'stop-btn.svg' or 'play-btn.svg'),
opacity = 0.4,
resize = false,
widget = wibox.widget.imagebox
},
left = 2,
right = 2,
layout = wibox.container.margin
},
shape = gears.shape.circle,
bg = '#00000000',
widget = wibox.container.background
}
local old_cursor, old_wibox
start_stop_button:connect_signal("mouse::enter", function(c)
c:set_bg('#3B4252')
local wb = mouse.current_wibox
old_cursor, old_wibox = wb.cursor, wb
wb.cursor = "hand1"
c:get_children_by_id("icon")[1]:set_opacity(1)
c:get_children_by_id("icon")[1]:emit_signal('widget::redraw_needed') end)
start_stop_button:connect_signal("mouse::leave", function(c)
c:set_bg('#00000000')
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
c:get_children_by_id("icon")[1]:set_opacity(0.4)
c:get_children_by_id("icon")[1]:emit_signal('widget::redraw_needed')
end)
start_stop_button:buttons(
gears.table.join( awful.button({}, 1, function()
local command
if container:is_up() then command = 'stop' else command = 'start' end
status_icon:set_opacity(0.2)
status_icon:emit_signal('widget::redraw_needed')
spawn.easy_async('docker ' .. command .. ' ' .. container['name'], function()
if errors ~= '' then show_warning(errors) end
spawn.easy_async(string.format(LIST_CONTAINERS_CMD, number_of_containers),
function(stdout, stderr)
rebuild_widget(stdout, stderr)
end)
end)
end) ) )
else
start_stop_button = nil
end
local pause_unpause_button
if container.is_up() then
pause_unpause_button = wibox.widget {
{
{
id = 'icon',
image = ICONS_DIR .. (container:is_paused() and 'unpause-btn.svg' or 'pause-btn.svg'),
opacity = 0.4,
resize = false,
widget = wibox.widget.imagebox
},
left = 2,
right = 2,
layout = wibox.container.margin
},
shape = gears.shape.circle,
bg = '#00000000',
widget = wibox.container.background
}
local old_cursor, old_wibox
pause_unpause_button:connect_signal("mouse::enter", function(c)
c:set_bg('#3B4252')
local wb = mouse.current_wibox
old_cursor, old_wibox = wb.cursor, wb
wb.cursor = "hand1"
c:get_children_by_id("icon")[1]:set_opacity(1)
c:get_children_by_id("icon")[1]:emit_signal('widget::redraw_needed')
end)
pause_unpause_button:connect_signal("mouse::leave", function(c)
c:set_bg('#00000000')
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
c:get_children_by_id("icon")[1]:set_opacity(0.4)
c:get_children_by_id("icon")[1]:emit_signal('widget::redraw_needed')
end)
pause_unpause_button:buttons(
gears.table.join( awful.button({}, 1, function()
local command
if container:is_paused() then command = 'unpause' else command = 'pause' end
status_icon:set_opacity(0.2)
status_icon:emit_signal('widget::redraw_needed')
awful.spawn.easy_async('docker ' .. command .. ' ' .. container['name'], function(_, stderr)
if stderr ~= '' then show_warning(stderr) end
spawn.easy_async(string.format(LIST_CONTAINERS_CMD, number_of_containers),
function(stdout, container_errors)
rebuild_widget(stdout, container_errors)
end)
end)
end) ) )
else
pause_unpause_button = nil
end
local delete_button
if not container.is_up() then
delete_button = wibox.widget {
{
{
id = 'icon',
image = ICONS_DIR .. 'trash-btn.svg',
opacity = 0.4,
resize = false,
widget = wibox.widget.imagebox
},
margins = 4,
layout = wibox.container.margin
},
shape = gears.shape.circle,
bg = '#00000000',
widget = wibox.container.background
}
delete_button:buttons(
gears.table.join( awful.button({}, 1, function()
awful.spawn.easy_async('docker rm ' .. container['name'], function(_, rm_stderr)
if rm_stderr ~= '' then show_warning(rm_stderr) end
spawn.easy_async(string.format(LIST_CONTAINERS_CMD, number_of_containers),
function(lc_stdout, lc_stderr)
rebuild_widget(lc_stdout, lc_stderr) end)
end)
end)))
local old_cursor, old_wibox
delete_button:connect_signal("mouse::enter", function(c)
c:set_bg('#3B4252')
local wb = mouse.current_wibox
old_cursor, old_wibox = wb.cursor, wb
wb.cursor = "hand1"
c:get_children_by_id("icon")[1]:set_opacity(1)
c:get_children_by_id("icon")[1]:emit_signal('widget::redraw_needed')
end)
delete_button:connect_signal("mouse::leave", function(c)
c:set_bg('#00000000')
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
c:get_children_by_id("icon")[1]:set_opacity(0.4)
c:get_children_by_id("icon")[1]:emit_signal('widget::redraw_needed')
end)
else
delete_button = nil
end
local row = wibox.widget {
{
{
{
{
status_icon,
margins = 8,
layout = wibox.container.margin
},
valign = 'center',
layout = wibox.container.place
},
{
{
{
markup = '<b>' .. container['name'] .. '</b>',
widget = wibox.widget.textbox
},
{
text = container['size'],
widget = wibox.widget.textbox
},
{
text = container['how_long'],
widget = wibox.widget.textbox
},
forced_width = 180,
layout = wibox.layout.fixed.vertical
},
valign = 'center',
layout = wibox.container.place
},
{
{
start_stop_button,
pause_unpause_button,
delete_button,
layout = wibox.layout.align.horizontal
},
forced_width = 90,
valign = 'center',
haligh = 'center',
layout = wibox.container.place,
},
spacing = 8,
layout = wibox.layout.align.horizontal
},
margins = 8,
layout = wibox.container.margin
},
bg = beautiful.bg_normal,
widget = wibox.container.background
}
row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end)
row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end)
table.insert(rows, row)
end
popup:setup(rows)
end
docker_widget:buttons(
gears.table.join(
awful.button({}, 1, function()
if popup.visible then
docker_widget:set_bg('#00000000')
popup.visible = not popup.visible
else
docker_widget:set_bg(beautiful.bg_focus)
spawn.easy_async(string.format(LIST_CONTAINERS_CMD, number_of_containers),
function(stdout, stderr)
rebuild_widget(stdout, stderr)
popup:move_next_to(mouse.current_widget_geometry)
end)
end
end)
)
)
return docker_widget
end
return setmetatable(docker_widget, { __call = function(_, ...) return worker(...) end })

View File

@ -0,0 +1 @@
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>Docker icon</title><path fill="#D8DEE9" d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,10 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M11 7H8V17H11V7Z" fill="#D8DEE9" />
<path d="M13 17H16V7H13V17Z" fill="#D8DEE9" />
</svg>

After

Width:  |  Height:  |  Size: 209 B

View File

@ -0,0 +1,16 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M9 9H11V15H9V9Z" fill="#EBCB8B" />
<path d="M15 15H13V9H15V15Z" fill="#EBCB8B" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12ZM21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
fill="#EBCB8B"
/>
</svg>

After

Width:  |  Height:  |  Size: 523 B

View File

@ -0,0 +1,9 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M9 17L17 12L9 7V17Z" fill="#D8DEE9" />
</svg>

After

Width:  |  Height:  |  Size: 163 B

View File

@ -0,0 +1,9 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M15 12.3301L9 16.6603L9 8L15 12.3301Z" fill="#D8DEE9" />
</svg>

After

Width:  |  Height:  |  Size: 181 B

View File

@ -0,0 +1,15 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23Z"
fill="#A3BE8C"
/>
<path d="M16 12L10 16.3301V7.66987L16 12Z" fill="#A3BE8C" />
</svg>

After

Width:  |  Height:  |  Size: 491 B

View File

@ -0,0 +1,15 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M15 9H9V15H15V9Z" fill="#BF616A" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12ZM21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
fill="#BF616A"
/>
</svg>

After

Width:  |  Height:  |  Size: 475 B

View File

@ -0,0 +1,10 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M7 7H17V17H7V7Z" fill="#D8DEE9" />
</svg>

After

Width:  |  Height:  |  Size: 161 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#BF616A" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-trash-2"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>

After

Width:  |  Height:  |  Size: 443 B

View File

@ -0,0 +1,10 @@
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M6 17L14 12L6 7V17Z" fill="#D8DEE9" />
<path d="M18 7H15V12V17H18V7Z" fill="#D8DEE9" />
</svg>

After

Width:  |  Height:  |  Size: 214 B

View File

@ -0,0 +1,36 @@
# Email widget
This widget consists of an icon with counter which shows number of unread emails: ![email icon](./em-wid-1.png)
and a popup message which appears when mouse hovers over an icon: ![email popup](./em-wid-2.png)
Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder.
## Installation
To install it put **email.lua** and **email-widget** folder under **~/.config/awesome**. Then
- in **email.lua** change path to python scripts;
- in python scripts add your credentials (note that password should be encrypted using pgp for example);
- add widget to awesome:
```lua
local email_widget, email_icon = require("email")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
email_icon,
email_widget,
...
```
## How it works
This widget uses the output of two python scripts, first is called every 20 seconds - it returns number of unread emails and second is called when mouse hovers over an icon and displays content of those emails. For both of them you'll need to provide your credentials and imap server. For testing, they can simply be called from console:
``` bash
python ~/.config/awesome/email/count_unread_emails.py
python ~/.config/awesome/email/read_emails.py
```

View File

@ -0,0 +1,16 @@
#!/usr/bin/python
import imaplib
import re
M=imaplib.IMAP4_SSL("mail.teenagemutantninjaturtles.com", 993)
M.login("mickey@tmnt.com","cowabunga")
status, counts = M.status("INBOX","(MESSAGES UNSEEN)")
if status == "OK":
unread = re.search(r'UNSEEN\s(\d+)', counts[0].decode('utf-8')).group(1)
else:
unread = "N/A"
print(unread)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,44 @@
local wibox = require("wibox")
local awful = require("awful")
local naughty = require("naughty")
local watch = require("awful.widget.watch")
local path_to_icons = "/usr/share/icons/Arc/actions/22/"
local email_widget = wibox.widget.textbox()
email_widget:set_font('Play 9')
local email_icon = wibox.widget.imagebox()
email_icon:set_image(path_to_icons .. "/mail-mark-new.png")
watch(
"python /home/<username>/.config/awesome/email-widget/count_unread_emails.py", 20,
function(_, stdout)
local unread_emails_num = tonumber(stdout) or 0
if (unread_emails_num > 0) then
email_icon:set_image(path_to_icons .. "/mail-mark-unread.png")
email_widget:set_text(stdout)
elseif (unread_emails_num == 0) then
email_icon:set_image(path_to_icons .. "/mail-message-new.png")
email_widget:set_text("")
end
end
)
local function show_emails()
awful.spawn.easy_async([[bash -c 'python /home/<username>/.config/awesome/email-widget/read_unread_emails.py']],
function(stdout)
naughty.notify{
text = stdout,
title = "Unread Emails",
timeout = 5, hover_timeout = 0.5,
width = 400,
}
end
)
end
email_icon:connect_signal("mouse::enter", function() show_emails() end)
return email_widget, email_icon

View File

@ -0,0 +1,44 @@
#!/usr/bin/python
import imaplib
import email
import datetime
def process_mailbox(M):
rv, data = M.search(None, "(UNSEEN)")
if rv != 'OK':
print "No messages found!"
return
for num in data[0].split():
rv, data = M.fetch(num, '(BODY.PEEK[])')
if rv != 'OK':
print "ERROR getting message", num
return
msg = email.message_from_bytes(data[0][1])
for header in [ 'From', 'Subject', 'Date' ]:
hdr = email.header.make_header(email.header.decode_header(msg[header]))
if header == 'Date':
date_tuple = email.utils.parsedate_tz(str(hdr))
if date_tuple:
local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
print("{}: {}".format(header, local_date.strftime("%a, %d %b %Y %H:%M:%S")))
else:
print('{}: {}'.format(header, hdr))
# with code below you can process text of email
# if msg.is_multipart():
# for payload in msg.get_payload():
# if payload.get_content_maintype() == 'text':
# print payload.get_payload()
# else:
# print msg.get_payload()
M=imaplib.IMAP4_SSL("mail.teenagemutantninjaturtles.com", 993)
M.login("mickey@tmnt.com","cowabunga")
rv, data = M.select("INBOX")
if rv == 'OK':
process_mailbox(M)
M.close()
M.logout()

View File

@ -0,0 +1,5 @@
# Spotify Player
In progress
![spotify-player](./spotify-player.png)

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" version="1.1">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="m 12,4 c -4.4182999,0 -7.9999999,3.5816996 -7.9999999,8 0,4.4183 3.5817,8 7.9999999,8 4.4183,0 8,-3.5817 8,-8 0,-4.4183004 -3.5817,-8 -8,-8 z m -1.484375,4.001953 c 0.135577,-0.0025 0.273043,-0.00125 0.40625,0 3.196934,0.043793 5.685547,1.3710939 5.685547,1.3710939 0.32387,0.1720431 0.478757,0.6868991 0.34375,1.0996091 -0.135016,0.41271 -0.551129,0.642746 -0.875,0.470703 0,0 -4.055029,-2.1406733 -8.1835939,-0.824218 -0.347652,0.145366 -0.785915,-0.135667 -0.875,-0.587891 -0.08907,-0.452224 0.170933,-0.9774967 0.53125,-1.0585939 1.017797,-0.3245495 2.017773,-0.4508522 2.9667969,-0.4707031 z m 0.435547,3 c 0.112731,-10e-4 0.212326,-0.0042 0.322266,0 2.638513,0.09188 4.466796,1.550781 4.466796,1.550781 0.234052,0.185402 0.328171,0.661373 0.207032,1.019532 -0.121139,0.358115 -0.441752,0.53892 -0.675782,0.353515 0,0 -2.907877,-2.344468 -6.6425779,-0.974609 -0.262497,0.124051 -0.553359,-0.122359 -0.617187,-0.53125 -0.06386,-0.40893 0.141317,-0.858788 0.412109,-0.929688 0.897365,-0.329138 1.7382149,-0.481181 2.5273439,-0.488281 z M 11.265625,14 c 1.291618,0.02495 2.442203,0.50401 3.542969,1.154297 0.164454,0.107427 0.243604,0.411344 0.152344,0.628906 -0.09126,0.217545 -0.337279,0.284734 -0.486329,0.140625 0,0 -2.036051,-1.658526 -5.0566399,-0.734375 -0.17338,0.07498 -0.372018,-0.06945 -0.41211,-0.314453 -0.04008,-0.245057 0.10336,-0.525057 0.283204,-0.560547 C 9.9993371,14.09714 10.660752,13.996 11.265625,14 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,192 @@
-------------------------------------------------
-- Spotify Player Widget for Awesome Window Manager
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/spotify-player
-- @author Pavel Makhov
-- @copyright 2021 Pavel Makhov
-------------------------------------------------
--luacheck:ignore
local awful = require("awful")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
local gfs = require("gears.filesystem")
local gs = require("gears.string")
local awesomebuttons = require("awesome-buttons.awesome-buttons")
local HOME_DIR = os.getenv("HOME")
local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/experiments/spotify-player/'
local ICON_DIR = WIDGET_DIR
local spotify_player = {}
local function show_warning(message)
naughty.notify{
preset = naughty.config.presets.critical,
title = 'Spotify Player Widget',
text = message}
end
local function worker(user_args)
local args = user_args or {}
local artwork_size = args.artwork_size or 300
local timeout = args.timeout or 1
local popup = awful.popup{
ontop = true,
bg = beautiful.bg_normal .. '88',
visible = false,
shape = gears.shape.rounded_rect,
border_width = 1,
border_color = beautiful.bg_focus,
width = artwork_size,
maximum_width = 300,
offset = { y = 5 },
widget = {}
}
local rows = {
expand = 'none',
layout = wibox.layout.align.vertical,
}
spotify_player.widget = wibox.widget {
image = ICON_DIR .. 'spotify-indicator.svg',
widget = wibox.widget.imagebox
}
local artwork_widget = wibox.widget {
forced_height = artwork_size,
forced_width = artwork_size,
widget = wibox.widget.imagebox
}
local artist_w = wibox.widget {
align = 'center',
widget = wibox.widget.textbox,
set_artist = function(self, artist)
self:set_markup('<span size="large" color="#ffffff">' .. artist .. '</span>')
end
}
local title_w = wibox.widget {
align = 'center',
forced_height = 30,
widget = wibox.widget.textbox,
set_title = function(self, title)
self:set_markup('<span size="x-large" font_weight="bold" color="#ffffff">' .. title .. '</span>')
end
}
local play_pause_btn = awesomebuttons.with_icon{ type = 'outline', icon = 'play', icon_size = 32, icon_margin = 8, color = '#1DB954', shape = 'circle', onclick = function()
spawn.with_shell('sp play')
end}
local buttons_w = wibox.widget {
{
awesomebuttons.with_icon{ icon = 'rewind', icon_size = 32, icon_margin = 8, color = '#18800000', shape = 'circle', onclick = function()
spawn.with_shell('sp prev')
end},
play_pause_btn,
awesomebuttons.with_icon{ icon = 'fast-forward', icon_size = 32, icon_margin = 8, color = '#18800000', shape = 'circle', onclick = function()
spawn.with_shell('sp next')
end},
spacing = 16,
layout = wibox.layout.fixed.horizontal
},
halign = 'center',
layout = wibox.container.place,
}
local some_w = wibox.widget {
artwork_widget,
{
{
{
{
title_w,
artist_w,
buttons_w,
layout = wibox.layout.fixed.vertical
},
top = 8,
bottom = 8,
widget = wibox.container.margin
},
bg = '#33333388',
widget = wibox.container.background
},
valign = 'bottom',
content_fill_horizontal = true,
layout = wibox.container.place,
},
layout = wibox.layout.stack
}
popup:setup({
some_w,
layout = wibox.layout.fixed.vertical,
})
local update_widget = function(widget, stdout, stderr, _, _)
for i = 0, #rows do rows[i]=nil end
if string.find(stdout, 'Error: Spotify is not running.') ~= nil then
return
end
local track_id, length, art_url, album, album_artist, artist, auto_rating, disc_number, title, track_number, url =
string.match(stdout, 'trackid|(.*)\nlength|(.*)\nartUrl|(.*)\nalbum|(.*)\nalbumArtist|(.*)\nartist|(.*)\nautoRating|(.*)\ndiscNumber|(.*)\ntitle|(.*)\ntrackNumber|(.*)\nurl|(.*)')
title = string.gsub(title, "&", '&amp;')
artist_w:set_artist(artist)
title_w:set_title(title)
-- spotify client bug: https://community.spotify.com/t5/Desktop-Linux/MPRIS-cover-art-url-file-not-found/td-p/4920104
art_url = art_url:gsub('https://open.spotify.com', 'https://i.scdn.co')
if ((art_url ~= nil or art_url ~='') and not gfs.file_readable('/tmp/' .. track_id)) then
spawn.easy_async('touch /tmp/' .. track_id, function()
spawn.easy_async('curl -L -s --show-error --create-dirs -o /tmp/' .. track_id .. ' '.. art_url, function(stdout, stderr)
if stderr ~= '' then
show_warning(stderr)
return
end
artwork_widget:set_image('/tmp/' .. track_id)
end)
end)
else
artwork_widget:set_image('/tmp/' .. track_id)
end
end
function spotify_player:tog()
if popup.visible then
popup.visible = not popup.visible
else
popup:move_next_to(mouse.current_widget_geometry)
end
end
spotify_player.widget:buttons(
awful.util.table.join(
awful.button({}, 1, function() spotify_player:tog() end)
)
)
watch('sp metadata', timeout, update_widget)
watch('sp status', 1, function(_, stdout)
stdout = string.gsub(stdout, "\n", "")
play_pause_btn:set_icon(stdout == 'Playing' and 'pause' or 'play')
end)
return spotify_player
end
return setmetatable(spotify_player, { __call = function(_, ...) return worker(...) end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

View File

@ -0,0 +1,29 @@
# Filesystem Widget
This widget shows file system disk space usage which is based on the `df` output. When clicked another widget appears with more detailed information. By default, it monitors the "/" mount. It can be configured with a list of mounts to monitor though only the first will show in the wibar. To have multiple mounts displayed on the wibar simply define multiple `fs_widgets` with different mounts as arguments.
![](./screenshot.png)
## Customizations
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `mounts` | `{'/'}` | Table with mounts to monitor, check the output from a `df` command for available options (column 'Mounted on') |
| `timeout` | 60 | How often in seconds the widget refreshes |
## Installation
Clone/download repo and use the widget in **rc.lua**:
```lua
local fs_widget = require("awesome-wm-widgets.fs-widget.fs-widget")
...
s.mywibox:setup {
s.mytasklist, -- Middle widget
{ -- Right widgets
fs_widget(), --default
fs_widget({ mounts = { '/', '/mnt/music' } }), -- multiple mounts
...
```

View File

@ -0,0 +1,190 @@
local awful = require("awful")
local watch = require("awful.widget.watch")
local wibox = require("wibox")
local beautiful = require("beautiful")
local gears = require("gears")
local storage_bar_widget = {}
--- Table with widget configuration, consists of three sections:
--- - general - general configuration
--- - widget - configuration of the widget displayed on the wibar
--- - popup - configuration of the popup
local config = {}
-- general
config.mounts = { '/' }
config.refresh_rate = 60
-- wibar widget
config.widget_width = 40
config.widget_bar_color = '#aaaaaa'
config.widget_onclick_bg = '#ff0000'
config.widget_border_color = '#535d6c66'
config.widget_background_color = '#22222233'
-- popup
config.popup_bg = '#22222233'
config.popup_border_width = 1
config.popup_border_color = '#535d6c66'
config.popup_bar_color = '#aaaaaa'
config.popup_bar_background_color = '#22222233'
config.popup_bar_border_color = '#535d6c66'
local function worker(user_args)
local args = user_args or {}
-- Setup config for the widget instance.
-- The `_config` table will keep the first existing value after checking
-- in this order: user parameter > beautiful > module default.
local _config = {}
for prop, value in pairs(config) do
_config[prop] = args[prop] or beautiful[prop] or value
end
storage_bar_widget = wibox.widget {
{
id = 'progressbar',
color = _config.widget_bar_color,
max_value = 100,
forced_height = 20,
forced_width = _config.widget_width,
paddings = 2,
margins = 4,
border_width = 1,
border_radius = 2,
border_color = _config.widget_border_color,
background_color = _config.widget_background_color,
widget = wibox.widget.progressbar
},
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 4)
end,
widget = wibox.container.background,
set_value = function(self, new_value)
self:get_children_by_id("progressbar")[1].value = new_value
end
}
local disk_rows = {
{ widget = wibox.widget.textbox },
spacing = 4,
layout = wibox.layout.fixed.vertical,
}
local disk_header = wibox.widget {
{
markup = '<b>Mount</b>',
forced_width = 150,
align = 'left',
widget = wibox.widget.textbox,
},
{
markup = '<b>Used</b>',
align = 'left',
widget = wibox.widget.textbox,
},
layout = wibox.layout.ratio.horizontal
}
disk_header:ajust_ratio(1, 0, 0.3, 0.7)
local popup = awful.popup {
bg = _config.popup_bg,
ontop = true,
visible = false,
shape = gears.shape.rounded_rect,
border_width = _config.popup_border_width,
border_color = _config.popup_border_color,
maximum_width = 400,
offset = { y = 5 },
widget = {}
}
storage_bar_widget:buttons(
awful.util.table.join(
awful.button({}, 1, function()
if popup.visible then
popup.visible = not popup.visible
storage_bar_widget:set_bg('#00000000')
else
storage_bar_widget:set_bg(_config.widget_background_color)
popup:move_next_to(mouse.current_widget_geometry)
end
end)
)
)
local disks = {}
watch([[bash -c "df | tail -n +2"]], _config.refresh_rate,
function(widget, stdout)
for line in stdout:gmatch("[^\r\n$]+") do
local filesystem, size, used, avail, perc, mount =
line:match('([%p%w]+)%s+([%d%w]+)%s+([%d%w]+)%s+([%d%w]+)%s+([%d]+)%%%s+([%p%w]+)')
disks[mount] = {}
disks[mount].filesystem = filesystem
disks[mount].size = size
disks[mount].used = used
disks[mount].avail = avail
disks[mount].perc = perc
disks[mount].mount = mount
if disks[mount].mount == _config.mounts[1] then
widget:set_value(tonumber(disks[mount].perc))
end
end
for k, v in ipairs(_config.mounts) do
local row = wibox.widget {
{
text = disks[v].mount,
forced_width = 150,
widget = wibox.widget.textbox
},
{
color = _config.popup_bar_color,
max_value = 100,
value = tonumber(disks[v].perc),
forced_height = 20,
paddings = 1,
margins = 4,
border_width = 1,
border_color = _config.popup_bar_border_color,
background_color = _config.popup_bar_background_color,
bar_border_width = 1,
bar_border_color = _config.popup_bar_border_color,
widget = wibox.widget.progressbar,
},
{
text = math.floor(disks[v].used / 1024 / 1024)
.. '/'
.. math.floor(disks[v].size / 1024 / 1024) .. 'GB('
.. math.floor(disks[v].perc) .. '%)',
widget = wibox.widget.textbox
},
layout = wibox.layout.ratio.horizontal
}
row:ajust_ratio(2, 0.3, 0.3, 0.4)
disk_rows[k] = row
end
popup:setup {
{
disk_header,
disk_rows,
layout = wibox.layout.fixed.vertical,
},
margins = 8,
widget = wibox.container.margin
}
end,
storage_bar_widget
)
return storage_bar_widget
end
return setmetatable(storage_bar_widget, { __call = function(_, ...)
return worker(...)
end })

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,77 @@
# Gerrit widget
It shows number of currently assigned reviews in [Gerrit](https://www.gerritcodereview.com/) to the user (by default) :
![gerrit_widget](./gerrit_widget.png)
when clicked it shows reviews in a list:
![popup](./popup.png)
left click on an item will open review in the default browser, right click will copy the review number, which you can use to checkout this review by running `git-review -d <review number>`.
Also, if a new review is assigned to the user, there will be a pop-up:
![new_review](./new_review.png)
## Customization
It is possible to customize widget by providing a table with all or some of the following config parameters:
| Name | Default | Description |
|---|---|---|
| `icon`| `/.config/awesome/awesome-wm-widgets/gerrit-widget/gerrit_icon.svg`| Path to the icon |
| `host` | Required | Ex https://gerrit.tmnt.com |
| `query` | `is:reviewer AND status:open AND NOT is:wip` | Query to retrieve reviews |
| `timeout` | 10 | How often in seconds the widget refreshes |
## Prerequisite
- [curl](https://curl.haxx.se/) - is used to communicate with gerrit's [REST API](https://gerrit-review.googlesource.com/Documentation/rest-api.html)
- setup [netrc](https://ec.haxx.se/usingcurl-netrc.html) which is used to store username and password in order to call API's endpoints.
## Installation
1. This widget relies on Gerrit [REST API](https://gerrit-review.googlesource.com/Documentation/rest-api.html), so you need to have a permission to access it. You also need to setup [netrc](https://ec.haxx.se/usingcurl-netrc.html), as widget uses curl to communicate with API and you have to be authenticated.
To test if you have access to API and netrc setup is correct run following command, you should have a json response:
```bash
curl -s --request GET --netrc https://gerrit-host.com/a/changes/\?q\=status:open+AND+NOT+is:wip+AND+is:reviewer | tail -n +2
```
Note: `tail -n +2` is needed to skip first line of the response, as gerrit returns some characters there in order to prevent XSS hacks.
1. Download json parser for lua from [github.com/rxi/json.lua](https://github.com/rxi/json.lua) and place it under **~/.config/awesome/** (don't forget to star a repo):
```bash
wget -P ~/.config/awesome/ https://raw.githubusercontent.com/rxi/json.lua/master/json.lua
```
1. Clone this repo (if not cloned yet) under **~/.config/awesome/**:
```bash
git clone https://github.com/streetturtle/awesome-wm-widgets.git ~/.config/awesome/
```
1. Require widget at the top of the **rc.lua**:
```lua
local gerrit_widget = require("awesome-wm-widgets.gerrit-widget.gerrit")
```
1. Add widget to the tasklist:
```lua
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
...
--default
gerrit_widget({host = 'https://gerrit.tmnt.com'}),
--customized
gerrit_widget({
host = 'https://gerrit.tmnt.com',
query = 'is:reviewer AND is:wip'
})
...
```

Some files were not shown because too many files have changed in this diff Show More