Introduction
Noti
is a simple yet powerful notification daemon, offering:
- Native Wayland Support: Built from the ground up for Wayland environments
- Highly-customizable: Tailor your notifications to suit your preferences
- Per-App Styling: Unique notification styles for different applications
- Modern Design: Clean, minimalist approach to desktop notifications
Whether you're a developer who wants to integrate notifications into your Wayland environment or a regular user looking for a more customizable desktop experience, Noti is here to provide a simple, powerful solution.
Noti doesn’t just deliver notifications; it gives you control.
Getting Started with Noti
Prerequisites
Before installing Noti, ensure you have the following:
- A Linux system with a Wayland compositor
- Rust toolchain (
rustc
andcargo
) - Basic understanding of terminal commands
Installation
Installing via Cargo (Recommended)
The simplest way to install Noti is using Cargo, Rust's package manager:
# Install directly from GitHub
cargo install --git https://github.com/noti-rs/noti/
# Or clone and install locally
git clone https://github.com/noti-rs/noti.git
cd noti
cargo install --path .
Building from Source
# Clone the repository
git clone https://github.com/noti-rs/noti.git
cd noti
# Build in release mode
cargo build --release
# Install the binary
cargo install --path .
Running
To confirm Noti is installed correctly:
# Check Noti version
noti --version
# Display help information
noti --help
After installation, you can start Noti manually:
# Start Noti daemon
noti run
Automatic Startup
Session Startup Script
You can add noti run to your session startup script to ensure it starts automatically. For example, if you use Hyprland, include the following line in your Hyprland configuration:
exec-once = noti run
This is a simple way to start noti automatically when your session begins. However, note that this approach does not handle cases where the application crashes or encounters errors — it will not automatically restart noti
in such situations.
Advanced Autostart
For more robust and advanced autostart setups, refer to the Autostart. This guide provides detailed instructions for setting up a reliable autostart configuration.
Autostart
Autostarting Noti using Systemd and D-Bus
This guide will help you configure autostart Noti
using systemd
user services and D-Bus
activation.
WARNING: Specific configurations might vary slightly depending on your distribution and desktop setup.
Understanding Environment Variables
Variable | Default Path | Description |
---|---|---|
$XDG_DATA_HOME | ~/.local/share | User-specific data directory |
$XDG_CONFIG_HOME | ~/.config | User-specific configuration directory |
Step 1: D-Bus Service Configuration
Create a D-Bus service
to define how application should be launched:
mkdir -d $XDG_DATA_HOME/dbus-1/services
touch $XDG_DATA_HOME/dbus-1/services/org.freedesktop.Notifications.service
Add the following:
[D-Bus Service]
Name=org.freedesktop.Notifications
Exec=%h/.cargo/bin/noti run
SystemdService=noti.service
Step 2: Systemd User Service Configuration
Create a systemd unit
to manage application's lifecycle:
mkdir -d $XDG_CONFIG_HOME/systemd/user
touch $XDG_CONFIG_HOME/systemd/user/noti.service
Add the following:
[Unit]
Description=Noti Application
PartOf=graphical-session.target
After=graphical-session.target
[Service]
Type=dbus
BusName=org.freedesktop.Notifications
Environment=XDG_CONFIG_HOME=%h/.config
Environment=NOTI_LOG=info
ExecStart=%h/.cargo/bin/noti run
Restart=always
[Install]
WantedBy=default.target
Unit Configuration Breakdown
Configuration | Purpose |
---|---|
PartOf=graphical-session.target | Ensures the service is managed with the graphical session |
Type=dbus | Enables D-Bus activation |
Restart=always | Automatically restarts on failure |
WantedBy=default.target | Enables autostart at user login |
Step 3: Enable and Start the Service
# Reload systemd user configuration
systemctl --user daemon-reload
# Enable service to start on boot
systemctl --user enable noti.service
# Start service immediately
systemctl --user start noti.service
Troubleshooting
# View service status
systemctl --user status noti
# Follow live service logs
journalctl --user --unit noti --follow
Common Issues:
- Ensure the executable path is correct
- Check file permissions
- Verify
D-Bus
andsystemd
configurations- Confirm environment variables are set correctly
Configuration
Understanding Noti's Configuration
Noti looks for configuration files in the following locations (in order of priority):
$XDG_CONFIG_HOME/noti/config.toml
$HOME/.config/noti/config.toml
Hot Reload
Noti supports hot-reloading configuration changes. Simply save your config file, and Noti will automatically apply the new settings.
Types
Before of all properties, need to understand a few primitive types. The complex types like array or table will be explained in place.
Type | Description |
---|---|
bool | A boolean value |
u8 | An unsigned integer of 8 bit |
u16 | An unsigned integer of 16 bit |
String | A string,typically used as an enumeration variant |
[...] | An array containing various type. Used as tuple |
[T; from..to] | An array with elements of type T , where the number of elements can vary between from and to (inclusive) |
Color | A color value. Either string or table |
Path | The path to particular file or directory |
Configuration Structure
The Noti configuration is divided into four main property groups:
Each of them belongs to specific idea. So the reading order is not matter. But we recommend you to go to through from the first one to the last one.
Importing
You can import configuration files from other files:
use = [
"$XDG_CONFIG_HOME/noti/themes.toml",
"~/.config/noti/layouts/layout.toml",
"./apps/*"
]
Note:
- Current configuration file takes precedence
- Avoid importing the same file multiple time
- Avoid circular dependencies
- Merge behavior is not guaranteed, so declare configurations carefully
General Settings
General settings apply to the entire notification system and control global behavior.
Property name | Description | Type | Default value |
---|---|---|---|
font | Font | String | "Noto Sans" |
width | Width of banner frame | u16 | 300 |
height | Height of banner frame | u16 | 150 |
anchor | Screen position where notifications appear | String | "top right" |
gap | Space size between two banners. Measures in px | u8 | 10 |
offset | Distance from screen edges | [u8, u8] | [0, 0] |
sorting | How notifications are ordered | String or Sorting | "default" |
idle_threshold | Duration that pauses notification timeouts during user inactivity | String | "5 sec" |
limit | Maximum number of notifications on the screen | u8 | 0 |
Font
Accepts the font name, which may or may not be separated by spaces.
font = "JetBrainsMono Nerd Font"
Note:
The application can only use font names recognized by the
fc-list
command. Styled fonts like "Noto Sans Bold" can't be used directly, but the app may load the required styles internally.
Width & Height
The width
and height
properties define the dimensions of the notification banner frame in pixels. These settings control the visual size of the individual notification banners on the screen.
width
: Sets the horizontal size of the banner.height
: Sets the vertical size of the banner.
width = 400
height = 200
Anchor
The anchor of the current monitor for the current window instance, which determines where the notification banners will appear. The possible values are:
top-left | top | top-right |
left | right | |
bottom-left | bottom | bottom-right |
anchor = "top"
Note:
Dash between words is optional.
Gap
The gap
property specifies the amount of space, measured in pixels, between two adjacent notification banners. This setting ensures that notifications do not overlap and maintains a consistent visual separation between them.
gap = 15
Offset
The offset from the edges for the window instance. The first value represents the offset along the x-axis
, and the second value represents the offset along the y-axis
.
For example, if you choose the "bottom-left"
anchor and set an offset of [5, 10]
, the window instance will be positioned at the bottom-left edge of the current monitor, with a 5-pixel offset from the left edge and a 10-pixel offset from the bottom edge.
offset = [10, 10]
Sorting
The property that determines the banner sorting rule. This is particularly useful when you want to position banners with critical urgency at the top or bottom.
You can define a string for ascending sorting by default.
# with default ordering
sorting = "urgency"
However, to sort in descending order, you must define a table:
Possible values of the by
property name:
"default"
(alias to"time"
)"time"
"id"
"urgency"
Possible values of the ordering
property name:
"ascending"
(also possible short name "asc")"descending"
(also possible short name "desc")
# with specific ordering
[general.sorting]
by = "id"
ordering = "descending"
Idle Threshold
When idle_threshold
is set, notifications will not be removed or expired while the user is idle beyond the configured threshold. Once the user is active again, the timeout resumes.
This setting accepts a human-readable duration format (e.g., "15 minutes"
, "30s"
).
If set to "none"
, the idle timeout behavior is disabled.
idle_threshold = "5 min"
Limit
The maximum number of notifications that can be displayed at once. Once this limit is reached, any new notifications will be queued and shown once the currently displayed ones either time out or are manually dismissed.
A value of 0
means there is no limit.
limit = 3
Display Configuration
The display
section allows you to customize the visual aspects of notifications.
Property name | Description | Type | Default value |
---|---|---|---|
padding | Spacing from the banner's edge to inner content | u8 or [u8; 1..4] or Spacing | 0 |
margin | Spacing from the banner's edge to inner content | u8 or [u8; 1..4] or Spacing | 0 |
image | Image properties | Image | - |
icons | Icons properties | Icons | - |
border | Border properties | Border | - |
text | Text properties (alias for title and body ) | Text | - |
title | Title text properties | Text | - |
body | Body text properties | Text | - |
markup | Enables HTML markup | bool | true |
timeout | Banner timeout | u16 or Timeout | 0 |
layout | Custom layout path | Path | "default" |
theme | Theme name | String | - |
Padding & Margin
In this application, padding and margin control spacing in different ways:
- Padding: The space between an element's content (like text or an image) and its edges. It reduces the area available for the content inside the element.
- Margin: The space between an element's outer edges and other surrounding elements. It separates elements from each other.
Declaring Padding and Margin Properties
CSS-like
If you familiar with CSS, you know that the padding or the margin can be applied in single row, in the TOML config file you can do it using array:
# Applies vertical and horizontal paddings respectively
padding = [0, 5]
# Applies top, horizontal and bottom paddings respectively
margin = [3, 2, 5]
# Applies top, right, bottom, left paddings respectively
padding = [1, 2, 3, 4]
# For all-directional padding or margin
padding = 10
margin = 5
Explicit
If you prefer a more detailed approach, you can use an explicit syntax with Spacing
table:
Key | Short description | Type |
---|---|---|
top | Spacing from top | u8 |
right | Spacing from right | u8 |
bottom | Spacing from bottom | u8 |
left | Spacing from left | u8 |
vertical | Spacing from top and bottom together | u8 |
horizontal | Spacing from left and right together | u8 |
# Sets only top padding
padding = { top = 3 }
# Sets only top and right padding
padding = { top = 5, right = 6 }
# Instead of
# padding = { top = 5, right = 6, bottom = 5 }
# You can write
padding = { vertical = 5, right = 6 }
# Conflicting values will result in an error due to ambiguity:
# padding = { top = 5, vertical = 6 } --- ERROR
# You can apply the same way for margin
margin = { top = 5, horizontal = 10 }
# For all-directional padding or margin
padding = 10
margin = 5
Warning:
- horizontal is incompatible with left or right keys
- vertical is incompatible with top or bottom keys
If content (like an image or text) isn't displaying correctly in a banner, check the padding or margin. Excessive padding or margin can reduce the space for content, causing it to overflow or not fit properly.
Image
Typically, the notification includes an image or icon, which is displayed on the left side of the banner.
Here's a table of Image
properties:
Property name | Description | Type | Default value |
---|---|---|---|
max_size | Sets the max size for image and resizes it when width or height of image exceeds this value | u16 | 64 |
rounding | Value used to round image corners | u16 | 0 |
margin | Spacing around image. If there is no space for image, the image will be squished. | u8 or [u8; 1..4] or Spacing | 0 |
resizing_method | Resizing method for image when it exceeds max_size . Possible values: "gaussian" , "nearest" , "triandle" , "catmull-rom" , "lanczos3" | String | "gaussian" |
[display.image]
max_size = 32
rounding = 10
Icons
If application doesn't provide any image but app-icon, then it will be treated as image.
The Icons
table:
Property name | Description | Type | Default value |
---|---|---|---|
theme | Icon theme like Adwaita, Papirus... | Strng | "Adwaita" |
size | Concrete sizes of the icon. Will be picked the first one which found in system resources. Ordering matters - searches from first to last. | [u16; 1..] | [64, 32] |
[display.icons]
theme = "Papirus"
size = [64, 32, 16]
Note: Since app-icon threated as image, the image properties will be applied to icon, even the
max_size
.
Border
You can customize the notification banner with border styles, including border size and border radius:
- Border size: The width of the border around the banner, which also reduces the inner space.
- Border radius: How rounded the corners of the banner are.
The Border
table:
Key | Short description | Type | Default value |
---|---|---|---|
size | Width of stroke which is outlines around the banner | u8 | 0 |
radius | Border radius for corner rounding | u8 | 0 |
[display.border]
size = 2
radius = 12
margin = { right = 15 }
Note: If the border size is larger than the radius, the inner corners won’t be rounded.
Text
The application has title and body properties, both treated as Text
. A new text
property can be used for both the title and body at once. Use text
when the same value applies to both, or set them separately if needed.
The Text
table:
Key | Short description | Type | Default value |
---|---|---|---|
wrap | Sets possibility to line breaking when text overflows a line | bool | true |
ellipsize_at | Ellipsizes a text if it's totally overflows an area. Possible values: "end" and "middle" . "end" - put ellipsis at end of word, "middle" - cut word at some middle of word and puts ellipsis | String | "end" |
style | Font style. Possible values: "regular" , "bold" , "italic" , "bold italic" | String | "regular" |
margin | Text spacing from edges of remaining area | Spacing | 0 |
justification | Text justification. Possible values: "left" , "right" , "center" , "space-between" | String | "left" |
line_spacing | Gap between wrapped text lines in px | u8 | 0 |
font_size | Font size in px | u8 | 12 |
[display.text]
justification = "left"
wrap = false
ellipsize_at = "middle"
font_size = 18
[display.title]
style = "bold"
Property priority:
- Use
title
orbody
first.- If missing, use the
text
property.- If still missing, default values apply.
Markup
Enables text styling through HTML tags.
For the body, the markup
property is applied, allowing the use of HTML-like tags, such as:
<b>
- bold style<i>
- italic style<u>
- underline style<a href="https://google.com">
- a hyperlink<img src="path/to/image" alt="image description">
- an image embedded in the text
You can disable the markup
property by setting it to false
.
markup = false
Timeout
The time in milliseconds after which the notification banner will automatically close due to expiration, starting from when it is created.
Additionally, there is an extended timeout configuration based on the urgency of the banners, defined in the Timeout
table.
The Timeout
table:
Key | Short description | Type |
---|---|---|
default | Set default timeout for all urgency | u16 |
low | Override timeout value for 'low' urgency banners | u16 |
normal | Override timeout value for 'normal' urgency banners | u16 |
critical | Override timeout value for 'critical' urgency banners | u16 |
timeout = 5000
# or
[display.timeout]
default = 5000
critical = 0
Note: The value
0
means will never expired.
Colors
Fill
To declare fill color use a string in format "#RGB"
, "#RRGGBB"
or "#RRGGBBAA"
:
[theme.normal]
background = "#FFF"
foreground = "#A2A2A2"
border = "#BEBEBEAA"
Gradient
When defining gradients, use the same property as you would for a single color, but provide a table value instead. All gradient configurations share these common properties:
Key | Type | Default value | Short description |
---|---|---|---|
mode | String | - | Specifies the gradient type |
degree | u16 | - | Angle of the gradient in degrees |
colors | [Color; 2..] | - | An array of color values (in hex format) |
Supported gradient types
Linear Gradient
Linear gradients create a smooth transition between two or more colors along a straight line.background. The transition direction is determined by the degree value, where 0° points upward and the angle increases clockwise.
[theme.normal]
background = { mode = "linear-gradient", degree = 30, colors = ["#F00", "#0F0", "#00F"] }]
Themes
Define custom color schemes for different notification urgency levels:
The Theme
table:
Key | Type | Default value | Short description |
---|---|---|---|
low | Colors | - | The colors for low urgency banner |
normal | Colors | - | The colors for normal urgency banner |
critical | Colors | - | The colors for critical urgency banner |
The Colors
table:
Key | Type | Default value | Short description |
---|---|---|---|
background | Color | "#FFFFFF" | The background color |
foreground | Color | "#000000" (but for critical : "#FF0000") | The foreground color |
border | Color | "#000000" (but for critical : "#FF0000") | The border stroke color |
[[theme]]
name = "pastel"
[theme.normal]
background = "#1e1e2e"
foreground = "#99AEB3"
border = "#000"
[theme.critical]
background = "#EBA0AC"
foreground = "#1E1E2E"
border = "#000"
App-Specific Configuration
The Noti application includes an app-specific configuration feature, allowing you to override the display table for a particular application.
Here’s how the properties are selected:
- Check if the property is defined in the app-specific configuration.
- If not, use the general display property.
- If it’s still not defined in the general display property, use the default value.
The App
table:
Key | Short description | Type |
---|---|---|
name | The name of application | String |
display | The display configuration table for this application | Display |
[[app]]
name = "Telegram Desktop"
[app.display]
theme = "telegram-theme"
padding = 10
border = { size = 2, radius = 12 }
[[app]]
name = "Spotify"
[app.display]
image = { max_size = 64 }
timeout = 2000
Custom Layout
The Noti
application allows users to customize the layout of notification banners, giving you complete control over how your notifications are displayed. Whether you want to move an image to the right, swap the title and body, or pin the title to the top, Noti
makes it possible through custom layout files.
To customize a layout, you define it in a .noti
file and reference it in your main configuration file.
Setting Up a Custom Layout
To enable a custom layout, specify its path in your configuration file:
display.layout = "path/to/your/layout/file.noti"
This can be set globally or for specific applications. Once specified, create the layout file and define your custom design.
WARNING: When using a custom layout:
- Border, padding, and margin settings are overridden
- Only general configurations, colors, and non-styling settings remain active
Types
The available property types are limited to a few:
- Literal: A continuous sequence of characters not enclosed in double quotes, always treated as a string.
- UInt: An unsigned integer.
- Type value: Refer to the linked section for details.
The Noti
application includes intelligent conversion for Literal
types, allowing them to represent boolean, color, type, or other supported formats as needed.
Layout Basics
Layouts in Noti
are built using widgets and type values:
Widgets
Widgets are the building blocks of layouts. They are graphic elements with customizable properties. The available widgets are:
- FlexContainer: A container that organizes its child widgets.
- Text: Displays text, such as the title or body.
- Image: Displays an image.
Type Values
Type values are configuration options used to adjust widget behavior. Examples include:
- Alignment: Controls horizontal and vertical alignment.
- Spacing: Defines padding or margins.
- Border: Adds a border around widgets.
Writing a Layout File
General Syntax
Each layout file must have one root widget, typically a FlexContainer
. Widgets and type values are declared using a constructor-like syntax:
WidgetName(
property_name = value,
another_property = true,
nested_property = TypeValueName(
type_value_property = 5,
)
)
You can include trailing commas for readability. If a widget or type value has default properties, they can be omitted:
Image()
Adding Child Widgets
To nest widgets, use the children
property inside a FlexContainer
:
FlexContainer() {
Text(kind = title)
Image()
}
Child widgets are enclosed in curly braces, with whitespace separating them.
Widget Properties
FlexContainer
The FlexContainer
organizes its child widgets either horizontally or vertically.
Property | Description | Type | Default |
---|---|---|---|
direction | Layout direction (horizontal or vertical ). | Literal | - |
max_width | Maximum width of the container. | UInt | MAX |
max_height | Maximum height of the container. | UInt | MAX |
border | Border around the container. | Border | Default border values |
spacing | Spacing between child widgets. | Spacing | Default spacing values |
alignment | Horizontal and vertical alignment of content (start , center , end ). | Alignment | - |
transparent_background | Make the background transparent (true or false ) | Literal | false |
Text
The Text
widget is used for titles and body text. Specify the kind of text to display.
Property | Description | Type | Default |
---|---|---|---|
kind | Type of text (title /summary or body ). | Literal | - |
Image
The Image
widget displays an image. It uses properties defined in the main configuration.
Supporting Type Values
Spacing
Defines padding or margin offsets. Currently, individual values (e.g., top
, right
) must be set explicitly.
Property | Description | Type | Default |
---|---|---|---|
top | Offset from the top. | UInt | 0 |
right | Offset from the right. | UInt | 0 |
bottom | Offset from the bottom. | UInt | 0 |
left | Offset from the left. | UInt | 0 |
Alignment
Controls how content is aligned within a widget.
Property | Description | Type | Default |
---|---|---|---|
horizontal | Horizontal alignment (start , end , center , space-between ). | Literal | - |
vertical | Vertical alignment (start , end , center , space-between ). | Literal | - |
Editor Support
Tree-sitter Highlighting
If your editor supports Tree-sitter, you can enable syntax highlighting for .noti
files by adding our Tree-sitter grammar:
Neovim Plugin
For Neovim users, we offer a plugin that integrates Tree-sitter to enable syntax highlighting with minimal effort.
To install, use your favorite plugin manager, such as lazy.nvim
:
{
"noti-rs/noti.nvim",
dependencies = {
"nvim-treesitter/nvim-treesitter",
},
build = "python3 clone_queries.py",
opts = {},
}
After adding the plugin to your configuration, run:
:TSInstall noti
Tips and Tricks
Blurred Transparent Background
If you're using Hyprland, you can create a blurred transparent background with the following steps:
- Make the background transparent in your theme configuration:
[theme.normal]
background = "#ffffff00" # the last two symbols control opacity
- Add these
layerrule
settings somewhere to your Hyprland config:
layerrule = blur, noti
layerrule = blurpopups, noti
layerrule = xray, noti
layerrule = ignorealpha 0, noti
Troubleshooting
You can change the log level by setting the NOTI_LOG
environment variable. Supported log levels are info, debug, and trace. For example, to enable detailed logging, use:
NOTI_LOG=debug noti run
This will help you check the logs for specific error messages.
Examples
Example configurations
jsonmaf1a
's setup
Example scripts
Volume Control
This script allows you to adjust the volume (increase, decrease, or mute) and displays notifications for each action.
Click to reveal
Requirements:
- pamixer: To control the audio volume.
Script:
#!/bin/bash
VOL_UP=$ICONS/volup.svg
VOL_DOWN=$ICONS/voldown.svg
VOL_MUTE=$ICONS/volmute.svg
URGENCY=low
APP_NAME=volume
ID_TMPFILE=/tmp/vol-noti-id
if [[ ! -f $ID_TMPFILE ]]; then
touch $ID_TMPFILE
fi
ID=$(<$ID_TMPFILE)
send_notification() {
local icon=$1
local message=$2
local urgency=${3:-$URGENCY}
if [[ $ID ]]; then
noti send -a "$APP_NAME" -u "$urgency" -i "$icon" -r "$ID" "$message"
else
noti send -a "$APP_NAME" -u "$urgency" -i "$icon" "$message" --print-id > "$ID_TMPFILE"
fi
}
update_volume() {
local change=$1
pamixer $change 5 -u
send_notification "$VOL_UP" "Volume: $(pamixer --get-volume)%"
}
toggle_mute() {
pamixer -t
if $(pamixer --get-mute); then
send_notification "$VOL_MUTE" "Volume muted" "critical"
else
send_notification "$VOL_MUTE" "Volume unmuted" "critical"
fi
}
case $1 in
up)
update_volume "-i"
;;
down)
update_volume "-d"
;;
mute)
toggle_mute
;;
*)
echo "Usage: $0 { 'up' | 'down' | 'mute' }"
exit 1
;;
esac
Note: Replace the
$ICONS/volup.svg
,$ICONS/voldown.svg
, and$ICONS/volmute.svg
with the paths to your own icons for volume up, down, and mute.
Usage
./volume.sh up # Increase volume
./volume.sh down # Decrease volume
./volume.sh mute # Toggle mute
Bind these commands to keyboard shortcuts for easier access.
Brightness Control
This script allows you to adjust the screen brightness and displays notifications for each action.
Click to reveal
Requirements:
- brightnessctl: To control the screen brightness.
Script:
#!/bin/bash
ID_TMPFILE=/tmp/brightness-noti-id
if [[ ! -f $ID_TMPFILE ]]; then
touch $ID_TMPFILE
fi
ID=$(<$ID_TMPFILE)
send_notification() {
local value=$1
if [[ $ID ]]; then
noti send -a "brightness" -u low -i $ICONS/brightness.svg -r $ID "Brightness: $value%"
else
noti send -a "brightness" -u low -i $ICONS/brightness.svg "Brightness: $value%" > $ID_TMPFILE
fi
}
calculate_percentage() {
local value=$1
percentage=$(echo "scale=0; $brightness * 100 / 1515" | bc -l)
rounded_percentage=$(echo "($percentage + 5) / 10 * 10" | bc)
echo $rounded_percentage
}
case $1 in
up)
brightnessctl s +10%
brightness=$(brightnessctl g)
send_notification $(calculate_percentage brightness)
;;
down)
brightnessctl s 10%-
brightness=$(brightnessctl g)
send_notification $(calculate_percentage brightness)
;;
*)
echo "Usage: $0 {up|down}"
exit 1
;;
esac
Note:
Replace$ICONS/brightness.svg
with the path to your own brightness icon.
Usage
./brightness.sh up # Increase brightness
./brightness.sh down # Decrease brightness
Bind these commands to keyboard shortcuts for quicker access.
Keyboard Layout Switcher
This script switches between keyboard layouts and displays a notification showing the current layout.
Click to reveal
Requirements:
- hyprctl: To manage devices and switch keyboard layouts.
- kb-switcher(optional): See hyprland_kb_switcher
Script:
#!/bin/sh
ID_TMPFILE=/tmp/kb-noti-id
if [[ ! -f $ID_TMPFILE ]]; then
touch $ID_TMPFILE
fi
ID=$(<$ID_TMPFILE)
KEYBOARD="your-keyboard-name" # use hyprctl devices to see all connected keyboards
# NOTE: kb is https://github.com/JarKz/hyprland_kb_switcher/
# but you can just use `hyprctl switchxkblayout $keyboard next`
kb switch
VALUE=$(hyprctl devices | grep -i $KEYBOARD -A 2 | tail -n1 | cut -f3,4 -d' ')
if [[ $ID ]]; then
noti send -a "kb" -u low -i $ICONS/kb.svg -r $ID "$VALUE"
else
noti send -a "kb" -u low -i $ICONS/kb.svg "$VALUE" --print-id > $ID_TMPFILE
fi
Note:
Replacekeyboard
with your actual keyboard device name and$ICONS/kb.svg
with the path to your keyboard icon.
Developer Guide
Welcome to the Noti Developer Guide! This chapter provides essential information for developers who want to contribute to the Noti project or understand its architecture and codebase.
Project Structure
The Noti project is organized into several crates, each serving a specific purpose:
- app: Contains the command-line interface and main application logic.
- backend: Handles the core functionality and runs as a daemon.
- client: Manages client-side operations and interactions.
- dbus: Implements D-Bus communication using the
zbus
crate. - render: Provides rendering capabilities for notifications.
- config: Manages configuration settings and parsing.
- macros: Contains procedural macros to simplify code generation.
- shared: Includes shared utilities and types used across the project.
Setting Up the Development Environment
To set up your development environment, follow these steps:
-
Install Rust Toolchain: Ensure you have the latest Rust toolchain installed. You can install it using rustup.
-
Clone the Repository:
git clone https://github.com/noti-rs/noti.git cd noti
-
Run the Project: Use Cargo to build the project:
cargo run -- run
Coding Guidelines
- Rust Edition: The project uses Rust 2021 edition. Ensure your code is compatible with this edition.
- Formatting: Use
rustfmt
to format your code. The configuration is specified inrustfmt.toml
. - Linting: Run
clippy
to catch common mistakes and improve code quality:cargo clippy
Contributing
We welcome contributions from the community! Here’s how you can contribute:
-
Fork the Repository: Create a fork of the repository on GitHub.
-
Create a Branch: Create a new branch for your feature or bug fix:
git checkout -b feat/my-feature
-
Make Changes: Implement your changes, ensuring you follow the coding guidelines.
-
Commit and Push: Commit your changes with a descriptive message and push to your fork:
git commit -am "feat: add new feature" git push origin feature/my-feature
-
Open a Pull Request: Submit a pull request to the main repository. Provide a clear description of your changes and any relevant context.
Commit messages
Write clear and concise commit messages. Use the following format:
type(scope): subject
body (optional)
For example:
feat(config): add support for custom themes
This feature allows users to define their own themes in the configuration file.