diff --git a/app/src/help/bindings.rs b/app/src/help/bindings.rs index 2bb6c64f..da714816 100644 --- a/app/src/help/bindings.rs +++ b/app/src/help/bindings.rs @@ -1,6 +1,7 @@ use core::Ctx; -use ratatui::{layout::{self, Constraint}, prelude::{Buffer, Direction, Rect}, style::{Color, Style, Stylize}, widgets::{List, ListItem, Widget}}; +use config::THEME; +use ratatui::{layout::{self, Constraint}, prelude::{Buffer, Direction, Rect}, widgets::{List, ListItem, Widget}}; pub(super) struct Bindings<'a> { cx: &'a Ctx, @@ -17,19 +18,22 @@ impl Widget for Bindings<'_> { return; } + // On let col1 = bindings .iter() - .map(|c| ListItem::new(c.on()).style(Style::new().fg(Color::Yellow))) + .map(|c| ListItem::new(c.on()).style(THEME.help.on.into())) .collect::>(); + // Exec let col2 = bindings .iter() - .map(|c| ListItem::new(c.exec()).style(Style::new().fg(Color::Cyan))) + .map(|c| ListItem::new(c.exec()).style(THEME.help.exec.into())) .collect::>(); + // Desc let col3 = bindings .iter() - .map(|c| ListItem::new(if let Some(ref desc) = c.desc { desc } else { "-" })) + .map(|c| ListItem::new(c.desc.as_deref().unwrap_or("-")).style(THEME.help.desc.into())) .collect::>(); let chunks = layout::Layout::new() @@ -40,7 +44,7 @@ impl Widget for Bindings<'_> { let cursor = self.cx.help.rel_cursor() as u16; buf.set_style( Rect { x: area.x, y: area.y + cursor, width: area.width, height: 1 }, - Style::new().bg(Color::Black).bold(), + THEME.help.hovered.into(), ); List::new(col1).render(chunks[0], buf); diff --git a/app/src/help/layout.rs b/app/src/help/layout.rs index d12acdb8..33644a17 100644 --- a/app/src/help/layout.rs +++ b/app/src/help/layout.rs @@ -1,6 +1,7 @@ use core::Ctx; -use ratatui::{buffer::Buffer, layout::{self, Rect}, prelude::{Constraint, Direction}, style::{Color, Style}, widgets::{Clear, Paragraph, Widget}}; +use config::THEME; +use ratatui::{buffer::Buffer, layout::{self, Rect}, prelude::{Constraint, Direction}, widgets::{Clear, Paragraph, Widget}}; use super::Bindings; @@ -23,7 +24,7 @@ impl<'a> Widget for Layout<'a> { let help = &self.cx.help; Paragraph::new(help.keyword().unwrap_or_else(|| format!("{}.help", help.layer()))) - .style(Style::new().fg(Color::Black).bg(Color::White)) + .style(THEME.help.footer.into()) .render(chunks[1], buf); Bindings::new(self.cx).render(chunks[0], buf); diff --git a/app/src/input/input.rs b/app/src/input/input.rs index b4935dd6..ea26ed3f 100644 --- a/app/src/input/input.rs +++ b/app/src/input/input.rs @@ -2,7 +2,8 @@ use core::{input::InputMode, Ctx}; use std::ops::Range; use ansi_to_tui::IntoText; -use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, text::{Line, Text}, widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget}}; +use config::THEME; +use ratatui::{buffer::Buffer, layout::Rect, text::{Line, Text}, widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget}}; use shared::Term; pub(crate) struct Input<'a> { @@ -30,14 +31,14 @@ impl<'a> Widget for Input<'a> { Block::new() .borders(Borders::ALL) .border_type(BorderType::Rounded) - .border_style(Style::new().fg(Color::Blue)) + .border_style(THEME.input.border.into()) .title({ let mut line = Line::from(input.title()); - line.patch_style(Style::new().fg(Color::White)); + line.patch_style(THEME.input.title.into()); line }), ) - .style(Style::new().fg(Color::White)) + .style(THEME.input.value.into()) .render(area, buf); if let Some(Range { start, end }) = input.selected() { @@ -46,7 +47,7 @@ impl<'a> Widget for Input<'a> { buf.set_style( Rect { x, y, width: (end - start).min(win.width - x), height: 1.min(win.height - y) }, - Style::new().bg(Color::Rgb(72, 77, 102)), + THEME.input.selected.into(), ) } diff --git a/app/src/select/select.rs b/app/src/select/select.rs index 3912e47d..f0b9a0dc 100644 --- a/app/src/select/select.rs +++ b/app/src/select/select.rs @@ -1,6 +1,7 @@ use core::Ctx; -use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}}; +use config::THEME; +use ratatui::{buffer::Buffer, layout::Rect, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}}; pub(crate) struct Select<'a> { cx: &'a Ctx, @@ -21,10 +22,10 @@ impl<'a> Widget for Select<'a> { .enumerate() .map(|(i, v)| { if i != select.rel_cursor() { - return ListItem::new(format!(" {v}")); + return ListItem::new(format!(" {v}")).style(THEME.select.inactive.into()); } - ListItem::new(format!(" {v}")).style(Style::new().fg(Color::Magenta)) + ListItem::new(format!(" {v}")).style(THEME.select.active.into()) }) .collect::>(); @@ -35,7 +36,7 @@ impl<'a> Widget for Select<'a> { .title(select.title()) .borders(Borders::ALL) .border_type(BorderType::Rounded) - .border_style(Style::new().fg(Color::Blue)), + .border_style(THEME.select.border.into()), ) .render(area, buf); } diff --git a/app/src/tasks/layout.rs b/app/src/tasks/layout.rs index 099057fc..82bfd53d 100644 --- a/app/src/tasks/layout.rs +++ b/app/src/tasks/layout.rs @@ -1,6 +1,7 @@ use core::{tasks::TASKS_PERCENT, Ctx}; -use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Direction, Rect}, style::{Color, Modifier, Style}, widgets::{Block, BorderType, Borders, List, ListItem, Padding, Widget}}; +use config::THEME; +use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Direction, Rect}, text::Line, widgets::{Block, BorderType, Borders, List, ListItem, Padding, Widget}}; use super::Clear; @@ -38,12 +39,16 @@ impl<'a> Widget for Layout<'a> { Clear.render(area, buf); let block = Block::new() - .title("Tasks") + .title({ + let mut line = Line::from("Tasks"); + line.patch_style(THEME.tasks.title.into()); + line + }) .title_alignment(Alignment::Center) .padding(Padding::new(0, 0, 1, 1)) .borders(Borders::ALL) .border_type(BorderType::Rounded) - .border_style(Style::new().fg(Color::Rgb(128, 174, 250))); + .border_style(THEME.tasks.border.into()); block.clone().render(area, buf); let tasks = &self.cx.tasks; @@ -54,7 +59,7 @@ impl<'a> Widget for Layout<'a> { .map(|(i, v)| { let mut item = ListItem::new(v.name.clone()); if i == tasks.cursor { - item = item.style(Style::new().add_modifier(Modifier::UNDERLINED)); + item = item.style(THEME.tasks.hovered.into()); } item }) diff --git a/app/src/which/layout.rs b/app/src/which/layout.rs index 686bf8be..89a7f9c8 100644 --- a/app/src/which/layout.rs +++ b/app/src/which/layout.rs @@ -1,6 +1,7 @@ use core::Ctx; -use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Block, Clear, Widget}}; +use config::THEME; +use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, widgets::{Block, Clear, Widget}}; use super::Side; @@ -39,7 +40,7 @@ impl Widget for Which<'_> { .split(area); Clear.render(area, buf); - Block::new().style(Style::new().bg(Color::Rgb(47, 51, 73))).render(area, buf); + Block::new().style(THEME.which.mask.into()).render(area, buf); Side::new(which.times, cands.0).render(chunks[0], buf); Side::new(which.times, cands.1).render(chunks[1], buf); Side::new(which.times, cands.2).render(chunks[2], buf); diff --git a/app/src/which/side.rs b/app/src/which/side.rs index da14f5c2..2934cba8 100644 --- a/app/src/which/side.rs +++ b/app/src/which/side.rs @@ -1,5 +1,5 @@ -use config::keymap::Control; -use ratatui::{prelude::{Buffer, Rect}, style::{Color, Style}, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}}; +use config::{keymap::Control, THEME}; +use ratatui::{prelude::{Buffer, Rect}, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}}; pub(super) struct Side<'a> { times: usize, @@ -21,19 +21,19 @@ impl Widget for Side<'_> { // Keys let keys = c.on[self.times..].iter().map(ToString::to_string).collect::>(); spans.push(Span::raw(" ".repeat(10usize.saturating_sub(keys.join("").len())))); - spans.push(Span::styled(keys[0].clone(), Style::new().fg(Color::LightCyan))); + spans.push(Span::styled(keys[0].clone(), THEME.which.cand.into())); spans.extend( - keys - .iter() - .skip(1) - .map(|k| Span::styled(k.to_string(), Style::new().fg(Color::DarkGray))), + keys.iter().skip(1).map(|k| Span::styled(k.to_string(), THEME.which.rest.into())), ); // Separator - spans.push(Span::styled("  ".to_string(), Style::new().fg(Color::DarkGray))); + spans.push(Span::styled( + THEME.which.separator.to_string(), + THEME.which.separator_style.into(), + )); - // Exec - spans.push(Span::styled(c.desc_or_exec(), Style::new().fg(Color::Magenta))); + // Desc / Exec + spans.push(Span::styled(c.desc_or_exec(), THEME.which.desc.into())); ListItem::new(Line::from(spans)) }) diff --git a/config/preset/theme.toml b/config/preset/theme.toml index 0e0ed90f..7d76ba64 100644 --- a/config/preset/theme.toml +++ b/config/preset/theme.toml @@ -1,17 +1,15 @@ -[tabs] -active = { fg = "#1E2031", bg = "#80AEFA" } -inactive = { fg = "#C8D3F8", bg = "#484D66" } -max_width = 1 +# vim:fileencoding=utf-8:foldmethod=marker + +# : Status {{{ [status] -plain = { fg = "#FFFFFF" } -fancy = { bg = "#45475D" } +fancy = { bg = "darkgray" } separator = { opening = "", closing = "" } # Mode -mode_normal = { fg = "#181827", bg = "#7DB5FF", bold = true } -mode_select = { fg = "#1E1E30", bg = "#D2A4FE", bold = true } -mode_unset = { fg = "#1E1E30", bg = "#FFAF80", bold = true } +mode_normal = { fg = "black", bg = "blue", bold = true } +mode_select = { fg = "black", bg = "green", bold = true } +mode_unset = { fg = "black", bg = "magenta", bold = true } # Progress progress_label = { fg = "#FFFFFF", bold = true } @@ -19,46 +17,60 @@ progress_normal = { fg = "#FFA577", bg = "#484D66" } progress_error = { fg = "#FF84A9", bg = "#484D66" } # Permissions -permissions_t = { fg = "#97DC8D" } -permissions_r = { fg = "#F3D398" } -permissions_w = { fg = "#FA7F94" } -permissions_x = { fg = "#7AD9E5" } -permissions_s = { fg = "#6D738F" } +permissions_t = { fg = "lightgreen" } +permissions_r = { fg = "lightyellow" } +permissions_w = { fg = "lightred" } +permissions_x = { fg = "lightcyan" } +permissions_s = { fg = "darkgray" } + +# : }}} + + +# : Manager {{{ + +[tabs] +active = { fg = "black", bg = "blue" } +inactive = { bg = "darkgray" } +max_width = 1 [files] -hovered = { fg = "#1E2031", bg = "#80AEFA" } +hovered = { fg = "#000000", bg = "blue" } [marker] -selected = { fg = "#97DC8D", bg = "#97DC8D" } -copied = { fg = "#F3D398", bg = "#F3D398" } -cut = { fg = "#FF84A9", bg = "#FF84A9" } +selected = { fg = "lightgreen", bg = "lightgreen" } +copied = { fg = "lightyellow", bg = "lightyellow" } +cut = { fg = "lightred", bg = "lightred" } [preview] hovered = { underline = true } syntect_theme = "~/.config/bat/themes/Catppuccin-macchiato.tmTheme" +# : }}} + + +# : File-specific styles {{{ + [filetype] rules = [ # Images - { mime = "image/*", fg = "#7AD9E5" }, + { mime = "image/*", fg = "cyan" }, # Videos - { mime = "video/*", fg = "#F3D398" }, - { mime = "audio/*", fg = "#F3D398" }, + { mime = "video/*", fg = "yellow" }, + { mime = "audio/*", fg = "yellow" }, # Archives - { mime = "application/zip", fg = "#CD9EFC" }, - { mime = "application/gzip", fg = "#CD9EFC" }, - { mime = "application/x-tar", fg = "#CD9EFC" }, - { mime = "application/x-bzip", fg = "#CD9EFC" }, - { mime = "application/x-bzip2", fg = "#CD9EFC" }, - { mime = "application/x-7z-compressed", fg = "#CD9EFC" }, - { mime = "application/x-rar", fg = "#CD9EFC" }, + { mime = "application/zip", fg = "magenta" }, + { mime = "application/gzip", fg = "magenta" }, + { mime = "application/x-tar", fg = "magenta" }, + { mime = "application/x-bzip", fg = "magenta" }, + { mime = "application/x-bzip2", fg = "magenta" }, + { mime = "application/x-7z-compressed", fg = "magenta" }, + { mime = "application/x-rar", fg = "magenta" }, # Fallback - { name = "*", fg = "#C8D3F8" }, - { name = "*/", fg = "#80AEFA" } + { name = "*/", fg = "blue" } ] [icons] @@ -155,3 +167,61 @@ rules = [ # Default "*" = "" "*/" = "" + +# : }}} + + +# : Input {{{ + +[input] +border = { fg = "blue" } +title = { fg = "white" } +value = { fg = "white" } +selected = { bg = "black" } + +# : }}} + + +# : Select {{{ + +[select] +border = { fg = "blue" } +active = { fg = "magenta" } +inactive = { fg = "white" } + +# : }}} + + +# : Tasks {{{ + +[tasks] +border = { fg = "blue" } +title = { fg = "white" } +hovered = { underline = true } + +# : }}} + + +# : Which {{{ + +[which] +mask = { bg = "black" } +cand = { fg = "lightcyan" } +rest = { fg = "darkgray" } +desc = { fg = "magenta" } +separator = "  " +separator_style = { fg = "darkgray" } + +# : }}} + + +# : Help {{{ + +[help] +on = { fg = "magenta" } +exec = { fg = "cyan" } +desc = { fg = "gray" } +hovered = { bg = "darkgray", bold = true } +footer = { fg = "black", bg = "white" } + +# : }}} diff --git a/config/src/theme/help.rs b/config/src/theme/help.rs new file mode 100644 index 00000000..2e6697aa --- /dev/null +++ b/config/src/theme/help.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; + +use super::Style; + +#[derive(Deserialize, Serialize)] +pub struct Help { + pub on: Style, + pub exec: Style, + pub desc: Style, + + pub hovered: Style, + pub footer: Style, +} diff --git a/config/src/theme/input.rs b/config/src/theme/input.rs new file mode 100644 index 00000000..e252e2fe --- /dev/null +++ b/config/src/theme/input.rs @@ -0,0 +1,11 @@ +use serde::{Deserialize, Serialize}; + +use super::Style; + +#[derive(Deserialize, Serialize)] +pub struct Input { + pub border: Style, + pub title: Style, + pub value: Style, + pub selected: Style, +} diff --git a/config/src/theme/list.rs b/config/src/theme/list.rs deleted file mode 100644 index 5ce1556b..00000000 --- a/config/src/theme/list.rs +++ /dev/null @@ -1,15 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::Style; - -#[derive(Deserialize, Serialize)] -pub struct Files { - pub hovered: Style, -} - -#[derive(Deserialize, Serialize)] -pub struct Marker { - pub selected: Style, - pub copied: Style, - pub cut: Style, -} diff --git a/config/src/theme/manager.rs b/config/src/theme/manager.rs new file mode 100644 index 00000000..15c58259 --- /dev/null +++ b/config/src/theme/manager.rs @@ -0,0 +1,32 @@ +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; +use validator::Validate; + +use super::Style; + +#[derive(Deserialize, Serialize, Validate)] +pub struct Tabs { + pub active: Style, + pub inactive: Style, + #[validate(range(min = 1, message = "Must be greater than 0"))] + pub max_width: u8, +} + +#[derive(Deserialize, Serialize)] +pub struct Files { + pub hovered: Style, +} + +#[derive(Deserialize, Serialize)] +pub struct Marker { + pub selected: Style, + pub copied: Style, + pub cut: Style, +} + +#[derive(Deserialize, Serialize)] +pub struct Preview { + pub hovered: Style, + pub syntect_theme: PathBuf, +} diff --git a/config/src/theme/mod.rs b/config/src/theme/mod.rs index ee9b13fb..2e2a6967 100644 --- a/config/src/theme/mod.rs +++ b/config/src/theme/mod.rs @@ -1,15 +1,25 @@ mod color; mod filetype; +mod help; mod icon; -mod list; +mod input; +mod manager; +mod select; mod status; mod style; +mod tasks; mod theme; +mod which; pub use color::*; pub use filetype::*; +pub use help::*; pub use icon::*; -pub use list::*; +pub use input::*; +pub use manager::*; +pub use select::*; pub use status::*; pub use style::*; +pub use tasks::*; pub use theme::*; +pub use which::*; diff --git a/config/src/theme/select.rs b/config/src/theme/select.rs new file mode 100644 index 00000000..856f239e --- /dev/null +++ b/config/src/theme/select.rs @@ -0,0 +1,10 @@ +use serde::{Deserialize, Serialize}; + +use super::Style; + +#[derive(Deserialize, Serialize)] +pub struct Select { + pub border: Style, + pub active: Style, + pub inactive: Style, +} diff --git a/config/src/theme/status.rs b/config/src/theme/status.rs index 672f0e0b..c7e5dd10 100644 --- a/config/src/theme/status.rs +++ b/config/src/theme/status.rs @@ -4,7 +4,6 @@ use super::Style; #[derive(Deserialize, Serialize)] pub struct Status { - pub plain: Style, pub fancy: Style, pub separator: StatusSeparator, diff --git a/config/src/theme/tasks.rs b/config/src/theme/tasks.rs new file mode 100644 index 00000000..96198e79 --- /dev/null +++ b/config/src/theme/tasks.rs @@ -0,0 +1,10 @@ +use serde::{Deserialize, Serialize}; + +use super::Style; + +#[derive(Deserialize, Serialize)] +pub struct Tasks { + pub border: Style, + pub title: Style, + pub hovered: Style, +} diff --git a/config/src/theme/theme.rs b/config/src/theme/theme.rs index 97dd66c0..ce912ff6 100644 --- a/config/src/theme/theme.rs +++ b/config/src/theme/theme.rs @@ -1,37 +1,41 @@ -use std::path::PathBuf; - use serde::{Deserialize, Serialize}; use shared::expand_path; use validator::Validate; -use super::{Files, Filetype, Icon, Marker, Status, Style}; +use super::{Files, Filetype, Help, Icon, Input, Marker, Preview, Select, Status, Tabs, Tasks, Which}; use crate::{validation::check_validation, MERGED_THEME}; -#[derive(Deserialize, Serialize, Validate)] -pub struct Tabs { - pub active: Style, - pub inactive: Style, - #[validate(range(min = 1, message = "Must be greater than 0"))] - pub max_width: u8, -} - -#[derive(Deserialize, Serialize)] -pub struct Preview { - pub hovered: Style, - pub syntect_theme: PathBuf, -} - #[derive(Deserialize, Serialize)] pub struct Theme { - pub tabs: Tabs, - pub status: Status, - pub files: Files, - pub marker: Marker, - pub preview: Preview, + // Status + pub status: Status, + + // Manager + pub tabs: Tabs, + pub files: Files, + pub marker: Marker, + pub preview: Preview, + + // File-specific styles #[serde(rename = "filetype", deserialize_with = "Filetype::deserialize", skip_serializing)] pub filetypes: Vec, #[serde(deserialize_with = "Icon::deserialize", skip_serializing)] pub icons: Vec, + + // Input + pub input: Input, + + // Select + pub select: Select, + + // Tasks + pub tasks: Tasks, + + // Which + pub which: Which, + + // Help + pub help: Help, } impl Default for Theme { diff --git a/config/src/theme/which.rs b/config/src/theme/which.rs new file mode 100644 index 00000000..1713f9dd --- /dev/null +++ b/config/src/theme/which.rs @@ -0,0 +1,14 @@ +use serde::{Deserialize, Serialize}; + +use super::Style; + +#[derive(Deserialize, Serialize)] +pub struct Which { + pub mask: Style, + pub cand: Style, + pub rest: Style, + pub desc: Style, + + pub separator: String, + pub separator_style: Style, +} diff --git a/cspell.json b/cspell.json index b1209d6d..33135cb1 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ"],"version":"0.2"} +{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand"],"language":"en","version":"0.2","flagWords":[]}