fix: crates
This commit is contained in:
parent
ea70650c45
commit
eb3e637462
15 changed files with 487 additions and 14 deletions
|
@ -1,11 +1,7 @@
|
|||
# Crate Manifest for Dotfile Processor
|
||||
|
||||
[crate]
|
||||
name = "dotfile-processor"
|
||||
name = "common"
|
||||
description = "A versatile crate for managing dotfiles and system configurations."
|
||||
author = "Strix"
|
||||
|
||||
# List of packages to be installed
|
||||
[[packages]]
|
||||
name = "git"
|
||||
description = "Version control system"
|
||||
|
@ -24,5 +20,9 @@ user = "root"
|
|||
command = "sh ./scripts/pam_wheel.sh"
|
||||
description = "Pam wheel setup"
|
||||
|
||||
[[actions.command]]
|
||||
command = "git config --global user.name Strix && git config --global user.email strix@saluco.nl"
|
||||
description = "git setup"
|
||||
|
||||
[metadata]
|
||||
repository = "https://git.saluco.nl/strix/dotfiles"
|
||||
|
|
62
crates/i3/crate.toml
Normal file
62
crates/i3/crate.toml
Normal file
|
@ -0,0 +1,62 @@
|
|||
[crate]
|
||||
name = "i3"
|
||||
description = "install and setup i3"
|
||||
|
||||
[[packages]]
|
||||
name = "i3"
|
||||
|
||||
[[packages]]
|
||||
name = "i3lock"
|
||||
|
||||
[[packages]]
|
||||
name = "i3status"
|
||||
|
||||
[[packages]]
|
||||
name = "libpulse"
|
||||
require = ["distro:arch"]
|
||||
|
||||
[[packages]]
|
||||
name = "brightnessctl"
|
||||
|
||||
[[packages]]
|
||||
name = "xss-lock"
|
||||
|
||||
[[packages]]
|
||||
name = "dex"
|
||||
|
||||
[[packages]]
|
||||
name = "maim"
|
||||
|
||||
[[packages]]
|
||||
name = "dmenu"
|
||||
|
||||
[[packages]]
|
||||
name = "gnome-keyring"
|
||||
|
||||
[[packages]]
|
||||
name = "feh"
|
||||
|
||||
[[packages]]
|
||||
name = "picom"
|
||||
|
||||
[[actions.link]]
|
||||
src = "files/i3config"
|
||||
dest = "~/.config/i3/config"
|
||||
|
||||
[[actions.link]]
|
||||
src = "files/i3status_config"
|
||||
dest = "~/.config/i3status/config"
|
||||
|
||||
[[actions.link]]
|
||||
src = "files/picom.conf"
|
||||
dest = "~/.config/picom.conf"
|
||||
|
||||
[[actions.command]]
|
||||
user = "root"
|
||||
command = "[ -d '/etc/X11/xorg.conf.d' ] || mkdir -p /etc/X11/xorg.conf.d/"
|
||||
description = "ensure /etc/X11/xorg.conf.d"
|
||||
|
||||
[[actions.command]]
|
||||
user = "root"
|
||||
command = "cp files/touchpad.conf /etc/X11/xorg.conf.d/40-touchpad.conf"
|
||||
description = "copy touchpad config to /etc/X11/xorg.conf.d"
|
206
crates/i3/files/i3config
Normal file
206
crates/i3/files/i3config
Normal file
|
@ -0,0 +1,206 @@
|
|||
#######################
|
||||
## Strix' i3 config ##
|
||||
## Mar 22, 2023 ##
|
||||
## mutation: 1m ##
|
||||
#######################
|
||||
|
||||
## Mostly similar to i3's config yet differs
|
||||
|
||||
# Useful variables:
|
||||
# This section probably gets changed a lot
|
||||
# ---
|
||||
set $terminal alacritty
|
||||
set $screen_lock i3lock -c "#111111" --nofork
|
||||
set $appmenu i3-dmenu-desktop
|
||||
|
||||
set $screenshot maim -s | xclip -selection clipboard -t image/png
|
||||
|
||||
set $font pango:monospace 8
|
||||
|
||||
# Startup Applications:
|
||||
# Things that will startup when starting i3.
|
||||
# ---
|
||||
exec_always --no-startup-id dex --autostart --environment i3
|
||||
exec_always --no-startup-id nm-applet
|
||||
exec_always --no-startup-id xss-lock --transfer-sleep-lock -- $screen_lock
|
||||
exec_always --no-startup-id gnome-keyring-daemon --start --components=ssh,secrets,pkcs11
|
||||
exec_always --no-startup-id feh --bg-fill ~/Pictures/wallpaper.jpg
|
||||
exec_always --no-startup-id picom
|
||||
|
||||
# Gaps & Borders:
|
||||
# ---
|
||||
gaps inner 10
|
||||
smart_gaps on
|
||||
|
||||
default_border pixel 1
|
||||
hide_edge_borders smart_no_gaps
|
||||
|
||||
# Extra variables:
|
||||
# Only need changing for very specific installations.
|
||||
# ---
|
||||
set $audio_volume_up XF86AudioRaiseVolume
|
||||
set $audio_volume_down XF86AudioLowerVolume
|
||||
set $audio_mute XF86AudioMute
|
||||
set $audio_mute_mic XF86AudioMicMute
|
||||
|
||||
set $brightness_up XF86MonBrightnessUp
|
||||
set $brightness_down XF86MonBrightnessDown
|
||||
|
||||
set $ws_1 "1:main"
|
||||
set $ws_2 "2:term"
|
||||
set $ws_3 "3:docs"
|
||||
set $ws_4 "4:mail"
|
||||
set $ws_5 "5"
|
||||
set $ws_6 "6"
|
||||
set $ws_7 "7"
|
||||
set $ws_8 "8"
|
||||
set $ws_9 "9:bg"
|
||||
set $ws_10 "10:misc"
|
||||
|
||||
set $meta_refresh_statusbar killall -SIGUSR1 i3status
|
||||
bar {
|
||||
strip_workspace_numbers yes
|
||||
status_command i3status
|
||||
}
|
||||
|
||||
# END OF CONFIG
|
||||
|
||||
set $mod Mod4
|
||||
set $alt Mod1
|
||||
|
||||
# Customization
|
||||
|
||||
# class border backgr. text indic. child_border
|
||||
client.focused #81A1C1 #81A1C1 #ffffff #D8DEE9
|
||||
client.focused_inactive #2E3440 #2E3440 #88C0D0 #454948
|
||||
client.unfocused #2E3440 #2E3440 #88C0D0 #454948
|
||||
client.urgent #D08770 #3B4252 #ffffff #268BD2
|
||||
client.placeholder #000000 #0c0c0c #ffffff #000000
|
||||
client.background #3B4252
|
||||
|
||||
# Generic
|
||||
floating_modifier $mod
|
||||
tiling_drag modifier titlebar
|
||||
font $font
|
||||
|
||||
# Open a terminal
|
||||
bindsym $mod+Return exec $terminal
|
||||
|
||||
# Kill current window
|
||||
bindsym $mod+$alt+q kill
|
||||
|
||||
# Open app menu
|
||||
bindsym $mod+d exec --no-startup-id $appmenu
|
||||
|
||||
# Lock screen
|
||||
bindsym $mod+l exec --no-startup-id $screen_lock
|
||||
|
||||
# Screenshots
|
||||
bindsym Print exec --no-startup-id $screenshot
|
||||
|
||||
# Audio
|
||||
bindsym $audio_volume_up exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $meta_refresh_statusbar
|
||||
bindsym $audio_volume_down exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $meta_refresh_statusbar
|
||||
bindsym $audio_mute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $meta_refresh_statusbar
|
||||
bindsym $audio_mute_mic exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $meta_refresh_statusbar
|
||||
|
||||
# Brightness
|
||||
bindsym $brightness_up exec --no-startup-id brightnessctl set +5% && $meta_refresh_statusbar
|
||||
bindsym $brightness_down exec --no-startup-id brightnessctl set 5%- && $meta_refresh_statusbar
|
||||
|
||||
# Change focused window
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Right focus right
|
||||
|
||||
# Move focused window
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Right move right
|
||||
|
||||
# Splits
|
||||
bindsym $mod+Shift+h split h
|
||||
bindsym $mod+Shift+v split v
|
||||
|
||||
# Change container layout
|
||||
bindsym $mod+Shift+s layout stacking
|
||||
bindsym $mod+Shift+t layout tabbed
|
||||
bindsym $mod+Shift+d layout toggle split
|
||||
|
||||
# Make current window fullscreen
|
||||
bindsym $mod+Shift+f fullscreen toggle
|
||||
|
||||
# Floating stuff
|
||||
bindsym $mod+space focus mode_toggle
|
||||
bindsym $mod+Shift+space floating toggle
|
||||
|
||||
# Scratchpad
|
||||
bindsym $mod+Shift+minus move scratchpad
|
||||
bindsym $mod+minus scratchpad show
|
||||
|
||||
# Switch to workspace
|
||||
bindsym $mod+1 workspace $ws_1
|
||||
bindsym $mod+2 workspace $ws_2
|
||||
bindsym $mod+3 workspace $ws_3
|
||||
bindsym $mod+4 workspace $ws_4
|
||||
bindsym $mod+5 workspace $ws_5
|
||||
bindsym $mod+6 workspace $ws_6
|
||||
bindsym $mod+7 workspace $ws_7
|
||||
bindsym $mod+8 workspace $ws_8
|
||||
bindsym $mod+9 workspace $ws_9
|
||||
bindsym $mod+0 workspace $ws_10
|
||||
|
||||
# Move focused container to workspace
|
||||
bindsym $mod+Shift+1 move container to workspace $ws_1
|
||||
bindsym $mod+Shift+2 move container to workspace $ws_2
|
||||
bindsym $mod+Shift+3 move container to workspace $ws_3
|
||||
bindsym $mod+Shift+4 move container to workspace $ws_4
|
||||
bindsym $mod+Shift+5 move container to workspace $ws_5
|
||||
bindsym $mod+Shift+6 move container to workspace $ws_6
|
||||
bindsym $mod+Shift+7 move container to workspace $ws_7
|
||||
bindsym $mod+Shift+8 move container to workspace $ws_8
|
||||
bindsym $mod+Shift+9 move container to workspace $ws_9
|
||||
bindsym $mod+Shift+0 move container to workspace $ws_10
|
||||
|
||||
# Move through workspaces
|
||||
bindsym $mod+$alt+Left workspace prev
|
||||
bindsym $mod+$alt+Right workspace next
|
||||
|
||||
# WM stuff
|
||||
# reload i3 config
|
||||
bindsym $mod+$alt+c reload
|
||||
# restart i3
|
||||
bindsym $mod+$alt+r restart
|
||||
# exit i3
|
||||
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'Exit i3?' -B 'Yes, exit i3' 'i3-msg exit'"
|
||||
|
||||
# Modes
|
||||
bindsym $mod+r mode resize
|
||||
mode "resize" {
|
||||
bindsym $nav_left resize shrink width 10 px or 10 ppt
|
||||
bindsym $nav_down resize grow height 10 px or 10 ppt
|
||||
bindsym $nav_up resize shrink height 10 px or 10 ppt
|
||||
bindsym $nav_right resize grow width 10 px or 10 ppt
|
||||
bindsym Left resize shrink width 10 px or 10 ppt
|
||||
bindsym Down resize grow height 10 px or 10 ppt
|
||||
bindsym Up resize shrink height 10 px or 10 ppt
|
||||
bindsym Right resize grow width 10 px or 10 ppt
|
||||
|
||||
bindsym Return mode "default"
|
||||
bindsym Escape mode "default"
|
||||
bindsym $mod+r mode "default"
|
||||
}
|
||||
|
||||
bindsym $mod+s mode "session"
|
||||
mode "session" {
|
||||
bindsym l exec --no-startup-id $lock, mode "default"
|
||||
bindsym e exec --no-startup-id i3-msg exit, mode "default"
|
||||
bindsym Shift+r exec --no-startup-id systemctl reboot, mode "default"
|
||||
bindsym Shift+s exec --no-startup-id systemctl poweroff -i, mode "default"
|
||||
|
||||
bindsym Return mode "default"
|
||||
bindsym Escape mode "default"
|
||||
bindsym $mod+s mode "default"
|
||||
}
|
57
crates/i3/files/i3status_config
Normal file
57
crates/i3/files/i3status_config
Normal file
|
@ -0,0 +1,57 @@
|
|||
general {
|
||||
output_format = "i3bar"
|
||||
colors = true
|
||||
interval = 5
|
||||
}
|
||||
|
||||
order += "ipv6"
|
||||
order += "wireless wlp58s0"
|
||||
order += "battery 0"
|
||||
order += "disk /"
|
||||
order += "memory"
|
||||
order += "load"
|
||||
order += "tztime local"
|
||||
|
||||
wireless wlp58s0 {
|
||||
format_up = "W: (%quality at %essid, %bitrate) %ip"
|
||||
format_down = "W: down"
|
||||
}
|
||||
|
||||
battery 0 {
|
||||
format = "%status %percentage %remaining %emptytime"
|
||||
format_down = "No battery"
|
||||
status_chr = "⚡ CHR"
|
||||
status_bat = "🔋 BAT"
|
||||
status_unk = "? UNK"
|
||||
status_full = "☻ FULL"
|
||||
path = "/sys/class/power_supply/BAT%d/uevent"
|
||||
low_threshold = 10
|
||||
}
|
||||
|
||||
tztime local {
|
||||
format = "%Y-%m-%d %H:%M:%S"
|
||||
hide_if_equals_localtime = false
|
||||
}
|
||||
|
||||
tztime berlin {
|
||||
format = "%Y-%m-%d %H:%M:%S %Z"
|
||||
timezone = "Europe/Berlin"
|
||||
}
|
||||
|
||||
load {
|
||||
format = "%5min"
|
||||
}
|
||||
|
||||
memory {
|
||||
format = "%used"
|
||||
threshold_degraded = "10%"
|
||||
format_degraded = "MEMORY: %free"
|
||||
}
|
||||
|
||||
disk "/" {
|
||||
format = "%free"
|
||||
}
|
||||
|
||||
read_file uptime {
|
||||
path = "/proc/uptime"
|
||||
}
|
9
crates/i3/files/picom.conf
Normal file
9
crates/i3/files/picom.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
inactive-opacity = 0.75;
|
||||
|
||||
blur: {
|
||||
method = "box";
|
||||
size = 10;
|
||||
background = false;
|
||||
background-frame = false;
|
||||
background-fixed = false;
|
||||
}
|
8
crates/i3/files/touchpad.conf
Normal file
8
crates/i3/files/touchpad.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
Section "InputClass"
|
||||
Identifier "libinput touchpad catchall"
|
||||
MatchIsTouchpad "on"
|
||||
MatchDevicePath "/dev/input/event*"
|
||||
Driver "libinput"
|
||||
Option "NaturalScrolling" "True"
|
||||
Option "Tapping" "on"
|
||||
EndSection
|
|
@ -1,6 +1,5 @@
|
|||
[crate]
|
||||
name = "ssh"
|
||||
author = "Strix"
|
||||
description = "fixes the ssh files"
|
||||
|
||||
[[actions.command]]
|
||||
|
|
15
crates/vim/crate.toml
Normal file
15
crates/vim/crate.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
[crate]
|
||||
name = "vim"
|
||||
description = "install & configure vim"
|
||||
|
||||
|
||||
[[packages]]
|
||||
name = "neovim"
|
||||
|
||||
[[actions.link]]
|
||||
src = "./ideavimrc"
|
||||
dest = "~/.ideavimrc"
|
||||
|
||||
[[actions.link]]
|
||||
src = "./init.vim"
|
||||
dest = "~/.config/nvim/init.vim"
|
10
crates/vim/ideavimrc
Normal file
10
crates/vim/ideavimrc
Normal file
|
@ -0,0 +1,10 @@
|
|||
source ~/.vimrc
|
||||
|
||||
set scrolloff=5
|
||||
set incsearch
|
||||
|
||||
map Q gq
|
||||
|
||||
Plug 'machakann/vim-highlightedyank'
|
||||
Plug 'tpope/vim-commentary'
|
||||
Plug 'wellle/targets.vim'
|
27
crates/vim/init.vim
Normal file
27
crates/vim/init.vim
Normal file
|
@ -0,0 +1,27 @@
|
|||
" vim preferences
|
||||
set number
|
||||
set relativenumber
|
||||
syntax on
|
||||
|
||||
" No arrow keys
|
||||
noremap <Up> <Nop>
|
||||
noremap <Down> <Nop>
|
||||
noremap <Left> <Nop>
|
||||
noremap <Right> <Nop>
|
||||
|
||||
" ensure vim-plug
|
||||
let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
|
||||
if empty(glob(data_dir . '/autoload/plug.vim'))
|
||||
silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
|
||||
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
|
||||
endif
|
||||
|
||||
call plug#begin()
|
||||
|
||||
Plug 'ThePrimeagen/vim-be-good'
|
||||
Plug 'machakann/vim-highlightedyank'
|
||||
Plug 'tpope/vim-commentary'
|
||||
Plug 'wellle/targets.vim'
|
||||
Plug 'vim-scripts/loremipsum'
|
||||
|
||||
call plug#end()
|
14
crates/zsh/crate.toml
Normal file
14
crates/zsh/crate.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[crate]
|
||||
name = "zsh"
|
||||
description = "install & configure zsh"
|
||||
|
||||
[[packages]]
|
||||
name = "zsh"
|
||||
|
||||
[[actions.command]]
|
||||
command = "sh ./setup-omzsh.sh"
|
||||
description = "oh-my-zsh setup"
|
||||
|
||||
[[actions.link]]
|
||||
src = "./zshrc"
|
||||
dest = "~/.zshrc"
|
10
crates/zsh/setup-omzsh.sh
Normal file
10
crates/zsh/setup-omzsh.sh
Normal file
|
@ -0,0 +1,10 @@
|
|||
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
||||
|
||||
PL_DIR=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
|
||||
[ -d "$PL_DIR" ] || git clone https://github.com/zsh-users/zsh-autosuggestions $PL_DIR
|
||||
PL_DIR=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
|
||||
[ -d "$PL_DIR" ] || git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $PL_DIR
|
||||
fi
|
||||
|
||||
[ -f "$HOME/.zshrc" ] && unlink $HOME/.zshrc
|
44
crates/zsh/zshrc
Normal file
44
crates/zsh/zshrc
Normal file
|
@ -0,0 +1,44 @@
|
|||
#!/bin/zsh
|
||||
|
||||
# Raine's .zshrc
|
||||
|
||||
if [ "$PROFILEINC" = "1" ]; then
|
||||
. ~/.profile
|
||||
fi
|
||||
|
||||
export EDITOR=vim
|
||||
export GPG_TTY=$(tty)
|
||||
export PATH="$PATH:$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$HOME/.local/bin"
|
||||
|
||||
# oh-my-zsh init
|
||||
if [ -f "$HOME/.oh-my-zsh/oh-my-zsh.sh" ]; then
|
||||
export ZSH="$HOME/.oh-my-zsh"
|
||||
ZSH_THEME="afowler"
|
||||
plugins=(git docker docker-compose node zsh-autosuggestions zsh-syntax-highlighting zsh-cargo-completion)
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
else
|
||||
echo "oh-my-zsh not detected :("
|
||||
PS1="$(whoami)@${HOSTNAME:-$(hostname)} $ "
|
||||
fi
|
||||
|
||||
update_dotfiles() {
|
||||
cd $HOME/.dotfiles
|
||||
git pull
|
||||
cd - &> /dev/null
|
||||
}
|
||||
|
||||
container() {
|
||||
docker run \
|
||||
-ti \
|
||||
--rm \
|
||||
--name tmp-$(id -u)-$(openssl rand -hex 8) \
|
||||
--network ${CONTAINER_NETWORK:-internal} \
|
||||
alpine \
|
||||
ash
|
||||
}
|
||||
|
||||
[ -f "$HOME/.config/i3/shortcuts-i3.sh" ] && . ~/.config/i3/shortcuts-i3.sh
|
||||
|
||||
alias q="exit"
|
||||
alias vim="nvim"
|
||||
alias vi="nvim"
|
|
@ -1,5 +1,8 @@
|
|||
use std::{
|
||||
collections::HashMap, fs, process::{Command, Stdio}, time::Duration
|
||||
collections::HashMap,
|
||||
fs::{self, remove_file},
|
||||
process::{Command, Stdio},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use dbus::{
|
||||
|
@ -11,7 +14,7 @@ use log::{debug, error, info, trace};
|
|||
use resolve_path::PathResolveExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{tags::Tag};
|
||||
use crate::tags::Tag;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Actions {
|
||||
|
@ -36,6 +39,7 @@ pub struct CommandAction {
|
|||
pub struct LinkAction {
|
||||
pub src: String,
|
||||
pub dest: String,
|
||||
overwrite: Option<bool>,
|
||||
}
|
||||
|
||||
impl CommandAction {
|
||||
|
@ -44,7 +48,7 @@ impl CommandAction {
|
|||
command: command.into(),
|
||||
user: user.into(),
|
||||
description: None,
|
||||
require: None
|
||||
require: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,16 +78,25 @@ impl CommandAction {
|
|||
|
||||
impl LinkAction {
|
||||
pub fn link(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
trace!("linking from {:?} to {:?}...", &self.src.resolve(), &self.dest.resolve());
|
||||
trace!(
|
||||
"linking from {:?} to {:?}...",
|
||||
&self.src.resolve(),
|
||||
&self.dest.resolve()
|
||||
);
|
||||
if let Ok(existing) = fs::read_link(&self.dest.resolve()) {
|
||||
if existing == self.src.resolve() {
|
||||
debug!("link OK");
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err("Destination is linked to a different path".into());
|
||||
if self.overwrite.unwrap_or(false) == true {
|
||||
debug!("removing {}...", self.dest);
|
||||
remove_file(self.dest.resolve())?;
|
||||
} else {
|
||||
return Err("Destination is linked to a different path".into());
|
||||
}
|
||||
}
|
||||
}
|
||||
std::os::unix::fs::symlink(&self.src.resolve(), &self.dest.resolve())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ pub struct CrateManifest {
|
|||
pub struct CrateInfo {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub author: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
Loading…
Reference in a new issue