Unix & Linux Stack Exchange
Q&A for users of Linux, FreeBSD and other Unix-like operating systems
Latest Questions
2
votes
2
answers
3285
views
In NixOS, is there a way to use Rofi instead of Dmenu when invoking Passmenu?
I'm using the `pass` package for password management. The `passmenu` command that comes with it uses `dmenu`, but I'd like for it to use Rofi instead. I saw [on the Arch wiki](https://wiki.archlinux.org/index.php/Rofi#Rofi_as_dmenu_replacement) that it's possible to use rofi as a drop-in dmenu repla...
I'm using the
pass
package for password management. The passmenu
command that comes with it uses dmenu
, but I'd like for it to use Rofi instead. I saw [on the Arch wiki](https://wiki.archlinux.org/index.php/Rofi#Rofi_as_dmenu_replacement) that it's possible to use rofi as a drop-in dmenu replacement, but the path structures of NixOS are so complex that I'm having a hard time figuring this out. Should I create a new package for it? Or is there a way to update [the original pass package](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/security/pass/default.nix) so that it uses rofi instead?
Jonathan
(1330 rep)
Sep 11, 2018, 04:28 PM
• Last activity: Jun 30, 2025, 07:03 AM
0
votes
0
answers
36
views
Issue with wallpaper changing while hovering over names in Rofi — where am I going wrong?
I’ve written a script to change my wallpaper with Rofi, but I’m having a problem. While I hover over the wallpaper names in the rofi menu, the wallpaper is not changing dynamically for like a temporary preview (as I expect). By the way, I want the wallpaper to only change after I select the one I wa...
I’ve written a script to change my wallpaper with Rofi, but I’m having a problem. While I hover over the wallpaper names in the rofi menu, the wallpaper is not changing dynamically for like a temporary preview (as I expect). By the way, I want the wallpaper to only change after I select the one I want and not during browsing.
Here's the script I’m using:
#!/bin/bash
WALLPAPER_DIR="$HOME/Pictures/Wallpapers"
# Function to format wallpaper names for display
format_name() {
basename "$1" | sed -E 's/[0-9]+[kK]?[- ]?[0-9]*[a-z]*//g; s/-/ /g; s/\.(jpg|png|jpeg)$//I; s/\b([a-z])/\u\1/g; s/\s+/ /g; s/^\s+|\s+$//g'
}
# Get list of wallpapers and format them
mapfile -t wallpapers < <(find "$WALLPAPER_DIR" -type f \( -iname "*.jpg" -o -iname "*.png" -o -iname "*.jpeg" \))
formatted_names=()
for wp in "${wallpapers[@]}"; do
formatted_names+=("$(format_name "$wp")")
done
# Store current wallpaper
current_wallpaper=$(grep 'feh --bg-scale' ~/.fehbg | cut -d "'" -f2)
# Let rofi show and capture the selection live
selection=$(printf "%s\n" "${formatted_names[@]}" | rofi -dmenu -i -p "Select Wallpaper" -format "s" -monitor-changes | while read -r selected_name; do
for wp in "${wallpapers[@]}"; do
if [ "$(format_name "$wp")" == "$selected_name" ]; then
# Change wallpaper temporarily as user browses
feh --bg-scale "$wp"
break
fi
done
done)
# Revert to previous wallpaper if no final selection
if [ -z "$selection" ]; then
[ -n "$current_wallpaper" ] && feh --bg-scale "$current_wallpaper"
fi
I’ve tried some solutions, but I’m not sure where I’m going wrong. Is there a simple way to the wallpaper from changing on temporary basis until I make a final selection? Any guidance would be appreciated... Oh I am using Arch (btw). :v
DarKnightz
(61 rep)
Feb 28, 2025, 10:01 PM
1
votes
1
answers
57
views
Open reference from Zotero using rofi / dmenu
I have a number of collections in Zotero (a bibliography manager). I would like to be able to open the associated PDFs using `rofi` or `dmenu`, and have a list of entries to choose from of the following form: [COLLECTION][AUTHORS]TITLE.pdf Has anyone created a script for this?
I have a number of collections in Zotero (a bibliography manager). I would like to be able to open the associated PDFs using
rofi
or dmenu
, and have a list of entries to choose from of the following form:
[COLLECTION][AUTHORS]TITLE.pdf
Has anyone created a script for this?
Rastapopoulos
(1869 rep)
Nov 7, 2024, 01:48 PM
• Last activity: Nov 8, 2024, 11:59 AM
0
votes
1
answers
109
views
Adding a Wine `.lnk` Program to Rofi
I was able to add a program ([KaTrain](https://github.com/sanderland/katrain)) — which I installed with `pipx` — to Rofi, following [this nice answer](https://unix.stackexchange.com/a/651744/364698): ```desktop [Desktop Entry] Exec=/home/phili/.local/bin/katrain Type=Application Categories=Go Name=K...
I was able to add a program ([KaTrain](https://github.com/sanderland/katrain)) — which I installed with
pipx
— to Rofi, following [this nice answer](https://unix.stackexchange.com/a/651744/364698) :
[Desktop Entry]
Exec=/home/phili/.local/bin/katrain
Type=Application
Categories=Go
Name=KaTrain
But now, I'm trying ot add another program ([Fox Weiqi](https://www.foxwq.com/soft/foreign.html)) , which I was only able to install via Wine.
[Desktop Entry]
Exec="wine /home/phili/Other\ Software/Fox\ Weiqi/Fox\ Go\ Server.lnk"
Type=Application
Categories=Go
Name=Fox Weiqi
If I use that Wine command on a terminal, it does work. (I'm using Archcraft.)
psygo
(233 rep)
Oct 9, 2024, 05:16 PM
• Last activity: Oct 9, 2024, 08:45 PM
0
votes
1
answers
326
views
Why is the scanned bluetooth devices not showing on `Rofi` bluetooth menu using `bluetoothctl`?
Why is the `rofi` menu not showing available the bluetooth devices when it's enabled and scanned via `bluetoothctl`? Here is the script that is used to make a shortcut to open a `rofi` styled bluetooth menu: ```sh #!/usr/bin/env bash # Function to enable Bluetooth enable_bluetooth() { sudo rfkill un...
Why is the
rofi
menu not showing available the bluetooth devices when it's enabled and scanned via bluetoothctl
? Here is the script that is used to make a shortcut to open a rofi
styled bluetooth menu:
#!/usr/bin/env bash
# Function to enable Bluetooth
enable_bluetooth() {
sudo rfkill unblock bluetooth
sudo bluetoothctl power on
sleep 2 # Short delay to ensure Bluetooth is powered on
}
# Function to disable Bluetooth
disable_bluetooth() {
sudo bluetoothctl power off
sleep 2 # Short delay to ensure Bluetooth is powered off
}
# Function to scan for Bluetooth devices
scan_bluetooth_devices() {
sudo bluetoothctl scan on &
sleep 10 # Allow some time for scanning
sudo bluetoothctl devices | while read -r line; do
device_mac=$(echo "$line" | awk '{print $2}')
device_name=$(echo "$line" | cut -d' ' -f3-)
if sudo bluetoothctl info "$device_mac" | grep -q "Connected: yes"; then
echo " $device_name (connected)"
else
echo " $device_name"
fi
done
}
# Ensure the bluetooth service is running
sudo systemctl start bluetooth
# Check the status of the bluetooth service
service_status=$(sudo systemctl is-active bluetooth)
if [[ "$service_status" != "active" ]]; then
notify-send "Bluetooth Service" "Bluetooth service is not active. Please check the systemctl status."
exit 1
fi
# Main menu loop
while true; do
# Get Bluetooth power status
bluetooth_status=$(sudo bluetoothctl show | grep "Powered:" | awk '{print $2}')
if [[ "$bluetooth_status" == "yes" ]]; then
toggle=" Disable Bluetooth"
else
toggle=" Enable Bluetooth"
fi
# Prompt user to select an option
chosen_option=$(echo -e "$toggle\n Scan for devices\n Exit" | rofi -dmenu -i -selected-row 1 -p "Bluetooth Menu")
# Handle user selection
if [ -z "$chosen_option" ]; then
exit
elif [ "$chosen_option" = " Enable Bluetooth" ]; then
enable_bluetooth
elif [ "$chosen_option" = " Disable Bluetooth" ]; then
disable_bluetooth
elif [ "$chosen_option" = " Scan for devices" ]; then
device_list=$(scan_bluetooth_devices)
chosen_device=$(echo -e "$device_list\n Back" | rofi -dmenu -i -selected-row 1 -p "Available Devices: ")
if [ "$chosen_device" = " Back" ] || [ -z "$chosen_device" ]; then
continue
else
# Extract MAC address and name of connection
chosen_mac=$(echo "$chosen_device" | awk '{print $2}')
chosen_name=$(echo "$chosen_device" | cut -d' ' -f3- | sed 's/ (connected)//')
# Message to show when connection is activated successfully
success_message="You are now connected to the Bluetooth device \"$chosen_name\"."
# Check if the device is already connected
if sudo bluetoothctl info "$chosen_mac" | grep -q "Connected: yes"; then
sudo bluetoothctl disconnect "$chosen_mac" && notify-send "Bluetooth Disconnected" "You are now disconnected from the Bluetooth device \"$chosen_name\"."
else
sudo bluetoothctl connect "$chosen_mac" && notify-send "Bluetooth Connected" "$success_message"
fi
fi
elif [ "$chosen_option" = " Exit" ]; then
exit
fi
done
DarKnightz
(61 rep)
Jun 23, 2024, 12:50 PM
• Last activity: Jul 12, 2024, 08:43 PM
1
votes
1
answers
1238
views
Cannot start rofi
getting this error after I updated by system yesterday, running endevouros i3 flavor. ``` The following errors where detected when starting rofi: Failed to set binding Tab for: Go to next element (in logical order).(kb-element-next): there is always a binding matching 'Tab' Failed to set binding ISO...
getting this error after I updated by system yesterday, running endevouros i3 flavor.
The following errors where detected when starting rofi:
Failed to set binding Tab for: Go to next element (in logical order).(kb-element-next):
there is always a binding matching 'Tab'
Failed to set binding ISO_LEFT_Tab for: Go to next element (in logical order).(kb-element-prev):
there is already a binding matching 'ISO_LEFT_Tab'
I am guess this means I have tab and iso_left_tab set to some config value twice, but I can't seems to see where it is, or this error pointing to something else?
My rofi config file : https://gist.github.com/SaHHiiLL/23c43c72fba344842ffd306155d60620
sahil
(23 rep)
Aug 21, 2022, 06:57 PM
• Last activity: Mar 29, 2024, 07:49 AM
0
votes
0
answers
211
views
Rofi leaves unresponsive terminals after run-shell-command | `Q` or `Ctrl-C` don't work
I'm trying to switch from using `dmenu` to `rofi` on my system, on which I use `i3wm`. I have the following keybinding: bindsym $mod+Ctrl+d exec --no-startup-id rofi -combi-modi window#drun#run -show combi -show-icons I use `urxvt` as my default terminal, and it's the one that's specified in my `con...
I'm trying to switch from using
dmenu
to rofi
on my system, on which
I use i3wm
. I have the following keybinding:
bindsym $mod+Ctrl+d exec --no-startup-id rofi -combi-modi
window#drun#run -show combi -show-icons
I use urxvt
as my default terminal, and it's the one that's specified
in my config.rasi
file for rofi
to use.
The problem I have is when I launch rofi
, and try to do something like
htop SHIFT RET
to run htop
in a terminal window.
When I'm done with htop
, I hit Q
and the process ends, but I'm left
with a blank terminal window. Hitting Q
again doesn't kill it, nor
does Ctrl-C
. I have to kill the window via my i3 keybinding
$mod+Shift+Q
.
It's a similar situation with a command like neofetch
, or ls -l
,
except now the first Q
doesn't kill the process as it has already
completed – the terminal window is not blank but contains the output of
those commands.
My run-shell-command
is "{terminal} -hold -e {cmd}"
.
I don't get this behavior when running these commands via dmenu
. For
instance, htop
is in the dmenu-recent/terminal
file, and hitting Q
kills the process and the terminal window at the same time. This is the
behavior I would like to replicate with rofi
– is this possible?
nonreligious
(153 rep)
Jan 23, 2024, 03:54 PM
0
votes
1
answers
1563
views
Automatically resize rofi menu height
I want `rofi` to automatically resize menu's height to the number of available options. There is an option `-lines` but with it I could only pass constant number. So for each call I'm forced to execute command twice - to calculate number of lines and to display menu: #!/usr/bin/sh lines=$(my_command...
I want
rofi
to automatically resize menu's height to the number of available options. There is an option -lines
but with it I could only pass constant number. So for each call I'm forced to execute command twice - to calculate number of lines and to display menu:
#!/usr/bin/sh
lines=$(my_command | wc -l)
my_command | rofi -dmenu -lines "$lines"
Is it possible to tell rofi
to shrink its menu to the number of available options?
anlar
(4357 rep)
May 30, 2023, 07:12 PM
• Last activity: May 31, 2023, 05:05 AM
2
votes
1
answers
877
views
Piping continuous output into rofi
I'm trying to write a bash script to pipe strings into rofi. These strings are continuously generated by a function `gen_x`. The function `gen_x` sometimes (only when a condition is met) outputs new strings. I currently implement the `gen_x`-function with an if statement within an infinite loop. I w...
I'm trying to write a bash script to pipe strings into rofi. These strings are continuously generated by a function
gen_x
.
The function gen_x
sometimes (only when a condition is met) outputs new strings. I currently implement the gen_x
-function with an if statement within an infinite loop.
I want to pipe this function into rofi. When an item is selected within rofi, rofi should output the selected item and gen_x
and rofi should end.
When using an infinite loop which outputs a new element every loop (as seen in gen_b
), the script does exactly what I described above.
However, when I implement an if statement in my function and only print a new element when the condition is true, the program never ends. I am unsure if this is due to gen_x
or rofi.
Simplified code
gen_a(){ while true; do if [[ "$v" == "" ]]; then echo "Test"; v=1; fi; sleep 1; done }
gen_b(){ while true; do echo "Test"; sleep 1; done }
gen_a | rofi -dmenu # -> this outputs Test and does not end
gen_b | rofi -dmenu # -> this outputs Test and ends properly
Is there a way to use conditionals within the while-loop, and the program ending properly.
Friendly Penguin 123
(23 rep)
May 28, 2023, 05:26 PM
• Last activity: May 28, 2023, 07:13 PM
4
votes
1
answers
739
views
Set EWMH properties, such as _NET_WM_WINDOW_TYPE, as a user?
For example, rofi runs as `_NET_WM_WINDOW_TYPE_NORMAL` (or, as I think I understand from the code, otherwise inherits from a parent window), but I'd like it to be `_NET_WM_WINDOW_TYPE_POPUP_MENU` in order to do something more generic in i3 & picom configs than matching on its class name. I know I ca...
For example, rofi runs as
_NET_WM_WINDOW_TYPE_NORMAL
(or, as I think I understand from the code, otherwise inherits from a parent window), but I'd like it to be _NET_WM_WINDOW_TYPE_POPUP_MENU
in order to do something more generic in i3 & picom configs than matching on its class name.
I know I can xprop -set
, but how can/where should I do that having matched its class? Or is this a complete abuse, and I should do it differently?
OJFord
(2073 rep)
Oct 14, 2020, 10:47 AM
• Last activity: May 26, 2023, 02:24 PM
0
votes
2
answers
318
views
How to get full path names of all opened pdf files (in zathura) - like rofi does
I am trying to get the full path of every PDF that I have opened in the zathura viewer. I know it is possible, since with `rofi -show window`, I can see the full path. I have tried running ps -p $(pgrep zathura) -o command however, that only displays part of the name, depending on where I was, when...
I am trying to get the full path of every PDF that I have opened in the zathura viewer. I know it is possible, since with
rofi -show window
, I can see the full path.
I have tried running
ps -p $(pgrep zathura) -o command
however, that only displays part of the name, depending on where I was, when I opened the PDF.
It gets worse, when I use Vimtex, as in that case, it would display something like
zathura -x /usr/bin/nvim --headless -c "VimtexInverseSearch %{line} '%{input}'" --synctex-forward 224:1:/Path/to/part.tex main.pdf
where main.pdf need not be in the same place as part.tex (this happens if you use \include etc.).
Once gain, rofi does it right!
I could probably write a "convoluted" script that would search recursively in every parent directory of the part.tex file to find the main.pdf file...
Does anyone know how rofi does it?
Or more to the point, how I can do it?
-----------------------------------------------------------------------------------------
I am using
the X11 server
Arch Linux, 6.2.8-arch1-1
GNU bash, Version 5.1.16
Rofi Version: 1.7.5
Zathura version 0.5.2
Thanks all.
I.P
(221 rep)
Mar 30, 2023, 02:11 PM
• Last activity: Mar 31, 2023, 12:15 PM
0
votes
0
answers
255
views
All daemons show in 'rofi -show run' using qtile
I'm having a problem using rofi launcher with qtile Window Manager, the problem is that when I execute "rofi -show run" (with my keybind assignment) and I get a list of all the daemons availables on the system: [![enter image description here][1]][1] [1]: https://i.sstatic.net/3HvtN.png I had tried...
I'm having a problem using rofi launcher with qtile Window Manager, the problem is that when I execute "rofi -show run" (with my keybind assignment) and I get a list of all the daemons availables on the system:
I had tried OpenBox too as a Window Manager, and this problem don't happend.
So there are any solution to this problem?

Raxabi
(1 rep)
Aug 31, 2022, 10:16 PM
5
votes
2
answers
2469
views
Is it possible to tell linux to look for .desktop files in a directory?
I started using `rofi` as an application launcher using its `drun` function. It works fine, `.desktop` files in `/usr/share/applications` and `$HOME/.local/share/applications` both show on it with no problems. I've been wanting to change where I keep my `.desktop` files from `$HOME/.local/share/appl...
I started using
rofi
as an application launcher using its drun
function. It works fine, .desktop
files in /usr/share/applications
and $HOME/.local/share/applications
both show on it with no problems. I've been wanting to change where I keep my .desktop
files from $HOME/.local/share/applications
to just $HOME/desktop
, but I can't find any way to tell linux to look for .desktop
files in the directory I want. Is it even possible?
SandWood Jones
(63 rep)
Jan 19, 2021, 05:06 AM
• Last activity: Apr 22, 2022, 10:04 AM
1
votes
2
answers
18861
views
How to launch application with rofi using i3wm's exec?
I had [this issue](https://github.com/i3/i3/discussions/4782) and now I know how to solve it. I need to launch applications with **i3wm**'s `exec` command. ButI use **rofi** as launchmenu and I have no idea how to make it lauch applications with **i3wm**'s `exec` command ? I have binded **rofi** men...
I had [this issue](https://github.com/i3/i3/discussions/4782) and now I know how to solve it. I need to launch applications with **i3wm**'s
exec
command.
ButI use **rofi** as launchmenu and I have no idea how to make it lauch applications with **i3wm**'s exec
command ?
I have binded **rofi** menu using this config:
bindsym $mod+space exec --no-startup-id rofi -show combi -show-icons
How can I chive it ?
Thank you for help
Jan Černý
(1723 rep)
Jan 19, 2022, 04:43 PM
• Last activity: Jan 20, 2022, 03:13 PM
0
votes
1
answers
5346
views
Where is the rofi configuration file?
Where is the rofi configuration file? The various manual/help files are wrong. They state that it is /etc/rofi.rasi but this file does not exist on my system. Furthermore, ~/.config/rofi is empty. The variable XDG_CONFIG_HOME is unset. Obviously rofi is getting application information from somewhere...
Where is the rofi configuration file? The various manual/help files are wrong. They state that it is /etc/rofi.rasi but this file does not exist on my system. Furthermore, ~/.config/rofi is empty. The variable XDG_CONFIG_HOME is unset.
Obviously rofi is getting application information from somewhere because when it runs, it lists dozens of applications. The question is: where is getting that information from?
Note that the "configuration" information I am asking about here is the application startup commands that rofi uses to start applications. How does it know the names and command line startup for the applications that it starts? I am not asking about UI configuration settings, like what color is the menu or things like that.
My rofi activating binding is as follows:
set $menu rofi -show run
Tyler Durden
(6193 rep)
Aug 22, 2021, 05:20 PM
• Last activity: Aug 22, 2021, 07:37 PM
1
votes
1
answers
745
views
Why does pkill not work with rofi?
I want to toggle `rofi` an application launcher with one keybinding. I made a shell script, ```bash #!/bin/bash rofi -dpi 1 -modi drun -show drun -show-icons ``` And bound it to some key. This works but to toggle toggle it back to not running, I tried: ```bash pkill -0 rofi || rofi -dpi 1 -modi drun...
I want to toggle
rofi
an application launcher with one keybinding. I made a shell script,
#!/bin/bash
rofi -dpi 1 -modi drun -show drun -show-icons
And bound it to some key. This works but to toggle toggle it back to not running, I tried:
pkill -0 rofi || rofi -dpi 1 -modi drun -show drun -show-icons
That won't let rofi start to begin with. I tested pkill emacs || emacs
and that does toggle emacs. Could someone tell me how can I fix it for rofi? And, what does the argument "-0" do? I could not find it in the manual.
I did find [this](https://blog.wotw.pro/rofi-change-window-location/) ,
> I spent a decent chunk of time beating my head against this, and then I realized that rofi stores its pid. We can access the pid file via the config, which in turn gives us access to all the information we need. Before I get to the exciting stuff, though, it's important to mention safety. It's a really good idea to limit your process count (somehow) in case you create a runaway script. Speaking from experience, it could be half an hour before you can free up enough memory to switch to another tty and kill everything.
if [[ 10 -lt $(pgrep -c -f "$0") ]]; then
pkill -f rofi
pkill -f "$0"
exit 1
fi
I am not sure if this is exactly what I want or what does that code even do.
scribe
(143 rep)
Mar 21, 2021, 11:47 PM
• Last activity: Mar 22, 2021, 02:57 AM
2
votes
0
answers
153
views
Executing typed Rofi command, not what is selected?
Is there a way to execute the typed command in Rofi, instead of what is highlighted? I'm having an issue where I'm trying to execute ```gnome-screenshot -a```, but Rofi keeps selecting ```gnome-screenshot -d 2```, a command I had run some time in the past, out of the list of possible commands. I kno...
Is there a way to execute the typed command in Rofi, instead of what is highlighted? I'm having an issue where I'm trying to execute
-screenshot -a
, but Rofi keeps selecting -screenshot -d 2
, a command I had run some time in the past, out of the list of possible commands. I know I could delete the history, but surely there is a way to run the command written rather than the command selected?
Dargscisyhp
(261 rep)
Nov 9, 2020, 04:47 AM
9
votes
1
answers
2203
views
How multi-select work in rofi dmenu
I am using `rofi 1.5.4` Suppose I run the command echo -e "Option #1\nOption #2\nOption #3" | rofi -dmenu -multi-select | xargs -I{} echo {} What keys shall I use to select multiple menu item?
I am using
rofi 1.5.4
Suppose I run the command
echo -e "Option #1\nOption #2\nOption #3" | rofi -dmenu -multi-select | xargs -I{} echo {}
What keys shall I use to select multiple menu item?
Ahmad Ismail
(2998 rep)
Aug 14, 2020, 01:10 PM
• Last activity: Aug 26, 2020, 12:41 AM
0
votes
0
answers
30
views
How to echo a lozenge using bash?
I want to provide output like `zsh` powerline does: [![o][1]][1] My main goal is to output a lozenge indicating an active item in `rofi` which I'll be using as a dmenu. How can I echo "Active" as a lozenge the same way `zsh` does? [1]: https://i.sstatic.net/Ytmgl.png
I want to provide output like
My main goal is to output a lozenge indicating an active item in
zsh
powerline does:

rofi
which I'll be using as a dmenu. How can I echo "Active" as a lozenge the same way zsh
does?
Utkarsh Verma
(329 rep)
Aug 22, 2020, 04:13 AM
2
votes
1
answers
638
views
How to use terminal as program runner with FZF
I have a thought. Can I use a terminal as program runner? Instead of dmenu / rofi I was thinking to list all the programs with FZF, run the selection, and then close the terminal after it runs. I tried this but it's not working. `termite -e run.sh` or `urxvt -e zsh -c run.sh` `run.sh` consists of: `...
I have a thought. Can I use a terminal as program runner?
Instead of dmenu / rofi I was thinking to list all the programs with FZF, run the selection, and then close the terminal after it runs.
I tried this but it's not working.
termite -e run.sh
or urxvt -e zsh -c run.sh
run.sh
consists of:
#!/bin/zsh
preexe() { kill -9 $PPID }
exec $(whence -pm '*' | fzf) &!
Nora
(21 rep)
Feb 21, 2020, 01:59 AM
• Last activity: Feb 21, 2020, 04:31 PM
Showing page 1 of 20 total questions