From 761d8e1268eb7a2dfcbd63355d11904b256cebc3 Mon Sep 17 00:00:00 2001 From: L3D Date: Tue, 1 Aug 2023 22:13:23 +0200 Subject: [PATCH] Improve i3wm role wit multiuser support + adding rofi themes + customize i3bar + multiuser support + cleanup --- README.md | 28 +++--- defaults/main.yml | 29 ++++-- files/i3blocks/battery.py | 84 +++++++++++++++++ files/i3blocks/config | 32 ------- files/i3blocks/{volume => volume.sh} | 0 files/i3blocks/{wlan => wlan.sh} | 0 files/rofi/dracula_dark.rasi | 133 +++++++++++++++++++++++++++ files/rofi/spotlight-dark.rasi | 98 ++++++++++++++++++++ files/rofi/spotlight.rasi | 98 ++++++++++++++++++++ tasks/config.yml | 80 +++++++++------- tasks/main.yml | 5 +- templates/i3blocks_config.j2 | 52 +++++++++++ 12 files changed, 553 insertions(+), 86 deletions(-) create mode 100644 files/i3blocks/battery.py delete mode 100644 files/i3blocks/config rename files/i3blocks/{volume => volume.sh} (100%) rename files/i3blocks/{wlan => wlan.sh} (100%) create mode 100644 files/rofi/dracula_dark.rasi create mode 100644 files/rofi/spotlight-dark.rasi create mode 100644 files/rofi/spotlight.rasi create mode 100644 templates/i3blocks_config.j2 diff --git a/README.md b/README.md index 8d301d9..a5f5beb 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,9 @@ Install and deploy a basic configuration of [I3 Window Manager](https://i3wm.org Optionally configure your resolution, which applications will be bound to which screen and what will be included in the autostart.
If you want to use wayland instead of xorg, think about using [sway](https://swaywm.org/) as window manager. The corresponding ansible is located on [github.com/roles-ansible/role-sway](https://github.com/roles-ansible/role-sway.git). -[![MIT License](https://raw.githubusercontent.com/chaos-bodensee/role-i3wm/master/.github/license.svg?sanitize=true)](https://github.com/chaos-bodensee/role-i3wm/blob/master/LICENSE) -[![MIT License](https://raw.githubusercontent.com/chaos-bodensee/role-i3wm/master/.github/galaxy.svg?sanitize=true)](https://galaxy.ansible.com/do1jlr/i3wm) - ### Get it directly from Ansible Galaxy ```bash -$ ansible-galaxy install do1jlr.i3wm +$ ansible-galaxy install l3d.i3wm ``` Role Variables @@ -22,22 +19,23 @@ $ ansible-galaxy install do1jlr.i3wm For a good overview about possible variables, please have a look into ``defaults/main.yml``. - Example Playbook ----------------- - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - +## Example Usage ```yaml - - name: install i3wm on localhost - hosts: localhost - vars_files: - - vars/main.yml - roles: - - {role: do1jlr.i3wm, tags[i3,i3wm]} + - name: install i3wm on localhost + hosts: localhost + vars_files: + - vars/main.yml + roles: + - {role: l3d.i3wm, tags[i3, i3wm]} ``` *`vars/main.yml`* ```yaml + # User List for i3wm config + i3wm_user_list: + - 'alice' + - 'bob' + # background image i3_desktop_background: "~/Bilder/wallpaper.jpg" diff --git a/defaults/main.yml b/defaults/main.yml index 1d41680..d52dfb2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -7,7 +7,8 @@ i3_keybindings_extra: [] # key: $mod+Shift+F10 # exec: --no-startup-id touch /tmp/example.txt -i3_monitors: [] # see: xrandr +i3_monitors: [] +# see: xrandr # - monitor: # id: 1 # output: "VGA-1" @@ -27,18 +28,32 @@ i3_run_on_startup: [] # - foo # - bar -# which user are we? -i3wm_user: "{{ ansible_user_id }}" +# deploy config to these users: +i3wm_user_list: + - user: "{{ ansible_user_id }}" + home: "{{ ansible_env.HOME | default('/home/{{ ansible_user_id }}') }}" ## set default font size -i3_font_size: 9 +i3_font_size: 10 i3_focus_follows_mouse: true # set i3lock options -i3lock_options: "i3lock --image=/home/{{ i3wm_user }}/.config/lockscreen.png --color 000000" +i3lock_options: "i3lock --image={{ i3wm_usr.home }}/.config/lockscreen.png --color 000000" # use fancy background -i3_desktop_background: "/home/{{ i3wm_user }}/.config/background.png" +i3_desktop_background: "{{ i3wm_usr.home }}/.config/background.png" + +# i3blocks options +i3_i3blocks_options: + weather: true + audio_volume: true + wifisignal: true + ipaddress: true + clock: true + battery: true + ddate: true + +i3_rofi_config_file: 'files/rofi/dracula_dark.rasi' i3_terminal: "terminator" @@ -50,7 +65,7 @@ i3wm_copy_wallpapers: true disable_screensaver: true enable_lock_after_time: false -lock_after_time: '200' # minutes to wait until your screen is locked +lock_after_time: '90' # minutes to wait until your screen is locked # version check for this role? submodules_versioncheck: true diff --git a/files/i3blocks/battery.py b/files/i3blocks/battery.py new file mode 100644 index 0000000..d7a7562 --- /dev/null +++ b/files/i3blocks/battery.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +""" +battery for i3blocks +""" + +import subprocess +import sys + +def get_battery_info(): + status = subprocess.check_output(['acpi'], universal_newlines=True) + + if not status: + # -> keine Batterie gefunden + text_output = "\uf00d \uf240" + battery_percent = 100 + else: + # -> auswertung der batteriedaten + batteries = status.strip().split("\n") + state_batteries = [] + battery_percent_batteries = [] + + for battery in batteries: + if battery: + state_batteries.append(battery.split(": ")[1].split(", ")[0]) + commasplitstatus = battery.split(", ") + battery_percent_batteries.append(int(commasplitstatus[1].rstrip("%\n"))) + + state = state_batteries[0] + battery_percent = int(sum(battery_percent_batteries) / len(battery_percent_batteries)) + + # stands for charging + fa_lightning = "\uf0e7" + + # stands for plugged in + fa_plug = "\uf1e6" + + text_output = "" + battery_remaining_time = "" + + if state == "Discharging": + battery_time = batteries[0].split()[-2] + battery_remaining_time = f" ({battery_time})" + elif state == "Full": + text_output = fa_plug + " " + elif state == "Unknown": + text_output = "\uf128 " + else: + text_output = fa_lightning + " " + fa_plug + " " + + def get_color(percent): + """ + -> color based on battery state + """ + color_mapping = { + 16: "#FFFFFF", + 24: "#FF3300", + 32: "#FF6600", + 40: "#FF9900", + 50: "#FFCC00", + 60: "#FFFF00", + 70: "#FFFF33", + 80: "#FFFF66" + } + + for threshold, color_code in color_mapping.items(): + if percent < threshold: + return color_code + + return "#FFFFFF" + + battery_form_string = '{}%' + text_output += battery_form_string.format(get_color(battery_percent), battery_percent) + text_output += battery_remaining_time + + return text_output + +if __name__ == "__main__": + text_output = get_battery_info() + print(text_output) + print(text_output) + + if "battery_percent" in locals() and battery_percent < 16: + sys.exit(33) + diff --git a/files/i3blocks/config b/files/i3blocks/config deleted file mode 100644 index b82d36c..0000000 --- a/files/i3blocks/config +++ /dev/null @@ -1,32 +0,0 @@ -command=~/.config/i3blocks/$BLOCK_NAME -separator_block_width=15 -markup=pango - -[weather] -command=curl -Ss 'https://wttr.in?format="%l:+%c%t+%w"' | xargs echo -interval=600 -color=#A4C2F4 - -[volume] -interval=30 -signal=10 - -[wlan] -interval=1 -signal=10 - -[ip] -command=hostname -i | awk '{ print " IPv4: " $1 }' -interval=120 -label=🖥️ -color=#91E78B - -[clock] -label=🕒 -command=date --iso-8601=seconds -interval=1 - -[ddate] -label=🚀 -command=ddate +'%{%A, %d %B%}, %Y%N, Celebrate %H' -interval=120 diff --git a/files/i3blocks/volume b/files/i3blocks/volume.sh similarity index 100% rename from files/i3blocks/volume rename to files/i3blocks/volume.sh diff --git a/files/i3blocks/wlan b/files/i3blocks/wlan.sh similarity index 100% rename from files/i3blocks/wlan rename to files/i3blocks/wlan.sh diff --git a/files/rofi/dracula_dark.rasi b/files/rofi/dracula_dark.rasi new file mode 100644 index 0000000..a81a4b5 --- /dev/null +++ b/files/rofi/dracula_dark.rasi @@ -0,0 +1,133 @@ +/*Dracula theme based on the Purple official rofi theme*/ + +* { + font: "Jetbrains Mono 12"; + foreground: #f8f8f2; + background-color: #282a36; + active-background: #6272a4; + urgent-background: #ff5555; + urgent-foreground: #282a36; + selected-background: @active-background; + selected-urgent-background: @urgent-background; + selected-active-background: @active-background; + separatorcolor: @active-background; + bordercolor: @active-background; +} + +configuration { + show-icons: true; + display-drun: ""; + disable-history: false; +} + +#window { + background-color: @background-color; + border: 3; + border-radius: 6; + border-color: @bordercolor; + padding: 15; +} +#mainbox { + border: 0; + padding: 0; +} +#message { + border: 0px; + border-color: @separatorcolor; + padding: 1px; +} +#textbox { + text-color: @foreground; +} +#listview { + fixed-height: 0; + border: 0px; + border-color: @bordercolor; + spacing: 2px ; + scrollbar: false; + padding: 2px 0px 0px ; +} +#element { + border: 0; + padding: 3px ; +} +#element.normal.normal { + background-color: @background-color; + text-color: @foreground; +} +#element.normal.urgent { + background-color: @urgent-background; + text-color: @urgent-foreground; +} +#element.normal.active { + background-color: @active-background; + text-color: @foreground; +} +#element.selected.normal { + background-color: @selected-background; + text-color: @foreground; +} +#element.selected.urgent { + background-color: @selected-urgent-background; + text-color: @foreground; +} +#element.selected.active { + background-color: @selected-active-background; + text-color: @foreground; +} +#element.alternate.normal { + background-color: @background-color; + text-color: @foreground; +} +#element.alternate.urgent { + background-color: @urgent-background; + text-color: @foreground; +} +#element.alternate.active { + background-color: @active-background; + text-color: @foreground; +} +#scrollbar { + width: 2px ; + border: 0; + handle-width: 8px ; + padding: 0; +} +#sidebar { + border: 2px dash 0px 0px ; + border-color: @separatorcolor; +} +#button.selected { + background-color: @selected-background; + text-color: @foreground; +} +#inputbar { + spacing: 0; + text-color: @foreground; + padding: 1px ; +} +#case-indicator { + spacing: 0; + text-color: @foreground; +} +#entry { + spacing: 0; + text-color: @foreground; +} +#prompt { + spacing: 0; + text-color: @foreground; +} +#inputbar { + children: [ prompt,textbox-prompt-colon,entry,case-indicator ]; +} +#textbox-prompt-colon { + expand: false; + str: ">"; + margin: 0px 0.3em 0em 0em ; + text-color: @foreground; +} +element-text, element-icon { + background-color: inherit; + text-color: inherit; +} diff --git a/files/rofi/spotlight-dark.rasi b/files/rofi/spotlight-dark.rasi new file mode 100644 index 0000000..0e27360 --- /dev/null +++ b/files/rofi/spotlight-dark.rasi @@ -0,0 +1,98 @@ +/******************************************************************************* + * MACOS SPOTLIGHT LIKE DARK THEME FOR ROFI + * User : LR-Tech + * Theme Repo : https://github.com/lr-tech/rofi-themes-collection + *******************************************************************************/ + +* { + font: "Montserrat 12"; + + bg0: #242424E6; + bg1: #7E7E7E80; + bg2: #0860f2E6; + + fg0: #DEDEDE; + fg1: #FFFFFF; + fg2: #DEDEDE80; + + background-color: transparent; + text-color: @fg0; + + margin: 0; + padding: 0; + spacing: 0; +} + +window { + background-color: @bg0; + + location: center; + width: 640; + border-radius: 8; +} + +inputbar { + font: "Montserrat 20"; + padding: 12px; + spacing: 12px; + children: [ icon-search, entry ]; +} + +icon-search { + expand: false; + filename: "search"; + size: 28px; +} + +icon-search, entry, element-icon, element-text { + vertical-align: 0.5; +} + +entry { + font: inherit; + + placeholder : "Search"; + placeholder-color : @fg2; +} + +message { + border: 2px 0 0; + border-color: @bg1; + background-color: @bg1; +} + +textbox { + padding: 8px 24px; +} + +listview { + lines: 10; + columns: 1; + + fixed-height: false; + border: 1px 0 0; + border-color: @bg1; +} + +element { + padding: 8px 16px; + spacing: 16px; + background-color: transparent; +} + +element normal active { + text-color: @bg2; +} + +element selected normal, element selected active { + background-color: @bg2; + text-color: @fg1; +} + +element-icon { + size: 1em; +} + +element-text { + text-color: inherit; +} diff --git a/files/rofi/spotlight.rasi b/files/rofi/spotlight.rasi new file mode 100644 index 0000000..395e3f0 --- /dev/null +++ b/files/rofi/spotlight.rasi @@ -0,0 +1,98 @@ +/******************************************************************************* + * MACOS SPOTLIGHT LIKE THEME FOR ROFI + * User : LR-Tech + * Theme Repo : https://github.com/lr-tech/rofi-themes-collection + *******************************************************************************/ + +* { + font: "Montserrat 12"; + + bg0: #F5F5F5BF; + bg1: #7E7E7E80; + bg2: #0860F2E6; + + fg0: #242424; + fg1: #FFFFFF; + fg2: #24242480; + + background-color: transparent; + text-color: @fg0; + + margin: 0; + padding: 0; + spacing: 0; +} + +window { + background-color: @bg0; + + location: center; + width: 640; + border-radius: 8; +} + +inputbar { + font: "Montserrat 20"; + padding: 12px; + spacing: 12px; + children: [ icon-search, entry ]; +} + +icon-search { + expand: false; + filename: "search"; + size: 28px; +} + +icon-search, entry, element-icon, element-text { + vertical-align: 0.5; +} + +entry { + font: inherit; + + placeholder : "Search"; + placeholder-color : @fg2; +} + +message { + border: 2px 0 0; + border-color: @bg1; + background-color: @bg1; +} + +textbox { + padding: 8px 24px; +} + +listview { + lines: 10; + columns: 1; + + fixed-height: false; + border: 1px 0 0; + border-color: @bg1; +} + +element { + padding: 8px 16px; + spacing: 16px; + background-color: transparent; +} + +element normal active { + text-color: @bg2; +} + +element selected normal, element selected active { + background-color: @bg2; + text-color: @fg1; +} + +element-icon { + size: 1em; +} + +element-text { + text-color: inherit; +} diff --git a/tasks/config.yml b/tasks/config.yml index c1ce8c4..47a3c3c 100644 --- a/tasks/config.yml +++ b/tasks/config.yml @@ -2,71 +2,89 @@ - name: Creates directory become: true ansible.builtin.file: - path: '/home/{{ i3wm_user }}/.config' + path: '{{ i3wm_usr.home }}/.config' state: directory mode: 0750 - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" - name: Create i3 config folder become: true ansible.builtin.file: - path: '/home/{{ i3wm_user }}/.config/i3/' + path: '{{ i3wm_usr.home }}/.config/i3/' state: directory - mode: 0755 - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + mode: 0750 + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" - name: Copy multiple images ansible.builtin.copy: src: "{{ item.src }}" dest: "{{ item.dest }}" mode: 0644 - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" with_items: - - { src: 'files/background.png', dest: "/home/{{ i3wm_user }}/.config/background.png" } - - { src: 'files/lockscreen.png', dest: '/home/{{ i3wm_user }}/.config/lockscreen.png' } + - { src: 'files/background.png', dest: "{{ i3wm_usr.home }}/.config/background.png" } + - { src: 'files/lockscreen.png', dest: '{{ i3wm_usr.home }}/.config/lockscreen.png' } when: i3wm_copy_wallpapers | bool - name: Copy and validate i3wm config file become: true ansible.builtin.template: src: templates/config.j2 - dest: "/home/{{ i3wm_user }}/.config/i3/config" + dest: "{{ i3wm_usr.home }}/.config/i3/config" mode: 0600 backup: true validate: i3 -C -c %s - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" -# todo: rewrite user stuff and support multiple users -- name: Mkdir ~/.config/i3blocks/ +- name: Create directory ~/.config/i3blocks/ become: true ansible.builtin.file: - path: "/home/{{ i3wm_user }}/.config/i3blocks/" + path: "{{ i3wm_usr.home }}/.config/i3blocks/" state: directory - mode: '0755' - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + mode: '0750' + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" -- name: Copy i3blocks config +- name: Generate i3blocks config become: true - ansible.builtin.copy: - src: "files/i3blocks/config" - dest: "/home/{{ i3wm_user }}/.config/i3blocks/config" + ansible.builtin.template: + src: 'templates/i3blocks_config.j2' + dest: "{{ i3wm_usr.home }}/.config/i3blocks/config" mode: 0640 - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" - name: Copy i3blocks config become: true ansible.builtin.copy: src: "files/i3blocks/{{ item }}" - dest: "/home/{{ i3wm_user }}/.config/i3blocks/{{ item }}" + dest: "{{ i3wm_usr.home }}/.config/i3blocks/{{ item }}" mode: 0750 - owner: "{{ i3wm_user }}" - group: "{{ i3wm_user }}" + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" with_items: - - 'volume' - - 'wlan' + - 'volume.sh' + - 'wlan.sh' + - 'battery.py' + +- name: Create rofi config folder + become: true + ansible.builtin.file: + path: '{{ i3wm_usr.home }}/.config/rofi/' + state: directory + mode: 0750 + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" + +- name: Copy rofi config + become: true + ansible.builtin.copy: + src: "{{ i3_rofi_config_file }}" + dest: "{{ i3wm_usr.home }}/.config/rofi/config.rasi" + mode: 0640 + owner: "{{ i3wm_usr.user }}" + group: "{{ i3wm_usr.user }}" diff --git a/tasks/main.yml b/tasks/main.yml index 585b686..2598246 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,7 +1,7 @@ --- - name: Run optional versionscheck ansible.builtin.include_tasks: versioncheck.yml - when: submodules_versionchecki | bool + when: submodules_versioncheck | bool - name: Register variables ansible.builtin.import_tasks: variables.yml @@ -20,3 +20,6 @@ - name: Create i3 config file ansible.builtin.include_tasks: config.yml + loop: "{{ i3wm_user_list | flatten(1) }}" + loop_control: + loop_var: i3wm_usr diff --git a/templates/i3blocks_config.j2 b/templates/i3blocks_config.j2 new file mode 100644 index 0000000..9bc2286 --- /dev/null +++ b/templates/i3blocks_config.j2 @@ -0,0 +1,52 @@ +command=~/.config/i3blocks/$BLOCK_NAME +separator_block_width=18 +markup=pango + +{% if i3_i3blocks_options.weather | bool %} +[weather] +command=curl -Ss 'https://wttr.in?format="%l:+%c%t+%w"' | xargs echo +interval=600 +color=#A4C2F4 +{% endif %} + +{% if i3_i3blocks_options.audio_volume | bool %} +[volume] +command={{ i3wm_usr.home }}/.config/i3blocks/volume.sh +interval=30 +signal=10 +{% endif %} + +{% if i3_i3blocks_options.wifisignal | bool %} +[wlan] +command={{ i3wm_usr.home }}/.config/i3blocks/wlan.sh +interval=1 +signal=10 +{% endif %} + +{% if i3_i3blocks_options.ipaddress | bool %} +[ip] +command=hostname -i | awk '{ print " IPv4: " $1 }' +interval=120 +label=🖥️ +{% endif %} + +{% if i3_i3blocks_options.clock | bool %} +[clock] +command=date --rfc-3339=seconds +color=#88ff0a +interval=1 +{% endif %} + +{% if i3_i3blocks_options.battery | bool %} +[battery] +command={{ i3wm_usr.home }}/.config/i3blocks/battery.py +markup=pango +interval=30 +{% endif %} + +{% if i3_i3blocks_options.ddate | bool %} +[ddate] +label=🚀 +command=ddate +'%A, %d %B, %Y%N, Celebrate %H' +interval=120 +{% endif %}