From a140b89f45b939ee8a941bbd3c407a0d26c17c7c Mon Sep 17 00:00:00 2001 From: Emma <817422+Pajn@users.noreply.github.com> Date: Sun, 22 Mar 2026 21:11:30 +0100 Subject: [PATCH 1/5] Keep PTY runtimes alive across server restarts --- Cargo.lock | 3 + crates/embers-cli/Cargo.toml | 1 + crates/embers-cli/src/lib.rs | 202 ++- crates/embers-cli/tests/interactive.rs | 7 +- crates/embers-cli/tests/panes.rs | 4 +- crates/embers-core/src/metadata.rs | 8 +- crates/embers-core/src/snapshot.rs | 14 +- crates/embers-server/Cargo.toml | 1 + crates/embers-server/src/buffer_runtime.rs | 1203 +++++++++++++++-- crates/embers-server/src/config.rs | 3 + crates/embers-server/src/lib.rs | 5 +- crates/embers-server/src/model.rs | 74 +- crates/embers-server/src/persist.rs | 31 +- crates/embers-server/src/server.rs | 693 +++++++--- crates/embers-server/src/state.rs | 53 +- crates/embers-server/tests/persistence.rs | 81 +- crates/embers-test-support/Cargo.toml | 1 + crates/embers-test-support/src/lib.rs | 2 + crates/embers-test-support/src/test_lock.rs | 115 ++ .../tests/buffer_runtime.rs | 7 +- 20 files changed, 2064 insertions(+), 444 deletions(-) create mode 100644 crates/embers-test-support/src/test_lock.rs diff --git a/Cargo.lock b/Cargo.lock index fdb72f21..a83c23ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -553,6 +553,7 @@ name = "embers-cli" version = "0.1.0" dependencies = [ "assert_cmd", + "base64", "clap", "embers-client", "embers-core", @@ -613,6 +614,7 @@ name = "embers-server" version = "0.1.0" dependencies = [ "alacritty_terminal", + "base64", "embers-core", "embers-protocol", "portable-pty", @@ -632,6 +634,7 @@ dependencies = [ "embers-core", "embers-protocol", "embers-server", + "libc", "portable-pty", "tempfile", "tokio", diff --git a/crates/embers-cli/Cargo.toml b/crates/embers-cli/Cargo.toml index 6ea3cbc1..815c3238 100644 --- a/crates/embers-cli/Cargo.toml +++ b/crates/embers-cli/Cargo.toml @@ -18,6 +18,7 @@ name = "embers-cli" path = "src/bin/embers-cli.rs" [dependencies] +base64.workspace = true clap.workspace = true embers-client = { path = "../embers-client" } embers-core = { path = "../embers-core" } diff --git a/crates/embers-cli/src/lib.rs b/crates/embers-cli/src/lib.rs index 0392faf0..a8cea15d 100644 --- a/crates/embers-cli/src/lib.rs +++ b/crates/embers-cli/src/lib.rs @@ -1,13 +1,19 @@ mod interactive; +use std::ffi::OsString; use std::fs::{self, OpenOptions}; use std::io::Write; use std::num::NonZeroU64; #[cfg(unix)] +use std::os::unix::ffi::OsStringExt; +#[cfg(unix)] use std::os::unix::fs::{MetadataExt, OpenOptionsExt, PermissionsExt}; +#[cfg(windows)] +use std::os::windows::ffi::OsStringExt; use std::path::{Path, PathBuf}; use std::process::{Command as ProcessCommand, Stdio}; +use base64::Engine as _; use clap::{Parser, Subcommand}; use embers_core::{ BufferId, FloatGeometry, FloatingId, MuxError, NodeId, Result, SessionId, SplitDirection, @@ -71,6 +77,21 @@ pub enum Command { }, #[command(name = "__serve", hide = true)] Serve, + #[command(name = "__runtime-keeper", hide = true)] + RuntimeKeeper { + #[arg(long = "keeper-socket")] + keeper_socket: PathBuf, + #[arg(long)] + cols: u16, + #[arg(long)] + rows: u16, + #[arg(long)] + cwd: Option, + #[arg(long = "env", value_parser = parse_env_arg)] + env: Vec<(String, OsString)>, + #[arg(last = true)] + command: Vec, + }, Ping { #[arg(default_value = "phase0")] payload: String, @@ -226,9 +247,9 @@ async fn execute(socket: &Path, command: Command) -> Result { let mut connection = CliConnection::connect(socket).await?; match command { - Command::Attach { .. } | Command::Serve => Err(MuxError::internal( - "interactive commands must be dispatched through run()", - )), + Command::Attach { .. } | Command::Serve | Command::RuntimeKeeper { .. } => Err( + MuxError::internal("interactive commands must be dispatched through run()"), + ), Command::Ping { payload } => { let response = connection .request(ClientMessage::Ping(PingRequest { @@ -621,31 +642,56 @@ async fn execute(socket: &Path, command: Command) -> Result { } pub async fn run(cli: Cli) -> Result<()> { - let socket = resolve_socket_path(cli.socket.as_deref()); - validate_runtime_socket_parent(&socket)?; + let Cli { + socket, + config, + command, + .. + } = cli; - match cli.command { - None => { - ensure_server_process(&socket).await?; - interactive::run(socket, None, cli.config).await - } - Some(Command::Attach { target }) => { - if !server_is_available(&socket).await { - return Err(MuxError::not_found(format!( - "no embers server is listening on {}", - socket.display() - ))); - } - interactive::run(socket, target, cli.config).await - } - Some(Command::Serve) => run_server(socket).await, - Some(command) => { - ensure_server_process(&socket).await?; - let output = execute(&socket, command).await?; - if !output.is_empty() { - println!("{output}"); + match command { + Some(Command::RuntimeKeeper { + keeper_socket, + cols, + rows, + cwd, + env, + command, + }) => embers_server::run_runtime_keeper(embers_server::RuntimeKeeperCli { + socket_path: keeper_socket, + command, + cwd, + env: env.into_iter().collect(), + size: embers_core::PtySize::new(cols, rows), + }), + command => { + let socket = resolve_socket_path(socket.as_deref()); + validate_runtime_socket_parent(&socket)?; + + match command { + None => { + ensure_server_process(&socket).await?; + interactive::run(socket, None, config).await + } + Some(Command::Attach { target }) => { + if !server_is_available(&socket).await { + return Err(MuxError::not_found(format!( + "no embers server is listening on {}", + socket.display() + ))); + } + interactive::run(socket, target, config).await + } + Some(Command::Serve) => run_server(socket).await, + Some(command) => { + ensure_server_process(&socket).await?; + let output = execute(&socket, command).await?; + if !output.is_empty() { + println!("{output}"); + } + Ok(()) + } } - Ok(()) } } } @@ -676,6 +722,46 @@ fn default_runtime_dir() -> PathBuf { PathBuf::from("/tmp").join(format!("embers-{}", effective_uid())) } +fn parse_env_arg(value: &str) -> std::result::Result<(String, OsString), String> { + let Some((key, env_value)) = value.split_once('=') else { + return Err("expected KEY=VALUE".to_owned()); + }; + if key.is_empty() { + return Err("environment key must not be empty".to_owned()); + } + Ok((key.to_owned(), decode_runtime_keeper_env_value(env_value)?)) +} + +fn decode_runtime_keeper_env_value(value: &str) -> std::result::Result { + let Some(encoded) = value.strip_prefix("base64:") else { + return Ok(OsString::from(value)); + }; + let decoded = base64::engine::general_purpose::STANDARD + .decode(encoded) + .map_err(|error| format!("invalid base64 environment value: {error}"))?; + #[cfg(unix)] + { + Ok(OsString::from_vec(decoded)) + } + #[cfg(windows)] + { + if decoded.len() % 2 != 0 { + return Err("invalid UTF-16LE environment value: odd-length byte sequence".to_owned()); + } + let wide = decoded + .chunks_exact(2) + .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) + .collect::>(); + Ok(OsString::from_wide(&wide)) + } + #[cfg(all(not(unix), not(windows)))] + { + String::from_utf8(decoded) + .map(OsString::from) + .map_err(|error| format!("invalid UTF-8 environment value: {error}")) + } +} + #[cfg(unix)] fn effective_uid() -> u32 { unsafe { libc::geteuid() } @@ -1585,9 +1671,20 @@ fn default_title(command: &[String], fallback: &str) -> String { #[cfg(test)] mod tests { + #[cfg(windows)] + use base64::Engine as _; use clap::Parser; use embers_core::NodeId; use embers_protocol::{TabRecord, TabsRecord}; + #[cfg(windows)] + use std::ffi::OsString; + #[cfg(unix)] + use std::ffi::OsString; + #[cfg(unix)] + use std::os::unix::ffi::OsStringExt; + #[cfg(windows)] + use std::os::windows::ffi::OsStringExt; + use std::path::Path; use super::{Cli, resolve_window_index, split_scoped_required, split_scoped_target}; @@ -1614,6 +1711,59 @@ mod tests { } } + #[test] + fn runtime_keeper_uses_distinct_keeper_socket_flag() { + let cli = Cli::try_parse_from([ + "embers", + "__runtime-keeper", + "--socket", + "/tmp/global.sock", + "--keeper-socket", + "/tmp/keeper.sock", + "--cols", + "80", + "--rows", + "24", + "--", + "/bin/sh", + ]) + .expect("cli parses"); + + assert_eq!(cli.socket.as_deref(), Some(Path::new("/tmp/global.sock"))); + match cli.command { + Some(super::Command::RuntimeKeeper { + keeper_socket, + cols, + rows, + command, + .. + }) => { + assert_eq!(keeper_socket, Path::new("/tmp/keeper.sock")); + assert_eq!((cols, rows), (80, 24)); + assert_eq!(command, vec!["/bin/sh"]); + } + other => panic!("expected runtime keeper command, got {other:?}"), + } + } + + #[cfg(unix)] + #[test] + fn runtime_keeper_env_values_decode_base64_losslessly() { + let (key, value) = super::parse_env_arg("KEY=base64:AP8=").expect("env parses"); + assert_eq!(key, "KEY"); + assert_eq!(value, OsString::from_vec(vec![0, 255])); + } + + #[cfg(windows)] + #[test] + fn runtime_keeper_env_values_decode_utf16le_losslessly() { + let encoded = base64::engine::general_purpose::STANDARD.encode([0x00, 0xD8, 0x61, 0x00]); + let (key, value) = + super::parse_env_arg(&format!("KEY=base64:{encoded}")).expect("env parses"); + assert_eq!(key, "KEY"); + assert_eq!(value, OsString::from_wide(&[0xD800, 0x0061])); + } + #[test] fn scoped_targets_split_session_prefix() { assert_eq!( diff --git a/crates/embers-cli/tests/interactive.rs b/crates/embers-cli/tests/interactive.rs index 3d939199..0577d3b6 100644 --- a/crates/embers-cli/tests/interactive.rs +++ b/crates/embers-cli/tests/interactive.rs @@ -3,7 +3,7 @@ use std::path::Path; use std::time::Duration; use embers_core::PtySize; -use embers_test_support::{PtyHarness, TestServer, cargo_bin, cargo_bin_path}; +use embers_test_support::{PtyHarness, TestServer, acquire_test_lock, cargo_bin, cargo_bin_path}; use tempfile::tempdir; use crate::support::{run_cli, stdout}; @@ -165,6 +165,7 @@ fn first_client_id_finds_attached_row() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn embers_without_subcommand_starts_server_and_client() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let tempdir = tempdir().expect("tempdir"); let socket_path = tempdir.path().join("embers.sock"); let socket_arg = socket_path.to_string_lossy().into_owned(); @@ -204,6 +205,7 @@ async fn embers_without_subcommand_starts_server_and_client() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn attach_subcommand_connects_to_running_server() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); let binary = cargo_bin_path("embers"); let binary_dir = binary.parent().expect("binary dir"); @@ -248,6 +250,7 @@ async fn attach_subcommand_connects_to_running_server() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn client_commands_can_switch_and_detach_a_live_attached_client() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); run_cli(&server, ["new-session", "main"]); @@ -302,6 +305,7 @@ async fn client_commands_can_switch_and_detach_a_live_attached_client() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn page_up_enters_local_scrollback_and_shows_indicator() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let tempdir = tempdir().expect("tempdir"); let socket_path = tempdir.path().join("embers.sock"); let socket_arg = socket_path.to_string_lossy().into_owned(); @@ -321,6 +325,7 @@ async fn page_up_enters_local_scrollback_and_shows_indicator() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn local_selection_yank_emits_osc52_clipboard_sequence() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let tempdir = tempdir().expect("tempdir"); let socket_path = tempdir.path().join("embers.sock"); let socket_arg = socket_path.to_string_lossy().into_owned(); diff --git a/crates/embers-cli/tests/panes.rs b/crates/embers-cli/tests/panes.rs index 4e060714..8f935e09 100644 --- a/crates/embers-cli/tests/panes.rs +++ b/crates/embers-cli/tests/panes.rs @@ -2,13 +2,14 @@ use std::time::Duration; use embers_core::RequestId; use embers_protocol::{BufferRequest, ClientMessage, ServerResponse}; -use embers_test_support::{TestConnection, TestServer}; +use embers_test_support::{TestConnection, TestServer, acquire_test_lock}; use tokio::time::sleep; use crate::support::{run_cli, session_snapshot_by_name, stdout}; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn pane_commands_round_trip_through_cli() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); run_cli(&server, ["new-session", "alpha"]); @@ -129,6 +130,7 @@ async fn pane_commands_round_trip_through_cli() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn detached_buffers_can_be_listed_and_attached_via_cli() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); run_cli(&server, ["new-session", "alpha"]); diff --git a/crates/embers-core/src/metadata.rs b/crates/embers-core/src/metadata.rs index 55231862..718d6fb4 100644 --- a/crates/embers-core/src/metadata.rs +++ b/crates/embers-core/src/metadata.rs @@ -1,7 +1,9 @@ use std::path::PathBuf; use std::time::SystemTime; -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Timestamp(pub SystemTime); impl Timestamp { @@ -16,7 +18,7 @@ impl Default for Timestamp { } } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum ActivityState { #[default] Idle, @@ -24,7 +26,7 @@ pub enum ActivityState { Bell, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct EntityMetadata { pub title: Option, pub cwd: Option, diff --git a/crates/embers-core/src/snapshot.rs b/crates/embers-core/src/snapshot.rs index 345667f1..1e409945 100644 --- a/crates/embers-core/src/snapshot.rs +++ b/crates/embers-core/src/snapshot.rs @@ -1,14 +1,16 @@ use std::path::PathBuf; +use serde::{Deserialize, Serialize}; + use crate::geometry::PtySize; -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct CursorPosition { pub row: u16, pub col: u16, } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum CursorShape { #[default] Block, @@ -16,13 +18,13 @@ pub enum CursorShape { Beam, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct CursorState { pub position: CursorPosition, pub shape: CursorShape, } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct TerminalModes { pub alternate_screen: bool, pub mouse_reporting: bool, @@ -30,7 +32,7 @@ pub struct TerminalModes { pub bracketed_paste: bool, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct SnapshotLine { pub text: String, } @@ -43,7 +45,7 @@ impl From<&str> for SnapshotLine { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct TerminalSnapshot { pub sequence: u64, pub size: PtySize, diff --git a/crates/embers-server/Cargo.toml b/crates/embers-server/Cargo.toml index e54dfb31..6960cf38 100644 --- a/crates/embers-server/Cargo.toml +++ b/crates/embers-server/Cargo.toml @@ -8,6 +8,7 @@ version.workspace = true [dependencies] alacritty_terminal = "0.25.1" +base64.workspace = true embers-core = { path = "../embers-core" } embers-protocol = { path = "../embers-protocol" } portable-pty.workspace = true diff --git a/crates/embers-server/src/buffer_runtime.rs b/crates/embers-server/src/buffer_runtime.rs index 97ec825a..4acda300 100644 --- a/crates/embers-server/src/buffer_runtime.rs +++ b/crates/embers-server/src/buffer_runtime.rs @@ -1,18 +1,55 @@ -use std::any::Any; use std::collections::BTreeMap; -use std::ffi::OsString; +use std::env; +use std::ffi::{OsStr, OsString}; +use std::fs; use std::io::{Read, Write}; -use std::path::Path; +#[cfg(unix)] +use std::os::unix::ffi::OsStrExt; +#[cfg(unix)] +use std::os::unix::fs::PermissionsExt; +use std::os::unix::net::{UnixListener, UnixStream}; +#[cfg(windows)] +use std::os::windows::ffi::OsStrExt; +use std::path::{Path, PathBuf}; +use std::process::{Command as ProcessCommand, Stdio}; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; +use std::time::Duration; -use embers_core::{BufferId, MuxError, PtySize, Result}; +use base64::Engine as _; +use embers_core::{ActivityState, BufferId, MuxError, PtySize, Result, TerminalSnapshot}; use portable_pty::{ Child, ChildKiller, CommandBuilder, MasterPty, NativePtySystem, PtySize as PortablePtySize, PtySystem, }; +use serde::{Deserialize, Serialize}; use tracing::error; +use crate::{AlacrittyTerminalBackend, RawByteRouter, TerminalBackend}; + +const CONNECT_RETRY_DELAY: Duration = Duration::from_millis(25); +const CONNECT_RETRY_ATTEMPTS: usize = 1200; +const STATUS_POLL_INTERVAL: Duration = Duration::from_millis(50); +const MAX_FRAME_SIZE: usize = 16 * 1024 * 1024; + +#[derive(Clone, Debug)] +pub struct BufferRuntimeUpdate { + pub sequence: u64, + pub activity: ActivityState, + pub title: Option>, +} + +#[derive(Clone, Debug)] +pub struct BufferRuntimeStatus { + pub pid: Option, + pub sequence: u64, + pub activity: ActivityState, + pub title: Option, + pub running: bool, + pub exit_code: Option, +} + #[derive(Clone)] pub struct BufferRuntimeHandle { inner: Arc, @@ -21,128 +58,273 @@ pub struct BufferRuntimeHandle { struct BufferRuntimeInner { buffer_id: BufferId, pid: Option, - master: Mutex>, - writer: Mutex>, - killer: Mutex>, + socket_path: PathBuf, + connection: Mutex, + stop: AtomicBool, threads: Mutex, } #[derive(Default)] struct RuntimeThreads { - reader: Option>, - wait: Option>, + poller: Option>, } #[derive(Clone)] pub struct BufferRuntimeCallbacks { - pub on_output: Arc) + Send + Sync>, + pub on_output: Arc, pub on_exit: Arc) + Send + Sync>, } +#[derive(Clone)] +pub struct RuntimeKeeperCli { + pub socket_path: PathBuf, + pub command: Vec, + pub cwd: Option, + pub env: BTreeMap, + pub size: PtySize, +} + +struct KeeperConnection { + stream: UnixStream, +} + +#[derive(Serialize, Deserialize)] +enum KeeperRequest { + Status, + Write { bytes: Vec }, + Resize { size: PtySize }, + Snapshot { cwd: Option }, + VisibleSnapshot { cwd: Option }, + ScrollbackSlice { start_line: u64, line_count: u32 }, + Kill, +} + +#[derive(Serialize, Deserialize)] +enum KeeperResponse { + Status(KeeperStatus), + Snapshot(KeeperSnapshot), + VisibleSnapshot(TerminalSnapshot), + ScrollbackSlice(KeeperScrollbackSlice), + Ok, + Error { message: String }, +} + +#[derive(Clone, Serialize, Deserialize)] +struct KeeperStatus { + pid: Option, + sequence: u64, + activity: ActivityState, + title: Option, + running: bool, + exit_code: Option, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct KeeperSnapshot { + pub sequence: u64, + pub size: PtySize, + pub lines: Vec, + pub title: Option, + pub cwd: Option, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct KeeperScrollbackSlice { + pub start_line: u64, + pub total_lines: u64, + pub lines: Vec, +} + +struct KeeperRuntime { + surface: Mutex, + master: Mutex>, + writer: Mutex>, + killer: Mutex>, + sequence: AtomicU64, + activity: Mutex, + exit_code: Mutex>>, + pid: Option, +} + +struct KeeperSurface { + router: RawByteRouter, + backend: Box, + size: PtySize, +} + impl std::fmt::Debug for BufferRuntimeHandle { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter .debug_struct("BufferRuntimeHandle") .field("buffer_id", &self.inner.buffer_id) .field("pid", &self.inner.pid) + .field("socket_path", &self.inner.socket_path) .finish() } } impl BufferRuntimeHandle { - pub fn spawn( + pub async fn spawn( buffer_id: BufferId, + socket_path: PathBuf, command: &[String], cwd: Option<&Path>, env: &BTreeMap, size: PtySize, callbacks: BufferRuntimeCallbacks, ) -> Result { - let Some(program) = command.first() else { - return Err(MuxError::invalid_input("buffer command must not be empty")); - }; - - let pty_system = NativePtySystem::default(); - let pair = pty_system - .openpty(to_portable_size(size)) - .map_err(|error| MuxError::pty(error.to_string()))?; + let command = command.to_vec(); + let cwd = cwd.map(Path::to_path_buf); + let env = env.clone(); + tokio::task::spawn_blocking(move || { + Self::spawn_blocking(buffer_id, socket_path, command, cwd, env, size, callbacks) + }) + .await + .map_err(|error| MuxError::internal(error.to_string()))? + } - let mut command_builder = CommandBuilder::new(program); - command_builder.args(&command[1..]); - if let Some(cwd) = cwd { - command_builder.cwd(cwd); + fn spawn_blocking( + buffer_id: BufferId, + socket_path: PathBuf, + command: Vec, + cwd: Option, + env: BTreeMap, + size: PtySize, + callbacks: BufferRuntimeCallbacks, + ) -> Result { + if command.is_empty() { + return Err(MuxError::invalid_input("buffer command must not be empty")); } - for (key, value) in env { - command_builder.env(key, value); + if let Some(parent) = socket_path.parent() { + fs::create_dir_all(parent)?; + } + if socket_path.exists() { + let _ = fs::remove_file(&socket_path); } - let mut child = pair - .slave - .spawn_command(command_builder) - .map_err(|error| MuxError::pty(error.to_string()))?; - let pid = child.process_id(); - let mut killer = child.clone_killer(); - let reader = pair - .master - .try_clone_reader() - .map_err(|error| MuxError::pty(error.to_string()))?; - let writer = pair - .master - .take_writer() - .map_err(|error| MuxError::pty(error.to_string()))?; - - let on_output = callbacks.on_output.clone(); - let reader_handle = thread::Builder::new() - .name(format!("buffer-{buffer_id}-reader")) - .spawn(move || read_loop(buffer_id, reader, on_output)) - .map_err(|error| { - let _ = killer.kill(); - let _ = child.wait(); - MuxError::internal(error.to_string()) - })?; - - let on_exit = callbacks.on_exit.clone(); - let wait_handle = match thread::Builder::new() - .name(format!("buffer-{buffer_id}-wait")) - .spawn(move || wait_loop(buffer_id, child, on_exit)) - { - Ok(handle) => handle, - Err(error) => { - let _ = killer.kill(); - join_thread(buffer_id, "reader", reader_handle); - return Err(MuxError::internal(error.to_string())); - } + let cli = RuntimeKeeperCli { + socket_path: socket_path.clone(), + command, + cwd, + env, + size, }; + spawn_runtime_keeper(cli)?; - Ok(Self { - inner: Arc::new(BufferRuntimeInner { - buffer_id, - pid, - master: Mutex::new(pair.master), - writer: Mutex::new(writer), - killer: Mutex::new(killer), - threads: Mutex::new(RuntimeThreads { - reader: Some(reader_handle), - wait: Some(wait_handle), - }), - }), + Self::attach_blocking(buffer_id, socket_path, callbacks) + } + + pub async fn attach( + buffer_id: BufferId, + socket_path: PathBuf, + callbacks: BufferRuntimeCallbacks, + ) -> Result { + tokio::task::spawn_blocking(move || { + Self::attach_blocking(buffer_id, socket_path, callbacks) }) + .await + .map_err(|error| MuxError::internal(error.to_string()))? + } + + fn attach_blocking( + buffer_id: BufferId, + socket_path: PathBuf, + callbacks: BufferRuntimeCallbacks, + ) -> Result { + let stream = connect_to_keeper(&socket_path)?; + let mut connection = KeeperConnection { stream }; + let initial = connection.status()?; + let inner = Arc::new(BufferRuntimeInner { + buffer_id, + pid: initial.pid, + socket_path, + connection: Mutex::new(connection), + stop: AtomicBool::new(false), + threads: Mutex::new(RuntimeThreads::default()), + }); + + let poller = spawn_status_poller(inner.clone(), callbacks, initial)?; + inner + .threads + .lock() + .map_err(|_| MuxError::internal("buffer runtime thread registry lock poisoned"))? + .poller = Some(poller); + + Ok(Self { inner }) } pub fn pid(&self) -> Option { self.inner.pid } + pub fn socket_path(&self) -> &Path { + &self.inner.socket_path + } + + pub async fn status(&self) -> Result { + let inner = self.inner.clone(); + tokio::task::spawn_blocking(move || { + let mut connection = inner + .connection + .lock() + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.status() + }) + .await + .map_err(|error| MuxError::internal(error.to_string()))? + } + + pub async fn capture_snapshot(&self, cwd: Option) -> Result { + let inner = self.inner.clone(); + tokio::task::spawn_blocking(move || { + let mut connection = inner + .connection + .lock() + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.snapshot(cwd) + }) + .await + .map_err(|error| MuxError::internal(error.to_string()))? + } + + pub async fn capture_visible_snapshot(&self, cwd: Option) -> Result { + let inner = self.inner.clone(); + tokio::task::spawn_blocking(move || { + let mut connection = inner + .connection + .lock() + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.visible_snapshot(cwd) + }) + .await + .map_err(|error| MuxError::internal(error.to_string()))? + } + + pub async fn capture_scrollback_slice( + &self, + start_line: u64, + line_count: u32, + ) -> Result { + let inner = self.inner.clone(); + tokio::task::spawn_blocking(move || { + let mut connection = inner + .connection + .lock() + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.scrollback_slice(start_line, line_count) + }) + .await + .map_err(|error| MuxError::internal(error.to_string()))? + } + pub async fn write(&self, bytes: Vec) -> Result<()> { let inner = self.inner.clone(); tokio::task::spawn_blocking(move || { - let mut writer = inner - .writer + let mut connection = inner + .connection .lock() - .map_err(|_| MuxError::internal("buffer runtime writer lock poisoned"))?; - writer.write_all(&bytes)?; - writer.flush()?; - Ok(()) + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.write(bytes) }) .await .map_err(|error| MuxError::internal(error.to_string()))? @@ -151,13 +333,11 @@ impl BufferRuntimeHandle { pub async fn resize(&self, size: PtySize) -> Result<()> { let inner = self.inner.clone(); tokio::task::spawn_blocking(move || { - let master = inner - .master + let mut connection = inner + .connection .lock() - .map_err(|_| MuxError::internal("buffer runtime master lock poisoned"))?; - master - .resize(to_portable_size(size)) - .map_err(|error| MuxError::pty(error.to_string())) + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.resize(size) }) .await .map_err(|error| MuxError::internal(error.to_string()))? @@ -166,13 +346,11 @@ impl BufferRuntimeHandle { pub async fn kill(&self) -> Result<()> { let inner = self.inner.clone(); tokio::task::spawn_blocking(move || { - let mut killer = inner - .killer + let mut connection = inner + .connection .lock() - .map_err(|_| MuxError::internal("buffer runtime killer lock poisoned"))?; - killer - .kill() - .map_err(|error| MuxError::pty(error.to_string())) + .map_err(|_| MuxError::internal("buffer runtime connection lock poisoned"))?; + connection.kill() }) .await .map_err(|error| MuxError::internal(error.to_string()))? @@ -188,6 +366,7 @@ impl BufferRuntimeHandle { impl BufferRuntimeInner { fn join_threads_blocking(&self) { + self.stop.store(true, Ordering::Relaxed); let mut threads = match self.threads.lock() { Ok(threads) => threads, Err(poisoned) => { @@ -198,14 +377,13 @@ impl BufferRuntimeInner { poisoned.into_inner() } }; - let RuntimeThreads { reader, wait } = std::mem::take(&mut *threads); + let poller = threads.poller.take(); drop(threads); - if let Some(handle) = reader { - join_thread(self.buffer_id, "reader", handle); - } - if let Some(handle) = wait { - join_thread(self.buffer_id, "wait", handle); + if let Some(poller) = poller + && poller.thread().id() != thread::current().id() + { + let _ = poller.join(); } } } @@ -216,29 +394,677 @@ impl Drop for BufferRuntimeInner { } } -fn read_loop( - buffer_id: BufferId, - mut reader: Box, - on_output: Arc) + Send + Sync>, -) { +impl KeeperConnection { + fn request(&mut self, request: KeeperRequest) -> Result { + write_message(&mut self.stream, &request)?; + match read_message(&mut self.stream)? { + Some(KeeperResponse::Error { message }) => Err(MuxError::transport(message)), + Some(response) => Ok(response), + None => Err(MuxError::transport("runtime keeper disconnected")), + } + } + + fn status(&mut self) -> Result { + match self.request(KeeperRequest::Status)? { + KeeperResponse::Status(status) => Ok(BufferRuntimeStatus { + pid: status.pid, + sequence: status.sequence, + activity: status.activity, + title: status.title, + running: status.running, + exit_code: status.exit_code, + }), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper status response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } + + fn write(&mut self, bytes: Vec) -> Result<()> { + match self.request(KeeperRequest::Write { bytes })? { + KeeperResponse::Ok => Ok(()), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper write response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } + + fn resize(&mut self, size: PtySize) -> Result<()> { + match self.request(KeeperRequest::Resize { size })? { + KeeperResponse::Ok => Ok(()), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper resize response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } + + fn snapshot(&mut self, cwd: Option) -> Result { + match self.request(KeeperRequest::Snapshot { cwd })? { + KeeperResponse::Snapshot(snapshot) => Ok(snapshot), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper snapshot response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } + + fn visible_snapshot(&mut self, cwd: Option) -> Result { + match self.request(KeeperRequest::VisibleSnapshot { cwd })? { + KeeperResponse::VisibleSnapshot(snapshot) => Ok(snapshot), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper visible snapshot response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } + + fn scrollback_slice( + &mut self, + start_line: u64, + line_count: u32, + ) -> Result { + match self.request(KeeperRequest::ScrollbackSlice { + start_line, + line_count, + })? { + KeeperResponse::ScrollbackSlice(slice) => Ok(slice), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper scrollback response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } + + fn kill(&mut self) -> Result<()> { + match self.request(KeeperRequest::Kill)? { + KeeperResponse::Ok => Ok(()), + other => Err(MuxError::protocol(format!( + "unexpected runtime keeper kill response: {other_kind}", + other_kind = keeper_response_kind(&other) + ))), + } + } +} + +impl KeeperSurface { + fn new(size: PtySize) -> Self { + Self { + router: RawByteRouter, + backend: Box::new(AlacrittyTerminalBackend::new(size)), + size, + } + } + + fn route_output(&mut self, bytes: &[u8]) -> ActivityState { + self.router.route_output(self.backend.as_mut(), bytes); + self.backend.take_activity() + } + + fn resize(&mut self, size: PtySize) { + self.size = size; + self.backend.resize(size); + } + + fn capture_lines(&self) -> Vec { + self.backend.capture_scrollback() + } + + fn capture_visible_snapshot(&self, sequence: u64, cwd: Option) -> TerminalSnapshot { + self.backend.visible_snapshot(sequence, self.size, cwd) + } + + fn capture_scrollback_slice(&self, start_line: u64, line_count: u32) -> KeeperScrollbackSlice { + let slice = self + .backend + .capture_scrollback_slice(start_line, line_count); + KeeperScrollbackSlice { + start_line: slice.start_line, + total_lines: slice.total_lines, + lines: slice.lines, + } + } +} + +pub fn run_runtime_keeper(cli: RuntimeKeeperCli) -> Result<()> { + let Some(program) = cli.command.first() else { + return Err(MuxError::invalid_input( + "runtime keeper command must not be empty", + )); + }; + + if let Some(parent) = cli.socket_path.parent() { + fs::create_dir_all(parent)?; + } + if cli.socket_path.exists() { + let _ = fs::remove_file(&cli.socket_path); + } + let listener = UnixListener::bind(&cli.socket_path)?; + let _cleanup = SocketCleanup::new(cli.socket_path.clone()); + + let pty_system = NativePtySystem::default(); + let pair = pty_system + .openpty(to_portable_size(cli.size)) + .map_err(|error| MuxError::pty(error.to_string()))?; + + let mut command_builder = CommandBuilder::new(program); + command_builder.args(&cli.command[1..]); + if let Some(cwd) = &cli.cwd { + command_builder.cwd(cwd); + } + for (key, value) in &cli.env { + command_builder.env(key, value); + } + + let child = pair + .slave + .spawn_command(command_builder) + .map_err(|error| MuxError::pty(error.to_string()))?; + let pid = child.process_id(); + let killer = child.clone_killer(); + let reader = pair + .master + .try_clone_reader() + .map_err(|error| MuxError::pty(error.to_string()))?; + let writer = pair + .master + .take_writer() + .map_err(|error| MuxError::pty(error.to_string()))?; + + let runtime = Arc::new(KeeperRuntime { + surface: Mutex::new(KeeperSurface::new(cli.size)), + master: Mutex::new(pair.master), + writer: Mutex::new(writer), + killer: Mutex::new(killer), + sequence: AtomicU64::new(0), + activity: Mutex::new(ActivityState::Idle), + exit_code: Mutex::new(None), + pid, + }); + + let reader_runtime = runtime.clone(); + let reader_join = thread::Builder::new() + .name(format!("keeper-reader-{}", cli.socket_path.display())) + .spawn(move || keeper_read_loop(reader_runtime, reader)) + .map_err(|error| MuxError::internal(error.to_string()))?; + let wait_runtime = runtime.clone(); + let wait_join = thread::Builder::new() + .name(format!("keeper-wait-{}", cli.socket_path.display())) + .spawn(move || keeper_wait_loop(wait_runtime, child)) + .map_err(|error| MuxError::internal(error.to_string()))?; + let mut terminate = false; + while !terminate { + let (mut stream, _) = listener.accept()?; + terminate = handle_keeper_client(runtime.clone(), &mut stream)?; + } + + let _ = reader_join.join(); + let _ = wait_join.join(); + Ok(()) +} + +fn handle_keeper_client(runtime: Arc, stream: &mut UnixStream) -> Result { + loop { + let request = match read_message::(stream) { + Ok(Some(request)) => request, + Ok(None) => return Ok(false), + Err(error) => { + let response = KeeperResponse::Error { + message: error.to_string(), + }; + if write_message(stream, &response).is_err() { + return Ok(false); + } + continue; + } + }; + let (response, terminate) = match handle_keeper_request(&runtime, request) { + Ok(result) => result, + Err(error) => { + let response = KeeperResponse::Error { + message: error.to_string(), + }; + if write_message(stream, &response).is_err() { + return Ok(false); + } + continue; + } + }; + if write_message(stream, &response).is_err() { + return Ok(false); + } + if terminate { + return Ok(true); + } + } +} + +fn handle_keeper_request( + runtime: &Arc, + request: KeeperRequest, +) -> Result<(KeeperResponse, bool)> { + match request { + KeeperRequest::Status => Ok((KeeperResponse::Status(runtime.status()?), false)), + KeeperRequest::Write { bytes } => { + runtime.write(bytes)?; + Ok((KeeperResponse::Ok, false)) + } + KeeperRequest::Resize { size } => { + runtime.resize(size)?; + Ok((KeeperResponse::Ok, false)) + } + KeeperRequest::Snapshot { cwd } => { + Ok((KeeperResponse::Snapshot(runtime.snapshot(cwd)?), false)) + } + KeeperRequest::VisibleSnapshot { cwd } => Ok(( + KeeperResponse::VisibleSnapshot(runtime.visible_snapshot(cwd)?), + false, + )), + KeeperRequest::ScrollbackSlice { + start_line, + line_count, + } => Ok(( + KeeperResponse::ScrollbackSlice(runtime.scrollback_slice(start_line, line_count)?), + false, + )), + KeeperRequest::Kill => { + runtime.kill()?; + Ok((KeeperResponse::Ok, false)) + } + } +} + +impl KeeperRuntime { + fn status(&self) -> Result { + let exit_code = *self + .exit_code + .lock() + .map_err(|_| MuxError::internal("runtime keeper exit lock poisoned"))?; + let surface = self + .surface + .lock() + .map_err(|_| MuxError::internal("runtime keeper surface lock poisoned"))?; + let activity = *self + .activity + .lock() + .map_err(|_| MuxError::internal("runtime keeper activity lock poisoned"))?; + let sequence = self.sequence.load(Ordering::Relaxed); + let title = surface.backend.metadata().title.clone(); + Ok(KeeperStatus { + pid: self.pid, + sequence, + activity, + title, + running: exit_code.is_none(), + exit_code: exit_code.flatten(), + }) + } + + fn write(&self, bytes: Vec) -> Result<()> { + if self + .exit_code + .lock() + .map_err(|_| MuxError::internal("runtime keeper exit lock poisoned"))? + .is_some() + { + return Err(MuxError::conflict("buffer runtime has already exited")); + } + let mut writer = self + .writer + .lock() + .map_err(|_| MuxError::internal("runtime keeper writer lock poisoned"))?; + writer.write_all(&bytes)?; + writer.flush()?; + Ok(()) + } + + fn resize(&self, size: PtySize) -> Result<()> { + let master = self + .master + .lock() + .map_err(|_| MuxError::internal("runtime keeper master lock poisoned"))?; + master + .resize(to_portable_size(size)) + .map_err(|error| MuxError::pty(error.to_string()))?; + self.surface + .lock() + .map_err(|_| MuxError::internal("runtime keeper surface lock poisoned"))? + .resize(size); + Ok(()) + } + + fn snapshot(&self, cwd: Option) -> Result { + let surface = self + .surface + .lock() + .map_err(|_| MuxError::internal("runtime keeper surface lock poisoned"))?; + Ok(KeeperSnapshot { + sequence: self.sequence.load(Ordering::Relaxed), + size: surface.size, + lines: surface.capture_lines(), + title: surface.backend.metadata().title, + cwd, + }) + } + + fn visible_snapshot(&self, cwd: Option) -> Result { + let surface = self + .surface + .lock() + .map_err(|_| MuxError::internal("runtime keeper surface lock poisoned"))?; + Ok(surface.capture_visible_snapshot(self.sequence.load(Ordering::Relaxed), cwd)) + } + + fn scrollback_slice(&self, start_line: u64, line_count: u32) -> Result { + let surface = self + .surface + .lock() + .map_err(|_| MuxError::internal("runtime keeper surface lock poisoned"))?; + Ok(surface.capture_scrollback_slice(start_line, line_count)) + } + + fn kill(&self) -> Result<()> { + let mut killer = self + .killer + .lock() + .map_err(|_| MuxError::internal("runtime keeper killer lock poisoned"))?; + killer + .kill() + .map_err(|error| MuxError::pty(error.to_string())) + } +} + +fn keeper_read_loop(runtime: Arc, mut reader: Box) { let mut buffer = [0_u8; 4096]; loop { match reader.read(&mut buffer) { Ok(0) => break, - Ok(read) => on_output(buffer_id, buffer[..read].to_vec()), + Ok(read) => { + let mut surface = match runtime.surface.lock() { + Ok(surface) => surface, + Err(_) => break, + }; + let activity = surface.route_output(&buffer[..read]); + runtime.sequence.fetch_add(1, Ordering::Relaxed); + if let Ok(mut state) = runtime.activity.lock() { + *state = activity; + } + } Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue, Err(_) => break, } } } -fn wait_loop( - buffer_id: BufferId, - mut child: Box, - on_exit: Arc) + Send + Sync>, -) { +fn keeper_wait_loop(runtime: Arc, mut child: Box) { let exit_code = child.wait().ok().and_then(exit_status_code); - on_exit(buffer_id, exit_code); + if let Ok(mut state) = runtime.exit_code.lock() { + *state = Some(exit_code); + } +} + +fn spawn_status_poller( + inner: Arc, + callbacks: BufferRuntimeCallbacks, + initial: BufferRuntimeStatus, +) -> Result> { + thread::Builder::new() + .name(format!("buffer-{}-poller", inner.buffer_id)) + .spawn(move || { + let mut last_sequence = initial.sequence; + let mut last_title = initial.title.clone(); + let mut last_activity = initial.activity; + let mut saw_exit = !initial.running; + + while !inner.stop.load(Ordering::Relaxed) { + let status = { + let mut connection = match inner.connection.lock() { + Ok(connection) => connection, + Err(_) => break, + }; + match connection.status() { + Ok(status) => status, + Err(error) => { + error!(%error, %inner.buffer_id, "status poll failed"); + (callbacks.on_exit)(inner.buffer_id, None); + break; + } + } + }; + + if status.sequence != last_sequence + || status.title != last_title + || status.activity != last_activity + { + let title = (status.title != last_title).then(|| status.title.clone()); + (callbacks.on_output)( + inner.buffer_id, + BufferRuntimeUpdate { + sequence: status.sequence, + activity: status.activity, + title, + }, + ); + last_sequence = status.sequence; + last_title = status.title.clone(); + last_activity = status.activity; + } + + if !saw_exit && !status.running { + saw_exit = true; + (callbacks.on_exit)(inner.buffer_id, status.exit_code); + } + + thread::sleep(STATUS_POLL_INTERVAL); + } + }) + .map_err(|error| MuxError::internal(error.to_string())) +} + +fn connect_to_keeper(socket_path: &Path) -> Result { + for _ in 0..CONNECT_RETRY_ATTEMPTS { + match UnixStream::connect(socket_path) { + Ok(stream) => return Ok(stream), + Err(error) if error.kind() == std::io::ErrorKind::NotFound => { + thread::sleep(CONNECT_RETRY_DELAY); + } + Err(error) if error.kind() == std::io::ErrorKind::ConnectionRefused => { + return Err(error.into()); + } + Err(error) => return Err(error.into()), + } + } + Err(MuxError::timeout(format!( + "timed out connecting to runtime keeper {}", + socket_path.display() + ))) +} + +fn spawn_runtime_keeper(cli: RuntimeKeeperCli) -> Result<()> { + if let Some(keeper_exe) = resolve_runtime_keeper_executable() { + let mut keeper = ProcessCommand::new(keeper_exe); + keeper + .arg("__runtime-keeper") + .arg("--keeper-socket") + .arg(&cli.socket_path) + .arg("--cols") + .arg(cli.size.cols.to_string()) + .arg("--rows") + .arg(cli.size.rows.to_string()); + if let Some(cwd) = &cli.cwd { + keeper.arg("--cwd").arg(cwd); + } + for (key, value) in &cli.env { + keeper.arg("--env").arg(format!( + "{}=base64:{}", + key, + encode_runtime_keeper_env_value(value.as_os_str()) + )); + } + keeper.arg("--"); + keeper.args(&cli.command); + keeper.stdin(Stdio::null()); + keeper.stdout(Stdio::null()); + keeper.stderr(Stdio::null()); + keeper.spawn()?; + return Ok(()); + } + + thread::Builder::new() + .name(format!("runtime-keeper-{}", cli.socket_path.display())) + .spawn(move || { + if let Err(error) = run_runtime_keeper(cli) { + error!(%error, "runtime keeper thread failed"); + } + }) + .map_err(|error| MuxError::internal(error.to_string()))?; + Ok(()) +} + +fn resolve_runtime_keeper_executable() -> Option { + if let Some(path) = env::var_os("EMBERS_RUNTIME_KEEPER_BIN").map(PathBuf::from) + && is_executable_file(&path) + { + return Some(path); + } + if let Some(path) = env::var_os("CARGO_BIN_EXE_embers").map(PathBuf::from) + && is_executable_file(&path) + { + return Some(path); + } + let current_exe = env::current_exe().ok(); + if let Some(current_exe) = current_exe.as_ref() { + if current_exe + .file_stem() + .and_then(|name| name.to_str()) + .is_some_and(|name| name == "embers" || name == "embers-cli") + && is_executable_file(current_exe) + { + return Some(current_exe.clone()); + } + + if let Some(parent) = current_exe.parent() { + if parent.file_name().is_some_and(|name| name == "deps") { + let candidate = parent.parent()?.join(binary_name("embers")); + if is_executable_file(&candidate) { + return Some(candidate); + } + } + + for stem in ["embers", "embers-cli", "embers-runtime-keeper"] { + let candidate = parent.join(binary_name(stem)); + if is_executable_file(&candidate) { + return Some(candidate); + } + } + } + } + + for stem in ["embers", "embers-cli", "embers-runtime-keeper"] { + if let Some(path) = resolve_binary_on_path(stem) { + return Some(path); + } + } + + None +} + +fn binary_name(stem: &str) -> String { + if cfg!(windows) { + format!("{stem}.exe") + } else { + stem.to_owned() + } +} + +fn is_executable_file(path: &Path) -> bool { + let Ok(metadata) = path.metadata() else { + return false; + }; + if !metadata.is_file() { + return false; + } + #[cfg(unix)] + if metadata.permissions().mode() & 0o111 == 0 { + return false; + } + true +} + +fn resolve_binary_on_path(stem: &str) -> Option { + let path = env::var_os("PATH")?; + let binary_name = binary_name(stem); + for entry in env::split_paths(&path) { + let candidate = entry.join(&binary_name); + if is_executable_file(&candidate) { + return Some(candidate); + } + } + None +} + +fn encode_runtime_keeper_env_value(value: &OsStr) -> String { + #[cfg(unix)] + { + base64::engine::general_purpose::STANDARD.encode(value.as_bytes()) + } + #[cfg(windows)] + { + let encoded = value + .encode_wide() + .flat_map(|unit| unit.to_le_bytes()) + .collect::>(); + base64::engine::general_purpose::STANDARD.encode(encoded) + } + #[cfg(all(not(unix), not(windows)))] + { + base64::engine::general_purpose::STANDARD.encode(value.to_string_lossy().as_bytes()) + } +} + +fn write_message(stream: &mut UnixStream, value: &T) -> Result<()> { + let payload = + serde_json::to_vec(value).map_err(|error| MuxError::internal(error.to_string()))?; + let len = u32::try_from(payload.len()) + .map_err(|_| MuxError::internal("runtime keeper payload exceeded u32 length"))?; + stream.write_all(&len.to_le_bytes())?; + stream.write_all(&payload)?; + stream.flush()?; + Ok(()) +} + +fn read_message Deserialize<'de>>(stream: &mut UnixStream) -> Result> { + let mut len_bytes = [0_u8; 4]; + match stream.read_exact(&mut len_bytes) { + Ok(()) => {} + Err(error) if error.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(None), + Err(error) => return Err(error.into()), + } + let len = usize::try_from(u32::from_le_bytes(len_bytes)) + .map_err(|_| MuxError::protocol("runtime keeper frame length exceeds platform limits"))?; + if len == 0 || len > MAX_FRAME_SIZE { + return Err(MuxError::protocol(format!( + "runtime keeper frame length {len} is out of range" + ))); + } + let mut payload = vec![0_u8; len]; + stream.read_exact(&mut payload)?; + let value = + serde_json::from_slice(&payload).map_err(|error| MuxError::internal(error.to_string()))?; + Ok(Some(value)) +} + +fn keeper_response_kind(response: &KeeperResponse) -> &'static str { + match response { + KeeperResponse::Status(_) => "status", + KeeperResponse::Snapshot(_) => "snapshot", + KeeperResponse::VisibleSnapshot(_) => "visible_snapshot", + KeeperResponse::ScrollbackSlice(_) => "scrollback_slice", + KeeperResponse::Ok => "ok", + KeeperResponse::Error { .. } => "error", + } } fn exit_status_code(status: portable_pty::ExitStatus) -> Option { @@ -258,23 +1084,152 @@ fn to_portable_size(size: PtySize) -> PortablePtySize { } } -fn join_thread(buffer_id: BufferId, role: &str, handle: thread::JoinHandle<()>) { - if let Err(payload) = handle.join() { - error!( - %buffer_id, - thread = role, - panic = %panic_payload_message(payload), - "buffer runtime thread panicked" - ); +struct SocketCleanup { + socket_path: PathBuf, +} + +impl SocketCleanup { + fn new(socket_path: PathBuf) -> Self { + Self { socket_path } } } -fn panic_payload_message(payload: Box) -> String { - match payload.downcast::() { - Ok(message) => *message, - Err(payload) => match payload.downcast::<&'static str>() { - Ok(message) => (*message).to_owned(), - Err(_) => "non-string panic payload".to_owned(), - }, +impl Drop for SocketCleanup { + fn drop(&mut self) { + let _ = fs::remove_file(&self.socket_path); + } +} + +#[cfg(test)] +mod tests { + use std::io::Write; + use std::os::unix::net::UnixStream; + use std::sync::Arc; + use std::sync::mpsc; + use std::thread; + use std::time::{Duration, Instant}; + + use embers_core::{ActivityState, BufferId, MuxError}; + + use super::{ + BufferRuntimeCallbacks, BufferRuntimeInner, BufferRuntimeStatus, KeeperConnection, + MAX_FRAME_SIZE, RuntimeThreads, read_message, spawn_status_poller, + }; + + #[test] + fn join_threads_waits_for_poller_shutdown() { + let (stream, _peer) = UnixStream::pair().expect("create socket pair"); + let inner = Arc::new(BufferRuntimeInner { + buffer_id: BufferId(1), + pid: None, + socket_path: "/tmp/test-buffer.sock".into(), + connection: std::sync::Mutex::new(KeeperConnection { stream }), + stop: std::sync::atomic::AtomicBool::new(false), + threads: std::sync::Mutex::new(RuntimeThreads::default()), + }); + let (tx, rx) = mpsc::channel(); + let poller_inner = inner.clone(); + let poller = thread::spawn(move || { + while !poller_inner.stop.load(std::sync::atomic::Ordering::Relaxed) { + thread::sleep(Duration::from_millis(5)); + } + thread::sleep(Duration::from_millis(40)); + tx.send(()).expect("send shutdown notification"); + }); + inner.threads.lock().expect("lock thread registry").poller = Some(poller); + + let started = Instant::now(); + inner.join_threads_blocking(); + + assert!( + started.elapsed() >= Duration::from_millis(40), + "join should wait for the poller to finish" + ); + rx.try_recv() + .expect("poller should finish before join returns"); + } + + #[test] + fn read_message_rejects_empty_frame() { + let (mut stream, mut peer) = UnixStream::pair().expect("create socket pair"); + peer.write_all(&0_u32.to_le_bytes()) + .expect("write frame length"); + drop(peer); + + let error = match read_message::(&mut stream) { + Err(error) => error, + Ok(_) => panic!("expected frame error"), + }; + + assert!(matches!(error, MuxError::Protocol(_))); + assert!(error.to_string().contains("out of range")); + } + + #[test] + fn read_message_rejects_oversized_frame() { + let (mut stream, mut peer) = UnixStream::pair().expect("create socket pair"); + peer.write_all( + &(u32::try_from(MAX_FRAME_SIZE).expect("frame size fits in u32") + 1).to_le_bytes(), + ) + .expect("write frame length"); + drop(peer); + + let error = match read_message::(&mut stream) { + Err(error) => error, + Ok(_) => panic!("expected frame error"), + }; + + assert!(matches!(error, MuxError::Protocol(_))); + assert!(error.to_string().contains("out of range")); + } + + #[test] + fn status_poller_exits_on_status_error() { + let (stream, peer) = UnixStream::pair().expect("create socket pair"); + drop(peer); + let inner = Arc::new(BufferRuntimeInner { + buffer_id: BufferId(1), + pid: None, + socket_path: "/tmp/test-buffer.sock".into(), + connection: std::sync::Mutex::new(KeeperConnection { stream }), + stop: std::sync::atomic::AtomicBool::new(false), + threads: std::sync::Mutex::new(RuntimeThreads::default()), + }); + let (exit_tx, exit_rx) = mpsc::channel(); + let (output_tx, output_rx) = mpsc::channel(); + let poller = spawn_status_poller( + inner, + BufferRuntimeCallbacks { + on_output: Arc::new(move |buffer_id, _| { + output_tx + .send(buffer_id) + .expect("send unexpected output notification"); + }), + on_exit: Arc::new(move |buffer_id, exit_code| { + exit_tx + .send((buffer_id, exit_code)) + .expect("send exit notification"); + }), + }, + BufferRuntimeStatus { + pid: None, + sequence: 0, + activity: ActivityState::Idle, + title: None, + running: true, + exit_code: None, + }, + ) + .expect("spawn poller"); + + poller.join().expect("poller exits cleanly"); + + assert_eq!( + exit_rx + .recv_timeout(Duration::from_secs(1)) + .expect("poller should report exit"), + (BufferId(1), None) + ); + assert!(output_rx.try_recv().is_err()); } } diff --git a/crates/embers-server/src/config.rs b/crates/embers-server/src/config.rs index 782a70a4..551d7e26 100644 --- a/crates/embers-server/src/config.rs +++ b/crates/embers-server/src/config.rs @@ -8,6 +8,7 @@ pub const SOCKET_ENV_VAR: &str = "EMBERS_SOCKET"; pub struct ServerConfig { pub socket_path: PathBuf, pub workspace_path: PathBuf, + pub runtime_dir: PathBuf, pub buffer_env: BTreeMap, } @@ -19,9 +20,11 @@ impl ServerConfig { socket_path.as_os_str().to_owned(), ); let workspace_path = socket_path.with_extension("workspace.json"); + let runtime_dir = socket_path.with_extension("runtimes"); Self { socket_path, workspace_path, + runtime_dir, buffer_env, } } diff --git a/crates/embers-server/src/lib.rs b/crates/embers-server/src/lib.rs index 6d2867dc..b467d7c2 100644 --- a/crates/embers-server/src/lib.rs +++ b/crates/embers-server/src/lib.rs @@ -8,7 +8,10 @@ mod protocol; mod server; mod terminal_backend; -pub use buffer_runtime::{BufferRuntimeCallbacks, BufferRuntimeHandle}; +pub use buffer_runtime::{ + BufferRuntimeCallbacks, BufferRuntimeHandle, BufferRuntimeStatus, BufferRuntimeUpdate, + RuntimeKeeperCli, run_runtime_keeper, +}; pub use config::{SOCKET_ENV_VAR, ServerConfig}; pub use model::{ Buffer, BufferAttachment, BufferState, BufferViewNode, BufferViewState, ExitedBuffer, diff --git a/crates/embers-server/src/model.rs b/crates/embers-server/src/model.rs index f8dc1ded..dffa4d59 100644 --- a/crates/embers-server/src/model.rs +++ b/crates/embers-server/src/model.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::fmt; use std::path::PathBuf; use embers_core::{ @@ -17,13 +18,14 @@ pub struct Session { pub created_at: Timestamp, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone)] pub struct Buffer { pub id: BufferId, pub title: String, pub command: Vec, pub cwd: Option, pub env: BTreeMap, + runtime_socket_path: Option, pub state: BufferState, pub attachment: BufferAttachment, pub pty_size: PtySize, @@ -32,6 +34,76 @@ pub struct Buffer { pub created_at: Timestamp, } +impl Buffer { + pub(crate) fn new( + id: BufferId, + title: impl Into, + command: Vec, + cwd: Option, + env: BTreeMap, + ) -> Self { + Self { + id, + title: title.into(), + command, + cwd, + env, + runtime_socket_path: None, + state: BufferState::Created, + attachment: BufferAttachment::Detached, + pty_size: PtySize::new(80, 24), + activity: ActivityState::Idle, + last_snapshot_seq: 0, + created_at: Timestamp::now(), + } + } + + pub(crate) fn runtime_socket_path(&self) -> Option<&PathBuf> { + self.runtime_socket_path.as_ref() + } + + pub(crate) fn set_runtime_socket_path(&mut self, runtime_socket_path: Option) { + self.runtime_socket_path = runtime_socket_path; + } +} + +impl fmt::Debug for Buffer { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("Buffer") + .field("id", &self.id) + .field("title", &self.title) + .field("command", &self.command) + .field("cwd", &self.cwd) + .field("env", &self.env) + .field("state", &self.state) + .field("attachment", &self.attachment) + .field("pty_size", &self.pty_size) + .field("activity", &self.activity) + .field("last_snapshot_seq", &self.last_snapshot_seq) + .field("created_at", &self.created_at) + .finish() + } +} + +impl PartialEq for Buffer { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.title == other.title + && self.command == other.command + && self.cwd == other.cwd + && self.env == other.env + && self.state == other.state + && self.attachment == other.attachment + && self.pty_size == other.pty_size + && self.activity == other.activity + && self.last_snapshot_seq == other.last_snapshot_seq + && self.created_at == other.created_at + } +} + +impl Eq for Buffer {} + #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct RunningBuffer { pub pid: Option, diff --git a/crates/embers-server/src/persist.rs b/crates/embers-server/src/persist.rs index 510a6783..302abb74 100644 --- a/crates/embers-server/src/persist.rs +++ b/crates/embers-server/src/persist.rs @@ -54,6 +54,8 @@ pub struct PersistedBuffer { pub command: Vec, pub cwd: Option, pub env: BTreeMap, + #[serde(default)] + pub runtime_socket_path: Option, pub state: PersistedBufferState, pub attachment: PersistedBufferAttachment, pub pty_size: PtySize, @@ -295,6 +297,7 @@ pub fn persisted_buffer(buffer: &Buffer) -> PersistedBuffer { command: buffer.command.clone(), cwd: buffer.cwd.clone(), env: buffer.env.clone(), + runtime_socket_path: buffer.runtime_socket_path().cloned(), state: persisted_buffer_state(&buffer.state), attachment: persisted_buffer_attachment(&buffer.attachment), pty_size: buffer.pty_size, @@ -305,19 +308,21 @@ pub fn persisted_buffer(buffer: &Buffer) -> PersistedBuffer { } pub fn restored_buffer(buffer: PersistedBuffer) -> Result { - Ok(Buffer { - id: BufferId(buffer.id), - title: buffer.title, - command: buffer.command, - cwd: buffer.cwd, - env: buffer.env, - state: restored_buffer_state(buffer.state)?, - attachment: restored_buffer_attachment(buffer.attachment), - pty_size: buffer.pty_size, - activity: restored_activity(buffer.activity), - last_snapshot_seq: buffer.last_snapshot_seq, - created_at: timestamp_from_millis(buffer.created_at_ms)?, - }) + let mut restored = Buffer::new( + BufferId(buffer.id), + buffer.title, + buffer.command, + buffer.cwd, + buffer.env, + ); + restored.set_runtime_socket_path(buffer.runtime_socket_path); + restored.state = restored_buffer_state(buffer.state)?; + restored.attachment = restored_buffer_attachment(buffer.attachment); + restored.pty_size = buffer.pty_size; + restored.activity = restored_activity(buffer.activity); + restored.last_snapshot_seq = buffer.last_snapshot_seq; + restored.created_at = timestamp_from_millis(buffer.created_at_ms)?; + Ok(restored) } pub fn persisted_node(node: &Node) -> PersistedNode { diff --git a/crates/embers-server/src/server.rs b/crates/embers-server/src/server.rs index 9a5cd0d7..04e9c4e2 100644 --- a/crates/embers-server/src/server.rs +++ b/crates/embers-server/src/server.rs @@ -2,6 +2,8 @@ use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsString; use std::fs; #[cfg(unix)] +use std::os::unix::ffi::OsStrExt; +#[cfg(unix)] use std::os::unix::fs::PermissionsExt; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}; @@ -30,9 +32,8 @@ use tracing::{debug, error, info}; use crate::persist::{load_workspace, save_workspace}; use crate::protocol::{buffer_record, floating_record, session_record, session_snapshot}; use crate::{ - AlacrittyTerminalBackend, BackendDamage, BufferAttachment, BufferRuntimeCallbacks, - BufferRuntimeHandle, BufferState, RawByteRouter, ServerConfig, ServerState, TabEntry, - TerminalBackend, + BufferAttachment, BufferRuntimeCallbacks, BufferRuntimeHandle, BufferRuntimeStatus, + BufferRuntimeUpdate, BufferState, ServerConfig, ServerState, TabEntry, }; #[derive(Debug)] @@ -51,14 +52,17 @@ impl Server { } let restored_state = load_workspace(&self.config.workspace_path)?; - let listener = UnixListener::bind(&self.config.socket_path)?; - set_socket_permissions(&self.config.socket_path)?; let socket_path = self.config.socket_path.clone(); let runtime = Arc::new(Runtime::new( restored_state.unwrap_or_default(), + self.config.socket_path.clone(), self.config.workspace_path.clone(), + self.config.runtime_dir.clone(), self.config.buffer_env.clone(), )); + runtime.restore_buffer_runtimes().await?; + let listener = UnixListener::bind(&self.config.socket_path)?; + set_socket_permissions(&self.config.socket_path)?; let shutdown_signal = runtime.shutdown.clone(); let (shutdown_tx, mut shutdown_rx) = oneshot::channel(); @@ -276,8 +280,9 @@ struct Runtime { state: Mutex, buffer_runtimes: Mutex>, buffer_shutdown_intents: StdMutex>, - buffer_surfaces: Mutex>, + socket_path: PathBuf, workspace_path: PathBuf, + runtime_dir: PathBuf, buffer_env: BTreeMap, subscriptions: Mutex>, clients: Mutex>, @@ -288,21 +293,6 @@ struct Runtime { state_tasks: TaskCounter, } -struct BufferSurface { - router: RawByteRouter, - backend: Box, - size: PtySize, -} - -impl std::fmt::Debug for BufferSurface { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter - .debug_struct("BufferSurface") - .field("size", &self.size) - .finish() - } -} - #[derive(Clone, Default)] struct TaskCounter { inner: Arc, @@ -363,74 +353,21 @@ impl Drop for TaskTicket { } } -impl BufferSurface { - fn new(size: PtySize) -> Self { - Self { - router: RawByteRouter, - backend: Box::new(AlacrittyTerminalBackend::new(size)), - size, - } - } - - fn route_input(&mut self, bytes: Vec) -> Vec { - self.router.route_input(bytes) - } - - fn route_output(&mut self, bytes: &[u8]) { - self.router.route_output(self.backend.as_mut(), bytes); - } - - fn resize(&mut self, size: PtySize) { - self.size = size; - self.backend.resize(size); - } - - fn capture_lines(&self) -> Vec { - self.backend.capture_scrollback() - } - - fn capture_visible_snapshot( - &self, - sequence: u64, - cwd: Option, - ) -> embers_core::TerminalSnapshot { - self.backend.visible_snapshot(sequence, self.size, cwd) - } - - fn capture_scrollback_slice( - &self, - start_line: u64, - line_count: u32, - ) -> crate::BackendScrollbackSlice { - self.backend - .capture_scrollback_slice(start_line, line_count) - } - - fn metadata(&self) -> crate::BackendMetadata { - self.backend.metadata() - } - - fn take_activity(&mut self) -> embers_core::ActivityState { - self.backend.take_activity() - } - - fn damage(&mut self) -> BackendDamage { - self.backend.take_damage() - } -} - impl Runtime { fn new( state: ServerState, + socket_path: PathBuf, workspace_path: PathBuf, + runtime_dir: PathBuf, buffer_env: BTreeMap, ) -> Self { Self { state: Mutex::new(state), buffer_runtimes: Mutex::new(BTreeMap::new()), buffer_shutdown_intents: StdMutex::new(BTreeSet::new()), - buffer_surfaces: Mutex::new(BTreeMap::new()), + socket_path, workspace_path, + runtime_dir, buffer_env, subscriptions: Mutex::new(BTreeMap::new()), clients: Mutex::new(BTreeMap::new()), @@ -461,6 +398,99 @@ impl Runtime { .remove(&buffer_id) } + fn runtime_socket_path(&self, buffer_id: BufferId) -> Result { + let path = self + .runtime_dir + .join(format!("buffer-{}.sock", buffer_id.0)); + validate_keeper_socket_path(&self.socket_path, &path)?; + Ok(path) + } + + fn buffer_runtime_callbacks(self: &Arc) -> BufferRuntimeCallbacks { + let output_handle = tokio::runtime::Handle::current(); + let exit_handle = output_handle.clone(); + let output_runtime = self.clone(); + let exit_runtime = self.clone(); + let output_tasks = self.state_tasks.clone(); + let exit_tasks = self.state_tasks.clone(); + + BufferRuntimeCallbacks { + on_output: Arc::new(move |buffer_id, update| { + let runtime = output_runtime.clone(); + let task = output_tasks.enter(); + std::mem::drop(output_handle.spawn(async move { + let _task = task; + runtime.record_buffer_update(buffer_id, update).await; + })); + }), + on_exit: Arc::new(move |buffer_id, exit_code| { + let runtime = exit_runtime.clone(); + let task = exit_tasks.enter(); + std::mem::drop(exit_handle.spawn(async move { + let _task = task; + runtime.record_buffer_exit(buffer_id, exit_code).await; + })); + }), + } + } + + async fn restore_buffer_runtimes(self: &Arc) -> Result<()> { + let buffers = { + let state = self.state.lock().await; + state.buffers.values().cloned().collect::>() + }; + + for buffer in buffers { + let Some(socket_path) = buffer.runtime_socket_path().cloned() else { + if matches!(buffer.state, BufferState::Running(_) | BufferState::Created) { + let mut state = self.state.lock().await; + let _ = + state.mark_buffer_interrupted(buffer.id, buffer_pid_hint(&buffer.state)); + } + continue; + }; + if !socket_path.exists() { + debug!( + %buffer.id, + socket_path = %socket_path.display(), + "skipping runtime restore because keeper socket is missing" + ); + let mut state = self.state.lock().await; + let _ = state.set_buffer_runtime_socket_path(buffer.id, None); + let _ = state.mark_buffer_interrupted(buffer.id, buffer_pid_hint(&buffer.state)); + continue; + } + + match self + .attach_buffer_runtime(buffer.id, socket_path.clone()) + .await + { + Ok((runtime, status)) => { + let mut state = self.state.lock().await; + let _ = + state.set_buffer_runtime_socket_path(buffer.id, Some(socket_path.clone())); + apply_runtime_status(&mut state, buffer.id, &status); + drop(state); + self.buffer_runtimes.lock().await.insert(buffer.id, runtime); + } + Err(error) => { + debug!( + %buffer.id, + socket_path = %socket_path.display(), + %error, + "failed to restore buffer runtime" + ); + let mut state = self.state.lock().await; + let _ = state.set_buffer_runtime_socket_path(buffer.id, None); + let _ = + state.mark_buffer_interrupted(buffer.id, buffer_pid_hint(&buffer.state)); + } + } + } + + Ok(()) + } + async fn register_client( &self, connection_id: u64, @@ -859,7 +889,6 @@ impl Runtime { if let Err(error) = self.spawn_buffer_runtime(buffer_id).await { let mut state = self.state.lock().await; let _ = state.remove_buffer(buffer_id); - self.buffer_surfaces.lock().await.remove(&buffer_id); return (mux_error_response(Some(request_id), error), Vec::new()); } @@ -986,7 +1015,7 @@ impl Runtime { request_id, buffer_id, force: _, - } => match self.running_buffer_runtime(buffer_id).await { + } => match self.buffer_runtime(buffer_id).await { Ok(runtime) => match runtime.kill().await { Ok(()) => (ServerResponse::Ok(OkResponse { request_id }), Vec::new()), Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), @@ -1031,14 +1060,11 @@ impl Runtime { request_id, buffer_id, bytes, - } => match self.running_buffer_runtime(buffer_id).await { - Ok(runtime) => { - let bytes = self.route_input_bytes(buffer_id, bytes).await; - match runtime.write(bytes).await { - Ok(()) => (ServerResponse::Ok(OkResponse { request_id }), Vec::new()), - Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), - } - } + } => match self.buffer_runtime(buffer_id).await { + Ok(runtime) => match runtime.write(bytes).await { + Ok(()) => (ServerResponse::Ok(OkResponse { request_id }), Vec::new()), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + }, Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), }, InputRequest::Resize { @@ -1047,7 +1073,7 @@ impl Runtime { cols, rows, } => { - let runtime = match self.running_buffer_runtime(buffer_id).await { + let runtime = match self.buffer_runtime(buffer_id).await { Ok(runtime) => runtime, Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), }; @@ -1076,11 +1102,12 @@ impl Runtime { return (mux_error_response(Some(request_id), error), Vec::new()); } } - let damage = self.resize_surface(buffer_id, size).await; ( ServerResponse::Ok(OkResponse { request_id }), - render_events(buffer_id, damage), + vec![ServerEvent::RenderInvalidated(RenderInvalidatedEvent { + buffer_id, + })], ) } } @@ -1548,61 +1575,53 @@ impl Runtime { (buffer.command, buffer.cwd, buffer.pty_size, buffer.env) }; - let output_handle = tokio::runtime::Handle::current(); - let exit_handle = output_handle.clone(); - let output_runtime = self.clone(); - let exit_runtime = self.clone(); - let output_tasks = self.state_tasks.clone(); - let exit_tasks = self.state_tasks.clone(); let mut buffer_env = self.buffer_env.clone(); for (key, value) in env_hints { buffer_env.insert(key, OsString::from(value)); } let runtime = BufferRuntimeHandle::spawn( buffer_id, + self.runtime_socket_path(buffer_id)?, &command, cwd.as_deref(), &buffer_env, size, - BufferRuntimeCallbacks { - on_output: Arc::new(move |buffer_id, bytes| { - let runtime = output_runtime.clone(); - let _task = output_tasks.enter(); - std::mem::drop(output_handle.spawn(async move { - let _task = _task; - runtime.record_buffer_output(buffer_id, bytes).await; - })); - }), - on_exit: Arc::new(move |buffer_id, exit_code| { - let runtime = exit_runtime.clone(); - let _task = exit_tasks.enter(); - std::mem::drop(exit_handle.spawn(async move { - let _task = _task; - runtime.record_buffer_exit(buffer_id, exit_code).await; - })); - }), - }, - )?; + self.buffer_runtime_callbacks(), + ) + .await?; + let status = runtime.status().await?; { let mut state = self.state.lock().await; - if let Err(error) = state.mark_buffer_running(buffer_id, runtime.pid()) { + if let Err(error) = state.mark_buffer_running(buffer_id, status.pid) { let _ = runtime.kill().await; let _ = runtime.join_threads().await; return Err(error); } + state.set_buffer_runtime_socket_path( + buffer_id, + Some(runtime.socket_path().to_path_buf()), + )?; + apply_runtime_status(&mut state, buffer_id, &status); } - self.buffer_surfaces - .lock() - .await - .entry(buffer_id) - .or_insert_with(|| BufferSurface::new(size)); self.buffer_runtimes.lock().await.insert(buffer_id, runtime); Ok(()) } - async fn running_buffer_runtime(&self, buffer_id: BufferId) -> Result { + async fn attach_buffer_runtime( + self: &Arc, + buffer_id: BufferId, + socket_path: PathBuf, + ) -> Result<(BufferRuntimeHandle, BufferRuntimeStatus)> { + let runtime = + BufferRuntimeHandle::attach(buffer_id, socket_path, self.buffer_runtime_callbacks()) + .await?; + let status = runtime.status().await?; + Ok((runtime, status)) + } + + async fn buffer_runtime(&self, buffer_id: BufferId) -> Result { if let Some(runtime) = self.buffer_runtimes.lock().await.get(&buffer_id).cloned() { return Ok(runtime); } @@ -1634,21 +1653,17 @@ impl Runtime { let state = self.state.lock().await; state.buffer(buffer_id)?.clone() }; - let lines = self - .buffer_surfaces - .lock() - .await - .get(&buffer_id) - .map(BufferSurface::capture_lines) - .unwrap_or_default(); + let runtime = self.buffer_runtime(buffer_id).await?; + let snapshot = runtime.capture_snapshot(buffer.cwd.clone()).await?; + self.sync_buffer_runtime_status(buffer_id, &runtime).await?; Ok(SnapshotResponse { request_id, buffer_id, - sequence: buffer.last_snapshot_seq, - size: buffer.pty_size, - lines, - title: Some(buffer.title), + sequence: snapshot.sequence, + size: snapshot.size, + lines: snapshot.lines, + title: snapshot.title.or(Some(buffer.title)), cwd: buffer.cwd.map(|path| path.display().to_string()), }) } @@ -1662,13 +1677,9 @@ impl Runtime { let state = self.state.lock().await; state.buffer(buffer_id)?.clone() }; - let snapshot = { - let mut surfaces = self.buffer_surfaces.lock().await; - surfaces - .entry(buffer_id) - .or_insert_with(|| BufferSurface::new(buffer.pty_size)) - .capture_visible_snapshot(buffer.last_snapshot_seq, buffer.cwd.clone()) - }; + let runtime = self.buffer_runtime(buffer_id).await?; + let snapshot = runtime.capture_visible_snapshot(buffer.cwd.clone()).await?; + self.sync_buffer_runtime_status(buffer_id, &runtime).await?; Ok(VisibleSnapshotResponse { request_id, @@ -1695,17 +1706,11 @@ impl Runtime { start_line: u64, line_count: u32, ) -> Result { - let buffer = { - let state = self.state.lock().await; - state.buffer(buffer_id)?.clone() - }; - let slice = { - let mut surfaces = self.buffer_surfaces.lock().await; - surfaces - .entry(buffer_id) - .or_insert_with(|| BufferSurface::new(buffer.pty_size)) - .capture_scrollback_slice(start_line, line_count) - }; + let runtime = self.buffer_runtime(buffer_id).await?; + let slice = runtime + .capture_scrollback_slice(start_line, line_count) + .await?; + self.sync_buffer_runtime_status(buffer_id, &runtime).await?; Ok(ScrollbackSliceResponse { request_id, @@ -1716,74 +1721,52 @@ impl Runtime { }) } - async fn route_input_bytes(&self, buffer_id: BufferId, bytes: Vec) -> Vec { - match self.buffer_surfaces.lock().await.get_mut(&buffer_id) { - Some(surface) => surface.route_input(bytes), - None => bytes, - } - } - - async fn resize_surface(&self, buffer_id: BufferId, size: PtySize) -> BackendDamage { - let mut surfaces = self.buffer_surfaces.lock().await; - let surface = surfaces - .entry(buffer_id) - .or_insert_with(|| BufferSurface::new(size)); - surface.resize(size); - surface.damage() - } - - async fn record_buffer_output(&self, buffer_id: BufferId, bytes: Vec) { - let size = { + async fn record_buffer_update(&self, buffer_id: BufferId, update: BufferRuntimeUpdate) { + let updated = { let mut state = self.state.lock().await; - if let Err(error) = state.note_buffer_output(buffer_id) { - debug!(%buffer_id, %error, "dropping PTY output for unknown buffer"); + let Some(buffer) = state.buffers.get_mut(&buffer_id) else { return; - } - match state.buffer(buffer_id) { - Ok(buffer) => buffer.pty_size, - Err(error) => { - debug!(%buffer_id, %error, "buffer disappeared while recording output"); - return; + }; + if update.sequence <= buffer.last_snapshot_seq { + false + } else { + buffer.last_snapshot_seq = update.sequence; + buffer.activity = update.activity; + if let Some(title) = update.title { + match title { + Some(title) => buffer.title = title, + None => buffer.title.clear(), + } } + true } }; - let (metadata, activity, damage) = { - let mut surfaces = self.buffer_surfaces.lock().await; - let surface = surfaces - .entry(buffer_id) - .or_insert_with(|| BufferSurface::new(size)); - surface.resize(size); - surface.route_output(&bytes); - ( - surface.metadata(), - surface.take_activity(), - surface.damage(), + if updated { + self.broadcast( + vec![ServerEvent::RenderInvalidated(RenderInvalidatedEvent { + buffer_id, + })], + &[], ) - }; - - { - let mut state = self.state.lock().await; - if let Some(title) = metadata.title - && let Err(error) = state.set_buffer_title(buffer_id, title) - { - debug!(%buffer_id, %error, "failed to apply terminal title update"); - } - if let Err(error) = state.set_buffer_activity(buffer_id, activity) { - debug!(%buffer_id, %error, "failed to apply buffer activity update"); - } + .await; } - - self.broadcast(render_events(buffer_id, damage), &[]).await; } async fn record_buffer_exit(&self, buffer_id: BufferId, exit_code: Option) { - let runtime = self.buffer_runtimes.lock().await.remove(&buffer_id); let should_interrupt = self.take_buffer_shutdown_intent(buffer_id); + if should_interrupt { + let runtime = self.buffer_runtimes.lock().await.remove(&buffer_id); + drop(runtime); + } let updated = { let mut state = self.state.lock().await; let result = if should_interrupt { - state.mark_buffer_interrupted(buffer_id) + let pid = state + .buffers + .get(&buffer_id) + .and_then(|buffer| buffer_pid_hint(&buffer.state)); + state.mark_buffer_interrupted(buffer_id, pid) } else { state.mark_buffer_exited(buffer_id, exit_code) }; @@ -1796,12 +1779,6 @@ impl Runtime { } }; - if let Some(runtime) = runtime - && let Err(error) = runtime.join_threads().await - { - debug!(%buffer_id, %error, "failed to join buffer runtime threads"); - } - if updated { self.broadcast( vec![ServerEvent::RenderInvalidated(RenderInvalidatedEvent { @@ -1813,6 +1790,27 @@ impl Runtime { } } + async fn sync_buffer_runtime_status( + &self, + buffer_id: BufferId, + runtime: &BufferRuntimeHandle, + ) -> Result<()> { + let status = runtime.status().await?; + self.record_buffer_update( + buffer_id, + BufferRuntimeUpdate { + sequence: status.sequence, + activity: status.activity, + title: Some(status.title.clone()), + }, + ) + .await; + if !status.running { + self.record_buffer_exit(buffer_id, status.exit_code).await; + } + Ok(()) + } + async fn shutdown_runtimes(&self) { let runtimes: Vec<_> = { let runtimes = self.buffer_runtimes.lock().await; @@ -1829,13 +1827,11 @@ impl Runtime { .collect() }; for runtime in runtimes { - if let Err(error) = runtime.kill().await { - debug!(%error, "failed to kill buffer runtime during shutdown"); - } if let Err(error) = runtime.join_threads().await { debug!(%error, "failed to join buffer runtime threads during shutdown"); } } + self.buffer_runtimes.lock().await.clear(); } async fn broadcast( @@ -2175,6 +2171,36 @@ fn set_socket_permissions(socket_path: &Path) -> Result<()> { Ok(()) } +/// Maximum Unix-domain socket path length in bytes for runtime keeper sockets. +/// These values come from `sockaddr_un.sun_path`: macOS exposes 104 bytes per +/// `unix(4)`, while other Unix/Linux platforms expose 108 bytes per `unix(7)`. +/// `validate_keeper_socket_path` uses this limit to validate keeper socket +/// paths derived from the server socket path before binding. +#[cfg(target_os = "macos")] +const UNIX_SOCKET_PATH_LIMIT: usize = 104; +/// Maximum Unix-domain socket path length in bytes for runtime keeper sockets. +/// These values come from `sockaddr_un.sun_path`: macOS exposes 104 bytes per +/// `unix(4)`, while other Unix/Linux platforms expose 108 bytes per `unix(7)`. +/// `validate_keeper_socket_path` uses this limit to validate keeper socket +/// paths derived from the server socket path before binding. +#[cfg(all(unix, not(target_os = "macos")))] +const UNIX_SOCKET_PATH_LIMIT: usize = 108; + +fn validate_keeper_socket_path(server_socket_path: &Path, keeper_socket_path: &Path) -> Result<()> { + #[cfg(unix)] + { + let len = keeper_socket_path.as_os_str().as_bytes().len(); + if len > UNIX_SOCKET_PATH_LIMIT { + return Err(MuxError::invalid_input(format!( + "runtime keeper socket path is too long ({len} bytes, max {UNIX_SOCKET_PATH_LIMIT}): {} (runtime_dir derived from server socket {}). Use a shorter server socket path.", + keeper_socket_path.display(), + server_socket_path.display(), + ))); + } + } + Ok(()) +} + fn protocol_tab_index(index: u32) -> Result { usize::try_from(index) .map_err(|_| MuxError::invalid_input(format!("tab index {index} exceeds platform limits"))) @@ -2254,24 +2280,48 @@ fn protocol_error_to_mux(error: ProtocolError) -> MuxError { MuxError::protocol(error.to_string()) } -fn render_events(buffer_id: BufferId, damage: BackendDamage) -> Vec { - match damage { - BackendDamage::None => Vec::new(), - BackendDamage::Full | BackendDamage::Partial(_) => { - vec![ServerEvent::RenderInvalidated(RenderInvalidatedEvent { - buffer_id, - })] - } +fn apply_runtime_status( + state: &mut ServerState, + buffer_id: BufferId, + status: &BufferRuntimeStatus, +) { + if let Some(buffer) = state.buffers.get_mut(&buffer_id) { + buffer.last_snapshot_seq = status.sequence; + } + if let Some(title) = &status.title { + let _ = state.set_buffer_title(buffer_id, title.clone()); + } + let _ = state.set_buffer_activity(buffer_id, status.activity); + if status.running { + let _ = state.mark_buffer_running(buffer_id, status.pid); + } else { + let _ = state.mark_buffer_exited(buffer_id, status.exit_code); + } +} + +fn buffer_pid_hint(state: &BufferState) -> Option { + match state { + BufferState::Running(running) => running.pid, + BufferState::Interrupted(interrupted) => interrupted.last_known_pid, + BufferState::Created | BufferState::Exited(_) => None, } } #[cfg(test)] mod tests { use std::collections::BTreeMap; + #[cfg(unix)] + use std::os::unix::net::UnixListener as StdUnixListener; use std::path::PathBuf; + use std::sync::Arc; - use super::{Runtime, ShutdownSignal, wait_for_shutdown}; - use crate::ServerState; + use embers_core::ActivityState; + use embers_protocol::{ServerEnvelope, ServerEvent}; + use tempfile::tempdir; + use tokio::sync::mpsc; + + use super::{Runtime, ShutdownSignal, Subscription, wait_for_shutdown}; + use crate::{BufferRuntimeUpdate, BufferState, ServerState}; use tokio::time::{Duration, timeout}; @@ -2290,7 +2340,9 @@ mod tests { fn buffer_shutdown_intents_are_consumed_per_buffer() { let runtime = Runtime::new( ServerState::new(), + PathBuf::from("server.sock"), PathBuf::from("workspace"), + PathBuf::from("runtime"), BTreeMap::new(), ); runtime @@ -2303,4 +2355,197 @@ mod tests { assert!(!runtime.take_buffer_shutdown_intent(embers_core::BufferId(1))); assert!(!runtime.take_buffer_shutdown_intent(embers_core::BufferId(2))); } + + #[tokio::test] + async fn record_buffer_update_ignores_stale_sequences() { + let runtime = Runtime::new( + ServerState::new(), + PathBuf::from("server.sock"), + PathBuf::from("workspace"), + PathBuf::from("runtime"), + BTreeMap::new(), + ); + let buffer_id = { + let mut state = runtime.state.lock().await; + let buffer_id = state.create_buffer("current-title", vec!["/bin/sh".to_owned()], None); + let buffer = state + .buffers + .get_mut(&buffer_id) + .expect("buffer is created"); + buffer.last_snapshot_seq = 5; + buffer.activity = ActivityState::Activity; + buffer_id + }; + let (sender, mut receiver) = mpsc::unbounded_channel(); + runtime.subscriptions.lock().await.insert( + 1, + Subscription { + connection_id: 1, + session_id: None, + sender, + }, + ); + + runtime + .record_buffer_update( + buffer_id, + BufferRuntimeUpdate { + sequence: 5, + activity: ActivityState::Bell, + title: Some(Some("stale-title".to_owned())), + }, + ) + .await; + + let buffer = runtime + .state + .lock() + .await + .buffer(buffer_id) + .expect("buffer exists") + .clone(); + assert_eq!(buffer.last_snapshot_seq, 5); + assert_eq!(buffer.activity, ActivityState::Activity); + assert_eq!(buffer.title, "current-title"); + assert!(receiver.try_recv().is_err()); + + runtime + .record_buffer_update( + buffer_id, + BufferRuntimeUpdate { + sequence: 6, + activity: ActivityState::Bell, + title: Some(Some("fresh-title".to_owned())), + }, + ) + .await; + + let buffer = runtime + .state + .lock() + .await + .buffer(buffer_id) + .expect("buffer exists") + .clone(); + assert_eq!(buffer.last_snapshot_seq, 6); + assert_eq!(buffer.activity, ActivityState::Bell); + assert_eq!(buffer.title, "fresh-title"); + assert!(matches!( + receiver.try_recv(), + Ok(ServerEnvelope::Event(ServerEvent::RenderInvalidated(event))) + if event.buffer_id == buffer_id + )); + } + + #[tokio::test] + async fn record_buffer_update_clears_title() { + let runtime = Runtime::new( + ServerState::new(), + PathBuf::from("server.sock"), + PathBuf::from("workspace"), + PathBuf::from("runtime"), + BTreeMap::new(), + ); + let buffer_id = { + let mut state = runtime.state.lock().await; + let buffer_id = state.create_buffer("current-title", vec!["/bin/sh".to_owned()], None); + let buffer = state + .buffers + .get_mut(&buffer_id) + .expect("buffer is created"); + buffer.last_snapshot_seq = 5; + buffer_id + }; + + runtime + .record_buffer_update( + buffer_id, + BufferRuntimeUpdate { + sequence: 6, + activity: ActivityState::Idle, + title: Some(None), + }, + ) + .await; + + let buffer = runtime + .state + .lock() + .await + .buffer(buffer_id) + .expect("buffer exists") + .clone(); + assert_eq!(buffer.last_snapshot_seq, 6); + assert_eq!(buffer.title, ""); + } + + #[tokio::test] + async fn restore_buffer_runtimes_clears_missing_socket_paths() { + let tempdir = tempdir().expect("tempdir"); + let mut state = ServerState::new(); + let buffer_id = state.create_buffer("buffer", vec!["/bin/sh".to_owned()], None); + state + .mark_buffer_running(buffer_id, Some(42)) + .expect("mark running"); + state + .set_buffer_runtime_socket_path( + buffer_id, + Some(tempdir.path().join("missing-runtime.sock")), + ) + .expect("set runtime socket path"); + + let runtime = Arc::new(Runtime::new( + state, + tempdir.path().join("server.sock"), + tempdir.path().join("workspace.json"), + tempdir.path().join("runtime"), + BTreeMap::new(), + )); + + runtime + .restore_buffer_runtimes() + .await + .expect("restore succeeds"); + + let state = runtime.state.lock().await; + let buffer = state.buffer(buffer_id).expect("buffer exists"); + assert!(matches!(buffer.state, BufferState::Interrupted(_))); + assert_eq!(buffer.runtime_socket_path(), None); + } + + #[cfg(unix)] + #[tokio::test] + async fn restore_buffer_runtimes_clears_unreachable_socket_paths() { + let tempdir = tempdir().expect("tempdir"); + let socket_path = tempdir.path().join("stale-runtime.sock"); + let listener = StdUnixListener::bind(&socket_path).expect("bind stale socket"); + drop(listener); + + let mut state = ServerState::new(); + let buffer_id = state.create_buffer("buffer", vec!["/bin/sh".to_owned()], None); + state + .mark_buffer_running(buffer_id, Some(42)) + .expect("mark running"); + state + .set_buffer_runtime_socket_path(buffer_id, Some(socket_path.clone())) + .expect("set runtime socket path"); + + let runtime = Arc::new(Runtime::new( + state, + tempdir.path().join("server.sock"), + tempdir.path().join("workspace.json"), + tempdir.path().join("runtime"), + BTreeMap::new(), + )); + + runtime + .restore_buffer_runtimes() + .await + .expect("restore succeeds"); + + let state = runtime.state.lock().await; + let buffer = state.buffer(buffer_id).expect("buffer exists"); + assert!(matches!(buffer.state, BufferState::Interrupted(_))); + assert_eq!(buffer.runtime_socket_path(), None); + } } diff --git a/crates/embers-server/src/state.rs b/crates/embers-server/src/state.rs index 35cfbdbf..416d58d2 100644 --- a/crates/embers-server/src/state.rs +++ b/crates/embers-server/src/state.rs @@ -122,7 +122,7 @@ impl ServerState { let safe_next_node_id = next_id_after_max(nodes.keys().map(|id| id.0)); let safe_next_floating_id = next_id_after_max(floating.keys().map(|id| id.0)); - let mut state = Self { + let state = Self { sessions, buffers, nodes, @@ -132,7 +132,6 @@ impl ServerState { node_ids: IdAllocator::new(next_node_id.max(safe_next_node_id)), floating_ids: IdAllocator::new(next_floating_id.max(safe_next_floating_id)), }; - state.interrupt_unrecoverable_buffers(); state.validate()?; Ok(state) } @@ -346,22 +345,8 @@ impl ServerState { env: BTreeMap, ) -> BufferId { let buffer_id = self.buffer_ids.next(); - self.buffers.insert( - buffer_id, - Buffer { - id: buffer_id, - title: title.into(), - command, - cwd, - env, - state: BufferState::Created, - attachment: BufferAttachment::Detached, - pty_size: PtySize::new(80, 24), - activity: ActivityState::Idle, - last_snapshot_seq: 0, - created_at: Timestamp::now(), - }, - ); + self.buffers + .insert(buffer_id, Buffer::new(buffer_id, title, command, cwd, env)); buffer_id } @@ -388,6 +373,27 @@ impl ServerState { Ok(()) } + pub fn set_buffer_runtime_socket_path( + &mut self, + buffer_id: BufferId, + runtime_socket_path: Option, + ) -> Result<()> { + self.buffer_mut(buffer_id)? + .set_runtime_socket_path(runtime_socket_path); + Ok(()) + } + + pub fn mark_buffer_interrupted(&mut self, buffer_id: BufferId, pid: Option) -> Result<()> { + let buffer = self.buffer_mut(buffer_id)?; + if matches!(buffer.state, BufferState::Exited(_)) { + return Ok(()); + } + buffer.state = BufferState::Interrupted(InterruptedBuffer { + last_known_pid: pid, + }); + Ok(()) + } + pub fn mark_buffer_exited( &mut self, buffer_id: BufferId, @@ -401,17 +407,6 @@ impl ServerState { Ok(()) } - pub fn mark_buffer_interrupted(&mut self, buffer_id: BufferId) -> Result<()> { - let buffer = self.buffer_mut(buffer_id)?; - let last_known_pid = match &buffer.state { - BufferState::Running(running) => running.pid, - BufferState::Interrupted(interrupted) => interrupted.last_known_pid, - BufferState::Created | BufferState::Exited(_) => None, - }; - buffer.state = BufferState::Interrupted(InterruptedBuffer { last_known_pid }); - Ok(()) - } - pub fn interrupt_unrecoverable_buffers(&mut self) { for buffer in self.buffers.values_mut() { buffer.state = match &buffer.state { diff --git a/crates/embers-server/tests/persistence.rs b/crates/embers-server/tests/persistence.rs index ecb4a848..dc1d7ffd 100644 --- a/crates/embers-server/tests/persistence.rs +++ b/crates/embers-server/tests/persistence.rs @@ -1,7 +1,7 @@ use embers_core::{BufferId, RequestId, init_test_tracing}; use embers_protocol::{ - BufferRecordState, BufferRequest, BufferResponse, BuffersResponse, ClientMessage, - ProtocolClient, ServerResponse, SessionRequest, SessionSnapshotResponse, + BufferRecordState, BufferRequest, BufferResponse, BuffersResponse, ClientMessage, InputRequest, + ProtocolClient, ServerResponse, SessionRequest, SessionSnapshotResponse, SnapshotResponse, }; use embers_server::{Server, ServerConfig}; use tempfile::tempdir; @@ -43,8 +43,38 @@ async fn request_buffers(client: &mut ProtocolClient, request: BufferRequest) -> } } +async fn wait_for_snapshot_line( + client: &mut ProtocolClient, + request_id: RequestId, + buffer_id: BufferId, + expected: &str, +) -> SnapshotResponse { + let deadline = Instant::now() + Duration::from_secs(2); + loop { + if let Ok(ServerResponse::Snapshot(snapshot)) = client + .request(&ClientMessage::Buffer(BufferRequest::Capture { + request_id, + buffer_id, + })) + .await + && snapshot.lines.iter().any(|line| line.contains(expected)) + { + return snapshot; + } + + if Instant::now() >= deadline { + break; + } + sleep(Duration::from_millis(25)).await; + } + + panic!( + "capture for buffer {buffer_id} did not contain expected line '{expected}' before timeout" + ); +} + #[tokio::test] -async fn clean_restart_restores_workspace_and_marks_live_buffers_interrupted() { +async fn clean_restart_restores_workspace_and_keeps_live_buffers_running() { init_test_tracing(); let tempdir = tempdir().expect("tempdir"); @@ -158,7 +188,7 @@ async fn clean_restart_restores_workspace_and_marks_live_buffers_interrupted() { .iter() .find(|buffer| buffer.id == attached_id) .expect("attached buffer restored"); - assert_eq!(attached_buffer.state, BufferRecordState::Interrupted); + assert_eq!(attached_buffer.state, BufferRecordState::Running); assert!(attached_buffer.attachment_node_id.is_some()); let buffers = request_buffers( @@ -176,22 +206,45 @@ async fn clean_restart_restores_workspace_and_marks_live_buffers_interrupted() { .iter() .find(|buffer| buffer.id == detached_id) .expect("detached buffer restored"); - assert_eq!(detached_buffer.state, BufferRecordState::Interrupted); + assert_eq!(detached_buffer.state, BufferRecordState::Running); assert_eq!(detached_buffer.attachment_node_id, None); - let send_err = client - .request(&ClientMessage::Buffer(BufferRequest::Get { + match client + .request(&ClientMessage::Input(InputRequest::Send { request_id: RequestId(7), - buffer_id: BufferId(detached_id.0), + buffer_id: attached_id, + bytes: b"printf restarted-attached\\n\r".to_vec(), })) .await - .expect("buffer get succeeds"); - match send_err { - ServerResponse::Buffer(response) => { - assert_eq!(response.buffer.state, BufferRecordState::Interrupted); - } - other => panic!("expected restored interrupted buffer, got {other:?}"), + .expect("send to attached buffer succeeds") + { + ServerResponse::Ok(_) => {} + other => panic!("expected ok response, got {other:?}"), } + match client + .request(&ClientMessage::Input(InputRequest::Send { + request_id: RequestId(8), + buffer_id: detached_id, + bytes: b"printf restarted-detached\\n\r".to_vec(), + })) + .await + .expect("send to detached buffer succeeds") + { + ServerResponse::Ok(_) => {} + other => panic!("expected ok response, got {other:?}"), + } + + let _attached_capture = + wait_for_snapshot_line(&mut client, RequestId(9), attached_id, "restarted-attached").await; + + let _detached_capture = wait_for_snapshot_line( + &mut client, + RequestId(10), + detached_id, + "restarted-detached", + ) + .await; + handle.shutdown().await.expect("shutdown restarted server"); } diff --git a/crates/embers-test-support/Cargo.toml b/crates/embers-test-support/Cargo.toml index 50a66f5f..b3961c04 100644 --- a/crates/embers-test-support/Cargo.toml +++ b/crates/embers-test-support/Cargo.toml @@ -11,6 +11,7 @@ assert_cmd.workspace = true embers-core = { path = "../embers-core" } embers-protocol = { path = "../embers-protocol" } embers-server = { path = "../embers-server" } +libc.workspace = true portable-pty.workspace = true tempfile.workspace = true tokio.workspace = true diff --git a/crates/embers-test-support/src/lib.rs b/crates/embers-test-support/src/lib.rs index dab8150a..03383369 100644 --- a/crates/embers-test-support/src/lib.rs +++ b/crates/embers-test-support/src/lib.rs @@ -2,8 +2,10 @@ mod cli; mod protocol; mod pty; mod server; +mod test_lock; pub use cli::{cargo_bin, cargo_bin_path}; pub use protocol::TestConnection; pub use pty::PtyHarness; pub use server::TestServer; +pub use test_lock::{InterprocessTestLock, acquire_test_lock}; diff --git a/crates/embers-test-support/src/test_lock.rs b/crates/embers-test-support/src/test_lock.rs new file mode 100644 index 00000000..de3809b1 --- /dev/null +++ b/crates/embers-test-support/src/test_lock.rs @@ -0,0 +1,115 @@ +use std::fs::{File, OpenOptions}; +use std::io; +#[cfg(unix)] +use std::os::fd::AsRawFd; +#[cfg(not(unix))] +use std::path::PathBuf; +use std::sync::{Arc, OnceLock}; + +#[cfg(not(unix))] +use std::thread; +#[cfg(not(unix))] +use std::time::{Duration, Instant}; +use tokio::sync::{Mutex, OwnedMutexGuard}; + +const TEST_LOCK_FILE_NAME: &str = "embers-integration-tests.lock"; +#[cfg(not(unix))] +const FILE_LOCK_RETRY_DELAY: Duration = Duration::from_millis(10); +#[cfg(not(unix))] +const FILE_LOCK_TIMEOUT: Duration = Duration::from_secs(10); + +fn process_lock() -> Arc> { + static LOCK: OnceLock>> = OnceLock::new(); + LOCK.get_or_init(|| Arc::new(Mutex::new(()))).clone() +} + +pub struct InterprocessTestLock { + _process_guard: OwnedMutexGuard<()>, + file: File, + #[cfg(not(unix))] + path: PathBuf, +} + +pub async fn acquire_test_lock() -> io::Result { + let process_guard = process_lock().lock_owned().await; + let path = std::env::temp_dir().join(TEST_LOCK_FILE_NAME); + + #[cfg(unix)] + let file = tokio::task::spawn_blocking(move || acquire_file_lock(path)) + .await + .map_err(|error| io::Error::other(error.to_string()))??; + + #[cfg(not(unix))] + let (file, path) = tokio::task::spawn_blocking(move || acquire_file_lock(path)) + .await + .map_err(|error| io::Error::other(error.to_string()))??; + + Ok(InterprocessTestLock { + _process_guard: process_guard, + file, + #[cfg(not(unix))] + path, + }) +} + +#[cfg(unix)] +fn acquire_file_lock(path: std::path::PathBuf) -> io::Result { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent)?; + } + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .open(path)?; + let result = unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_EX) }; + if result != 0 { + return Err(io::Error::last_os_error()); + } + Ok(file) +} + +#[cfg(not(unix))] +fn acquire_file_lock(path: PathBuf) -> io::Result<(File, PathBuf)> { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent)?; + } + let started = Instant::now(); + loop { + match OpenOptions::new() + .read(true) + .write(true) + .create_new(true) + .open(&path) + { + Ok(file) => return Ok((file, path)), + Err(error) if error.kind() == io::ErrorKind::AlreadyExists => { + thread::sleep(FILE_LOCK_RETRY_DELAY); + if started.elapsed() >= FILE_LOCK_TIMEOUT { + return Err(io::Error::new( + io::ErrorKind::TimedOut, + format!( + "timed out acquiring integration test lock at {}; remove the orphaned lock file if no other test process is using it", + path.display() + ), + )); + } + } + Err(error) => return Err(error), + } + } +} + +impl Drop for InterprocessTestLock { + fn drop(&mut self) { + #[cfg(unix)] + { + let _ = unsafe { libc::flock(self.file.as_raw_fd(), libc::LOCK_UN) }; + } + #[cfg(not(unix))] + { + let _ = std::fs::remove_file(&self.path); + } + } +} diff --git a/crates/embers-test-support/tests/buffer_runtime.rs b/crates/embers-test-support/tests/buffer_runtime.rs index 0b2a688c..67005419 100644 --- a/crates/embers-test-support/tests/buffer_runtime.rs +++ b/crates/embers-test-support/tests/buffer_runtime.rs @@ -5,7 +5,7 @@ use embers_protocol::{ BufferRecord, BufferRecordState, BufferRequest, ClientMessage, InputRequest, OkResponse, ServerResponse, SnapshotResponse, }; -use embers_test_support::{TestConnection, TestServer}; +use embers_test_support::{TestConnection, TestServer, acquire_test_lock}; use tokio::time::sleep; async fn create_buffer(connection: &mut TestConnection, command: &[&str]) -> BufferRecord { @@ -178,6 +178,7 @@ async fn wait_for_exit( #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn detached_buffers_accept_input_and_keep_running_after_detach_requests() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); let mut connection = TestConnection::connect(server.socket_path()) .await @@ -215,6 +216,7 @@ async fn detached_buffers_accept_input_and_keep_running_after_detach_requests() #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn resize_and_kill_requests_update_buffer_state_and_preserve_capture() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); let mut connection = TestConnection::connect(server.socket_path()) .await @@ -245,6 +247,7 @@ async fn resize_and_kill_requests_update_buffer_state_and_preserve_capture() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn capture_preserves_scrollback_for_long_output() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); let mut connection = TestConnection::connect(server.socket_path()) .await @@ -270,6 +273,7 @@ async fn capture_preserves_scrollback_for_long_output() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn visible_snapshot_surfaces_terminal_modes_and_cursor_metadata() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); let mut connection = TestConnection::connect(server.socket_path()) .await @@ -305,6 +309,7 @@ async fn visible_snapshot_surfaces_terminal_modes_and_cursor_metadata() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn scrollback_slice_returns_history_while_full_capture_stays_available() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); let server = TestServer::start().await.expect("start server"); let mut connection = TestConnection::connect(server.socket_path()) .await From d6639e8892afc8b38e2c7baec21a70ee23051ea9 Mon Sep 17 00:00:00 2001 From: Emma <817422+Pajn@users.noreply.github.com> Date: Sun, 22 Mar 2026 21:50:10 +0100 Subject: [PATCH 2/5] Add native buffer reveal and history helpers --- crates/embers-cli/src/lib.rs | 362 ++++++++++- crates/embers-cli/tests/interactive.rs | 71 +- crates/embers-cli/tests/panes.rs | 128 +++- crates/embers-client/Cargo.toml | 3 + crates/embers-client/src/configured_client.rs | 12 +- .../embers-client/tests/configured_client.rs | 20 +- crates/embers-client/tests/reducer.rs | 15 +- crates/embers-client/tests/support/mod.rs | 12 +- crates/embers-core/Cargo.toml | 3 + crates/embers-protocol/Cargo.toml | 3 + crates/embers-protocol/schema/embers.fbs | 73 ++- crates/embers-protocol/src/codec.rs | 610 ++++++++++++++++++ crates/embers-protocol/src/lib.rs | 20 +- crates/embers-protocol/src/types.rs | 124 +++- .../tests/family_round_trip.rs | 68 ++ crates/embers-server/Cargo.toml | 3 + crates/embers-server/src/model.rs | 24 + crates/embers-server/src/persist.rs | 73 ++- crates/embers-server/src/protocol.rs | 52 +- crates/embers-server/src/server.rs | 384 ++++++++++- crates/embers-server/src/state.rs | 30 +- crates/embers-test-support/Cargo.toml | 3 + 22 files changed, 2040 insertions(+), 53 deletions(-) diff --git a/crates/embers-cli/src/lib.rs b/crates/embers-cli/src/lib.rs index a8cea15d..f9e0b2ac 100644 --- a/crates/embers-cli/src/lib.rs +++ b/crates/embers-cli/src/lib.rs @@ -20,9 +20,11 @@ use embers_core::{ new_request_id, }; use embers_protocol::{ + BufferHistoryPlacement, BufferHistoryScope, BufferLocation, BufferLocationResponse, BufferRequest, BufferResponse, ClientMessage, ClientRecord, ClientRequest, FloatingRecord, - FloatingRequest, FloatingResponse, NodeRequest, PingRequest, ProtocolClient, ServerResponse, - SessionRecord, SessionRequest, SessionSnapshot, SnapshotResponse, + FloatingRequest, FloatingResponse, NodeBreakDestination, NodeJoinPlacement, NodeRequest, + PingRequest, ProtocolClient, ServerResponse, SessionRecord, SessionRequest, SessionSnapshot, + SnapshotResponse, }; use embers_server::{SOCKET_ENV_VAR, Server, ServerConfig}; use tokio::time::{Duration, sleep}; @@ -143,6 +145,14 @@ pub enum Command { #[arg(short = 't', long = "target")] target: String, }, + Buffer { + #[command(subcommand)] + command: BufferCommand, + }, + Node { + #[command(subcommand)] + command: NodeCommand, + }, #[command(name = "new-window")] NewWindow { #[arg(short = 't', long = "target")] @@ -243,6 +253,94 @@ pub enum Command { }, } +#[derive(Debug, Subcommand)] +pub enum BufferCommand { + Show { + buffer_id: u64, + }, + Reveal { + buffer_id: u64, + #[arg(long)] + client: Option, + }, + History { + buffer_id: u64, + #[arg(long, default_value = "full")] + scope: HistoryScopeArg, + #[arg(long, default_value = "tab")] + placement: HistoryPlacementArg, + #[arg(long)] + client: Option, + }, +} + +#[derive(Debug, Subcommand)] +pub enum NodeCommand { + Zoom { + node_id: u64, + }, + Unzoom { + #[arg(short = 't', long = "target")] + target: Option, + }, + ToggleZoom { + node_id: u64, + }, + Swap { + first_node_id: u64, + second_node_id: u64, + }, + Break { + node_id: u64, + #[arg(long = "to")] + destination: BreakDestinationArg, + }, + JoinBuffer { + node_id: u64, + buffer_id: u64, + #[arg(long = "as")] + placement: JoinPlacementArg, + }, + MoveBefore { + node_id: u64, + sibling_id: u64, + }, + MoveAfter { + node_id: u64, + sibling_id: u64, + }, +} + +#[derive(Clone, Copy, Debug, clap::ValueEnum)] +pub enum HistoryScopeArg { + Full, + Visible, +} + +#[derive(Clone, Copy, Debug, clap::ValueEnum)] +pub enum HistoryPlacementArg { + Tab, + Floating, +} + +#[derive(Clone, Copy, Debug, clap::ValueEnum)] +pub enum BreakDestinationArg { + Tab, + Floating, +} + +#[derive(Clone, Copy, Debug, clap::ValueEnum)] +pub enum JoinPlacementArg { + Left, + Right, + Up, + Down, + #[value(name = "tab-before")] + TabBefore, + #[value(name = "tab-after")] + TabAfter, +} + async fn execute(socket: &Path, command: Command) -> Result { let mut connection = CliConnection::connect(socket).await?; @@ -377,6 +475,164 @@ async fn execute(socket: &Path, command: Command) -> Result { ))), } } + Command::Buffer { command } => match command { + BufferCommand::Show { buffer_id } => { + let buffer = connection + .request(ClientMessage::Buffer(BufferRequest::Get { + request_id: new_request_id(), + buffer_id: BufferId(buffer_id), + })) + .await?; + let buffer = match buffer { + ServerResponse::Buffer(response) => response.buffer, + other => { + return Err(MuxError::protocol(format!( + "unexpected response to buffer show: {other:?}" + ))); + } + }; + let location = connection + .request(ClientMessage::Buffer(BufferRequest::GetLocation { + request_id: new_request_id(), + buffer_id: BufferId(buffer_id), + })) + .await?; + let location = expect_buffer_location(location, "buffer show")?; + Ok(format_buffer_details(&buffer, &location)) + } + BufferCommand::Reveal { buffer_id, client } => { + let response = connection + .request(ClientMessage::Buffer(BufferRequest::Reveal { + request_id: new_request_id(), + buffer_id: BufferId(buffer_id), + client_id: client, + })) + .await?; + let location = expect_buffer_location(response, "buffer reveal")?; + if location.session_id.is_none() { + return Err(MuxError::conflict(format!( + "buffer {} is detached; use attach-buffer or node join-buffer", + buffer_id + ))); + } + Ok(format_buffer_location_line(&location)) + } + BufferCommand::History { + buffer_id, + scope, + placement, + client, + } => { + let response = connection + .request(ClientMessage::Buffer(BufferRequest::OpenHistory { + request_id: new_request_id(), + buffer_id: BufferId(buffer_id), + scope: history_scope(scope), + placement: history_placement(placement), + client_id: client, + })) + .await?; + let location = expect_buffer_location(response, "buffer history")?; + Ok(format_buffer_location_line(&location)) + } + }, + Command::Node { command } => match command { + NodeCommand::Zoom { node_id } => { + connection + .request(ClientMessage::Node(NodeRequest::Zoom { + request_id: new_request_id(), + node_id: NodeId(node_id), + })) + .await?; + Ok(String::new()) + } + NodeCommand::Unzoom { target } => { + let session = connection.resolve_session_record(target.as_deref()).await?; + connection + .request(ClientMessage::Node(NodeRequest::Unzoom { + request_id: new_request_id(), + session_id: session.id, + })) + .await?; + Ok(String::new()) + } + NodeCommand::ToggleZoom { node_id } => { + connection + .request(ClientMessage::Node(NodeRequest::ToggleZoom { + request_id: new_request_id(), + node_id: NodeId(node_id), + })) + .await?; + Ok(String::new()) + } + NodeCommand::Swap { + first_node_id, + second_node_id, + } => { + connection + .request(ClientMessage::Node(NodeRequest::SwapSiblings { + request_id: new_request_id(), + first_node_id: NodeId(first_node_id), + second_node_id: NodeId(second_node_id), + })) + .await?; + Ok(String::new()) + } + NodeCommand::Break { + node_id, + destination, + } => { + connection + .request(ClientMessage::Node(NodeRequest::BreakNode { + request_id: new_request_id(), + node_id: NodeId(node_id), + destination: break_destination(destination), + })) + .await?; + Ok(String::new()) + } + NodeCommand::JoinBuffer { + node_id, + buffer_id, + placement, + } => { + connection + .request(ClientMessage::Node(NodeRequest::JoinBufferAtNode { + request_id: new_request_id(), + node_id: NodeId(node_id), + buffer_id: BufferId(buffer_id), + placement: join_placement(placement), + })) + .await?; + Ok(String::new()) + } + NodeCommand::MoveBefore { + node_id, + sibling_id, + } => { + connection + .request(ClientMessage::Node(NodeRequest::MoveNodeBefore { + request_id: new_request_id(), + node_id: NodeId(node_id), + sibling_node_id: NodeId(sibling_id), + })) + .await?; + Ok(String::new()) + } + NodeCommand::MoveAfter { + node_id, + sibling_id, + } => { + connection + .request(ClientMessage::Node(NodeRequest::MoveNodeAfter { + request_id: new_request_id(), + node_id: NodeId(node_id), + sibling_node_id: NodeId(sibling_id), + })) + .await?; + Ok(String::new()) + } + }, Command::NewWindow { target, title, @@ -1327,6 +1583,15 @@ fn expect_capture(response: ServerResponse, operation: &str) -> Result Result { + match response { + ServerResponse::BufferLocation(BufferLocationResponse { location, .. }) => Ok(location), + other => Err(MuxError::protocol(format!( + "unexpected response to {operation}: {other:?}" + ))), + } +} + fn format_sessions(sessions: &[SessionRecord]) -> String { sessions .iter() @@ -1381,6 +1646,53 @@ fn format_clients(clients: &[ClientRecord], sessions: &[SessionRecord]) -> Strin .join("\n") } +fn format_buffer_details( + buffer: &embers_protocol::BufferRecord, + location: &BufferLocation, +) -> String { + let mut lines = vec![ + format!("id\t{}", buffer.id), + format!("title\t{}", buffer.title), + format!("state\t{}", buffer_state_label(buffer.state)), + format!("kind\t{}", buffer_kind_label(buffer.kind)), + format!("read_only\t{}", usize::from(buffer.read_only)), + format!("location\t{}", format_buffer_location_value(location)), + ]; + if let Some(source_buffer_id) = buffer.helper_source_buffer_id { + lines.push(format!("source_buffer\t{}", source_buffer_id)); + } + if let Some(scope) = buffer.helper_scope { + lines.push(format!("history_scope\t{}", history_scope_label(scope))); + } + if !buffer.command.is_empty() { + lines.push(format!("command\t{}", buffer.command.join(" "))); + } + if let Some(cwd) = &buffer.cwd { + lines.push(format!("cwd\t{cwd}")); + } + lines.join("\n") +} + +fn format_buffer_location_line(location: &BufferLocation) -> String { + format!( + "{}\t{}", + location.buffer_id, + format_buffer_location_value(location) + ) +} + +fn format_buffer_location_value(location: &BufferLocation) -> String { + match (location.session_id, location.node_id, location.floating_id) { + (Some(session_id), Some(node_id), Some(floating_id)) => { + format!("session:{session_id}\tnode:{node_id}\tfloating:{floating_id}") + } + (Some(session_id), Some(node_id), None) => { + format!("session:{session_id}\tnode:{node_id}") + } + _ => "detached".to_owned(), + } +} + fn session_label(sessions: &[SessionRecord], session_id: SessionId) -> String { sessions .iter() @@ -1630,6 +1942,52 @@ fn buffer_state_label(state: embers_protocol::BufferRecordState) -> &'static str } } +fn buffer_kind_label(kind: embers_protocol::BufferRecordKind) -> &'static str { + match kind { + embers_protocol::BufferRecordKind::Pty => "pty", + embers_protocol::BufferRecordKind::Helper => "helper", + } +} + +fn history_scope_label(scope: BufferHistoryScope) -> &'static str { + match scope { + BufferHistoryScope::Full => "full", + BufferHistoryScope::Visible => "visible", + } +} + +fn history_scope(scope: HistoryScopeArg) -> BufferHistoryScope { + match scope { + HistoryScopeArg::Full => BufferHistoryScope::Full, + HistoryScopeArg::Visible => BufferHistoryScope::Visible, + } +} + +fn history_placement(placement: HistoryPlacementArg) -> BufferHistoryPlacement { + match placement { + HistoryPlacementArg::Tab => BufferHistoryPlacement::Tab, + HistoryPlacementArg::Floating => BufferHistoryPlacement::Floating, + } +} + +fn break_destination(destination: BreakDestinationArg) -> NodeBreakDestination { + match destination { + BreakDestinationArg::Tab => NodeBreakDestination::Tab, + BreakDestinationArg::Floating => NodeBreakDestination::Floating, + } +} + +fn join_placement(placement: JoinPlacementArg) -> NodeJoinPlacement { + match placement { + JoinPlacementArg::Left => NodeJoinPlacement::Left, + JoinPlacementArg::Right => NodeJoinPlacement::Right, + JoinPlacementArg::Up => NodeJoinPlacement::Up, + JoinPlacementArg::Down => NodeJoinPlacement::Down, + JoinPlacementArg::TabBefore => NodeJoinPlacement::TabBefore, + JoinPlacementArg::TabAfter => NodeJoinPlacement::TabAfter, + } +} + fn split_scoped_required(target: &str, label: &str) -> Result<(Option, String)> { let (session, selector) = split_scoped_target(Some(target)); let selector = diff --git a/crates/embers-cli/tests/interactive.rs b/crates/embers-cli/tests/interactive.rs index 0577d3b6..d35a6c28 100644 --- a/crates/embers-cli/tests/interactive.rs +++ b/crates/embers-cli/tests/interactive.rs @@ -3,10 +3,12 @@ use std::path::Path; use std::time::Duration; use embers_core::PtySize; -use embers_test_support::{PtyHarness, TestServer, acquire_test_lock, cargo_bin, cargo_bin_path}; +use embers_test_support::{ + PtyHarness, TestConnection, TestServer, acquire_test_lock, cargo_bin, cargo_bin_path, +}; use tempfile::tempdir; -use crate::support::{run_cli, stdout}; +use crate::support::{run_cli, session_snapshot_by_name, stdout}; const STARTUP_TIMEOUT: Duration = Duration::from_secs(15); const IO_TIMEOUT: Duration = Duration::from_secs(30); @@ -303,6 +305,71 @@ async fn client_commands_can_switch_and_detach_a_live_attached_client() { server.shutdown().await.expect("shutdown server"); } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn buffer_reveal_switches_the_attached_client_to_the_buffer_session() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); + let server = TestServer::start().await.expect("start server"); + + run_cli(&server, ["new-session", "main"]); + run_cli( + &server, + [ + "new-window", + "-t", + "main", + "--title", + "shell", + "--", + "/bin/sh", + ], + ); + run_cli(&server, ["new-session", "ops"]); + run_cli( + &server, + [ + "new-window", + "-t", + "ops", + "--title", + "logs", + "--", + "/bin/sh", + ], + ); + + let mut connection = TestConnection::connect(server.socket_path()) + .await + .expect("connect protocol client"); + let ops_snapshot = session_snapshot_by_name(&mut connection, "ops").await; + let ops_buffer_id = ops_snapshot + .session + .focused_leaf_id + .and_then(|leaf_id| { + ops_snapshot + .nodes + .iter() + .find(|node| node.id == leaf_id) + .and_then(|node| node.buffer_view.as_ref()) + .map(|view| view.buffer_id.0) + }) + .expect("ops focused buffer id exists"); + + let socket_arg = server.socket_path().to_string_lossy().into_owned(); + let mut harness = spawn_embers(&["attach", "--socket", &socket_arg, "-t", "main"]); + harness + .read_until_contains("[main]", STARTUP_TIMEOUT) + .expect("attach client renders main"); + + run_cli(&server, ["buffer", "reveal", &ops_buffer_id.to_string()]); + harness + .read_until_contains("[ops]", IO_TIMEOUT) + .expect("buffer reveal retargets the live client"); + + harness.write_all("\x11").expect("quit attached client"); + harness.wait().expect("client exits"); + server.shutdown().await.expect("shutdown server"); +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn page_up_enters_local_scrollback_and_shows_indicator() { let _guard = acquire_test_lock().await.expect("acquire test lock"); diff --git a/crates/embers-cli/tests/panes.rs b/crates/embers-cli/tests/panes.rs index 8f935e09..048cf184 100644 --- a/crates/embers-cli/tests/panes.rs +++ b/crates/embers-cli/tests/panes.rs @@ -1,7 +1,7 @@ use std::time::Duration; use embers_core::RequestId; -use embers_protocol::{BufferRequest, ClientMessage, ServerResponse}; +use embers_protocol::{BufferRequest, ClientMessage, InputRequest, ServerResponse}; use embers_test_support::{TestConnection, TestServer, acquire_test_lock}; use tokio::time::sleep; @@ -246,3 +246,129 @@ async fn detached_buffers_can_be_listed_and_attached_via_cli() { server.shutdown().await.expect("shutdown server"); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn buffer_show_and_history_open_helper_buffers() { + let _guard = acquire_test_lock().await.expect("acquire test lock"); + let server = TestServer::start().await.expect("start server"); + + run_cli(&server, ["new-session", "alpha"]); + run_cli( + &server, + [ + "new-window", + "-t", + "alpha", + "--title", + "work", + "--", + "/bin/sh", + ], + ); + + let mut connection = TestConnection::connect(server.socket_path()) + .await + .expect("connect protocol client"); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + let leaf = snapshot + .session + .focused_leaf_id + .expect("focused pane exists"); + let buffer_id = snapshot + .nodes + .iter() + .find(|node| node.id == leaf) + .and_then(|node| node.buffer_view.as_ref()) + .map(|view| view.buffer_id) + .expect("focused pane buffer exists"); + + run_cli( + &server, + [ + "send-keys", + "-t", + &leaf.to_string(), + "--enter", + "printf", + "history-helper\\n", + ], + ); + let deadline = tokio::time::Instant::now() + Duration::from_secs(2); + loop { + let captured = run_cli(&server, ["capture-pane", "-t", &leaf.to_string()]); + if stdout(&captured).contains("history-helper") { + break; + } + assert!( + tokio::time::Instant::now() < deadline, + "timed out waiting for pane output" + ); + sleep(Duration::from_millis(50)).await; + } + + let shown = run_cli(&server, ["buffer", "show", &buffer_id.to_string()]); + let shown_stdout = stdout(&shown); + assert!(shown_stdout.contains(&format!("id\t{buffer_id}"))); + assert!(shown_stdout.contains("kind\tpty")); + assert!(shown_stdout.contains(&format!("location\tsession:1\tnode:{leaf}"))); + + let opened = run_cli( + &server, + [ + "buffer", + "history", + &buffer_id.to_string(), + "--scope", + "visible", + ], + ); + let opened_stdout = stdout(&opened).trim().to_owned(); + let helper_buffer_id = opened_stdout + .split('\t') + .next() + .expect("helper buffer id column") + .parse::() + .expect("helper buffer id parses"); + + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + let helper = snapshot + .buffers + .iter() + .find(|buffer| buffer.id.0 == helper_buffer_id) + .expect("helper buffer exists in session"); + assert_eq!(helper.kind, embers_protocol::BufferRecordKind::Helper); + assert!(helper.read_only); + assert_eq!(helper.helper_source_buffer_id, Some(buffer_id)); + assert_eq!( + helper.helper_scope, + Some(embers_protocol::BufferHistoryScope::Visible) + ); + + let helper_capture = connection + .request(&ClientMessage::Buffer(BufferRequest::Capture { + request_id: RequestId(3), + buffer_id: helper.id, + })) + .await + .expect("capture helper succeeds"); + let helper_text = match helper_capture { + ServerResponse::Snapshot(response) => response.lines.join("\n"), + other => panic!("expected helper snapshot response, got {other:?}"), + }; + assert!(helper_text.contains("history-helper")); + + let send = connection + .request(&ClientMessage::Input(InputRequest::Send { + request_id: RequestId(4), + buffer_id: helper.id, + bytes: b"nope".to_vec(), + })) + .await + .expect("helper send request returns a response"); + assert!( + matches!(send, ServerResponse::Error(_)), + "helper buffers reject input, got {send:?}" + ); + + server.shutdown().await.expect("shutdown server"); +} diff --git a/crates/embers-client/Cargo.toml b/crates/embers-client/Cargo.toml index cf9032f6..1a1f1be4 100644 --- a/crates/embers-client/Cargo.toml +++ b/crates/embers-client/Cargo.toml @@ -6,6 +6,9 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[lib] +doctest = false + [dependencies] async-trait.workspace = true base64.workspace = true diff --git a/crates/embers-client/src/configured_client.rs b/crates/embers-client/src/configured_client.rs index 7a87aea5..85ae8aeb 100644 --- a/crates/embers-client/src/configured_client.rs +++ b/crates/embers-client/src/configured_client.rs @@ -888,8 +888,16 @@ where .await?; self.client.resync_all_sessions().await } - Action::FocusBuffer { buffer_id } | Action::RevealBuffer { buffer_id } => { - self.focus_buffer(session_id, buffer_id).await + Action::FocusBuffer { buffer_id } => self.focus_buffer(session_id, buffer_id).await, + Action::RevealBuffer { buffer_id } => { + self.client + .request_message(ClientMessage::Buffer(BufferRequest::Reveal { + request_id: self.client.next_request_id(), + buffer_id, + client_id: None, + })) + .await?; + self.client.resync_all_sessions().await } other => Err(MuxError::invalid_input(format!( "action '{other:?}' is not supported by the live executor yet" diff --git a/crates/embers-client/tests/configured_client.rs b/crates/embers-client/tests/configured_client.rs index c37dfa0e..02a77478 100644 --- a/crates/embers-client/tests/configured_client.rs +++ b/crates/embers-client/tests/configured_client.rs @@ -8,11 +8,12 @@ use embers_client::{ }; use embers_core::{ActivityState, BufferId, NodeId, PtySize, RequestId, SessionId, Size}; use embers_protocol::{ - BufferCreatedEvent, BufferRecord, BufferRecordState, BufferViewRecord, ClientChangedEvent, - ClientMessage, ClientRecord, ClientRequest, ClientResponse, FocusChangedEvent, InputRequest, - NodeRecord, NodeRecordKind, NodeRequest, OkResponse, RenderInvalidatedEvent, - ScrollbackSliceResponse, ServerEvent, ServerResponse, SessionRecord, SessionRequest, - SessionSnapshot, SessionSnapshotResponse, SnapshotResponse, VisibleSnapshotResponse, + BufferCreatedEvent, BufferRecord, BufferRecordKind, BufferRecordState, BufferViewRecord, + ClientChangedEvent, ClientMessage, ClientRecord, ClientRequest, ClientResponse, + FocusChangedEvent, InputRequest, NodeRecord, NodeRecordKind, NodeRequest, OkResponse, + RenderInvalidatedEvent, ScrollbackSliceResponse, ServerEvent, ServerResponse, SessionRecord, + SessionRequest, SessionSnapshot, SessionSnapshotResponse, SnapshotResponse, + VisibleSnapshotResponse, }; use tempfile::tempdir; @@ -127,6 +128,7 @@ fn second_session_state() -> embers_client::ClientState { floating_ids: Vec::new(), focused_leaf_id: Some(SECOND_ROOT_ID), focused_floating_id: None, + zoomed_node_id: None, }, ); state.nodes.insert( @@ -154,9 +156,13 @@ fn second_session_state() -> embers_client::ClientState { title: "other pane".to_owned(), command: vec!["/bin/sh".to_owned()], cwd: None, + kind: BufferRecordKind::Pty, state: BufferRecordState::Running, pid: None, attachment_node_id: Some(SECOND_ROOT_ID), + read_only: false, + helper_source_buffer_id: None, + helper_scope: None, pty_size: PtySize::new(80, 20), activity: ActivityState::Idle, last_snapshot_seq: 1, @@ -983,9 +989,13 @@ async fn detached_buffer_events_do_not_fall_back_to_the_active_session() { title: "detached".to_owned(), command: vec!["/bin/sh".to_owned()], cwd: None, + kind: BufferRecordKind::Pty, state: BufferRecordState::Running, pid: None, attachment_node_id: None, + read_only: false, + helper_source_buffer_id: None, + helper_scope: None, pty_size: PtySize::new(80, 20), activity: ActivityState::Idle, last_snapshot_seq: 0, diff --git a/crates/embers-client/tests/reducer.rs b/crates/embers-client/tests/reducer.rs index 96afccff..5ae7209a 100644 --- a/crates/embers-client/tests/reducer.rs +++ b/crates/embers-client/tests/reducer.rs @@ -6,10 +6,10 @@ use embers_core::{ ActivityState, BufferId, FloatGeometry, NodeId, PtySize, RequestId, SessionId, SplitDirection, }; use embers_protocol::{ - BufferDetachedEvent, BufferRecord, BufferRecordState, BufferViewRecord, BuffersResponse, - ClientChangedEvent, ClientMessage, ClientRecord, ClientRequest, ClientResponse, - FloatingChangedEvent, FloatingRecord, FocusChangedEvent, NodeChangedEvent, NodeRecord, - NodeRecordKind, RenderInvalidatedEvent, ServerEvent, ServerResponse, SessionRecord, + BufferDetachedEvent, BufferRecord, BufferRecordKind, BufferRecordState, BufferViewRecord, + BuffersResponse, ClientChangedEvent, ClientMessage, ClientRecord, ClientRequest, + ClientResponse, FloatingChangedEvent, FloatingRecord, FocusChangedEvent, NodeChangedEvent, + NodeRecord, NodeRecordKind, RenderInvalidatedEvent, ServerEvent, ServerResponse, SessionRecord, SessionRequest, SessionSnapshot, SessionSnapshotResponse, SplitRecord, TabRecord, TabsRecord, VisibleSnapshotResponse, }; @@ -20,10 +20,14 @@ fn buffer(id: u64, attachment_node_id: Option, title: &str) -> BufferRecord title: title.to_owned(), command: vec!["/bin/sh".to_owned()], cwd: Some("/tmp".to_owned()), + kind: BufferRecordKind::Pty, pid: None, env: Default::default(), state: BufferRecordState::Running, attachment_node_id: attachment_node_id.map(NodeId), + read_only: false, + helper_source_buffer_id: None, + helper_scope: None, pty_size: PtySize::new(80, 24), activity: ActivityState::Idle, last_snapshot_seq: 0, @@ -64,6 +68,7 @@ fn session_snapshot(root_active: u32, nested_active: u32) -> SessionSnapshot { floating_ids: vec![embers_core::FloatingId(90)], focused_leaf_id: Some(NodeId(11)), focused_floating_id: None, + zoomed_node_id: None, }, nodes: vec![ NodeRecord { @@ -543,6 +548,7 @@ async fn reconnect_resync_rebuilds_sessions_and_detached_buffers() { floating_ids: vec![], focused_leaf_id: Some(NodeId(11)), focused_floating_id: None, + zoomed_node_id: None, }], }), ); @@ -579,6 +585,7 @@ async fn reconnect_resync_rebuilds_sessions_and_detached_buffers() { floating_ids: vec![], focused_leaf_id: None, focused_floating_id: None, + zoomed_node_id: None, }, ); client diff --git a/crates/embers-client/tests/support/mod.rs b/crates/embers-client/tests/support/mod.rs index 444d6850..0bb083fb 100644 --- a/crates/embers-client/tests/support/mod.rs +++ b/crates/embers-client/tests/support/mod.rs @@ -5,8 +5,9 @@ use embers_core::{ ActivityState, BufferId, FloatGeometry, FloatingId, NodeId, PtySize, SessionId, SplitDirection, }; use embers_protocol::{ - BufferRecord, BufferRecordState, BufferViewRecord, FloatingRecord, NodeRecord, NodeRecordKind, - SessionRecord, SessionSnapshot, SplitRecord, TabRecord, TabsRecord, VisibleSnapshotResponse, + BufferRecord, BufferRecordKind, BufferRecordState, BufferViewRecord, FloatingRecord, + NodeRecord, NodeRecordKind, SessionRecord, SessionSnapshot, SplitRecord, TabRecord, TabsRecord, + VisibleSnapshotResponse, }; pub const SESSION_ID: SessionId = SessionId(1); @@ -86,6 +87,7 @@ fn demo_snapshot(focused_floating: Option<(FloatingId, NodeId)>) -> SessionSnaps floating_ids: vec![FLOATING_ID], focused_leaf_id, focused_floating_id, + zoomed_node_id: None, }, nodes: vec![ NodeRecord { @@ -212,6 +214,7 @@ fn root_buffer_snapshot() -> SessionSnapshot { floating_ids: Vec::new(), focused_leaf_id: Some(ROOT_BUFFER_LEAF_ID), focused_floating_id: None, + zoomed_node_id: None, }, nodes: vec![buffer_view_node(ROOT_BUFFER_LEAF_ID, None, BufferId(7))], buffers: vec![buffer( @@ -233,6 +236,7 @@ fn root_split_snapshot() -> SessionSnapshot { floating_ids: Vec::new(), focused_leaf_id: Some(ROOT_SPLIT_RIGHT_LEAF_ID), focused_floating_id: None, + zoomed_node_id: None, }, nodes: vec![ NodeRecord { @@ -306,10 +310,14 @@ fn buffer( title: title.to_owned(), command: vec!["/bin/sh".to_owned()], cwd: Some("/tmp".to_owned()), + kind: BufferRecordKind::Pty, pid: None, env: Default::default(), state: BufferRecordState::Running, attachment_node_id, + read_only: false, + helper_source_buffer_id: None, + helper_scope: None, pty_size: PtySize::new(80, 24), activity, last_snapshot_seq: 0, diff --git a/crates/embers-core/Cargo.toml b/crates/embers-core/Cargo.toml index 26b475d2..6c404b6f 100644 --- a/crates/embers-core/Cargo.toml +++ b/crates/embers-core/Cargo.toml @@ -5,6 +5,9 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[lib] +doctest = false + [dependencies] serde.workspace = true thiserror.workspace = true diff --git a/crates/embers-protocol/Cargo.toml b/crates/embers-protocol/Cargo.toml index 864d5626..6bc377a8 100644 --- a/crates/embers-protocol/Cargo.toml +++ b/crates/embers-protocol/Cargo.toml @@ -7,6 +7,9 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[lib] +doctest = false + [dependencies] flatbuffers.workspace = true embers-core = { path = "../embers-core" } diff --git a/crates/embers-protocol/schema/embers.fbs b/crates/embers-protocol/schema/embers.fbs index 19909ec5..bb2bdae0 100644 --- a/crates/embers-protocol/schema/embers.fbs +++ b/crates/embers-protocol/schema/embers.fbs @@ -27,6 +27,7 @@ enum MessageKind : ubyte { ScrollbackSliceResponse = 32, ClientsResponse = 33, ClientResponse = 34, + BufferLocationResponse = 35, SessionCreatedEvent = 40, SessionClosedEvent = 41, @@ -73,6 +74,9 @@ enum BufferOp : ubyte { Capture = 5, CaptureVisible = 6, ScrollbackSlice = 7, + GetLocation = 8, + Reveal = 9, + OpenHistory = 10, } enum NodeOp : ubyte { @@ -89,6 +93,14 @@ enum NodeOp : ubyte { CreateTabs = 10, ReplaceNode = 11, WrapInSplit = 12, + Zoom = 13, + Unzoom = 14, + ToggleZoom = 15, + SwapSiblings = 16, + BreakNode = 17, + JoinBufferAtNode = 18, + MoveNodeBefore = 19, + MoveNodeAfter = 20, } enum FloatingOp : ubyte { @@ -128,6 +140,35 @@ enum BufferStateWire : ubyte { Interrupted = 4, } +enum BufferKindWire : ubyte { + Pty = 0, + Helper = 1, +} + +enum BufferHistoryScopeWire : ubyte { + Full = 0, + Visible = 1, +} + +enum BufferHistoryPlacementWire : ubyte { + Tab = 0, + Floating = 1, +} + +enum NodeBreakDestinationWire : ubyte { + Tab = 0, + Floating = 1, +} + +enum NodeJoinPlacementWire : ubyte { + Left = 0, + Right = 1, + Up = 2, + Down = 3, + TabBefore = 4, + TabAfter = 5, +} + enum NodeRecordKindWire : ubyte { BufferView = 0, Split = 1, @@ -159,11 +200,14 @@ table BufferRequest { op:BufferOp = Create; buffer_id:ulong = 0; session_id:ulong = 0; + client_id:ulong = 0; attached_only:bool = false; detached_only:bool = false; force:bool = false; start_line:ulong = 0; line_count:uint = 0; + history_scope:BufferHistoryScopeWire = Full; + history_placement:BufferHistoryPlacementWire = Tab; title:string; command:[string]; cwd:string; @@ -185,10 +229,15 @@ table NodeRequest { index:uint = 0; active:uint = 0; direction:SplitDirectionWire = Horizontal; + break_destination:NodeBreakDestinationWire = Tab; + join_placement:NodeJoinPlacementWire = Left; sizes:[ushort]; child_node_ids:[ulong]; titles:[string]; insert_before:bool = false; + first_node_id:ulong = 0; + second_node_id:ulong = 0; + sibling_node_id:ulong = 0; } table FloatingRequest { @@ -246,6 +295,7 @@ table SessionRecord { floating_ids:[ulong]; focused_leaf_id:ulong = 0; focused_floating_id:ulong = 0; + zoomed_node_id:ulong = 0; } table BufferRecord { @@ -253,10 +303,15 @@ table BufferRecord { title:string; command:[string]; cwd:string; + kind:BufferKindWire = Pty; state:BufferStateWire = Created; pid:uint = 0; has_pid:bool = false; attachment_node_id:ulong = 0; + read_only:bool = false; + helper_source_buffer_id:ulong = 0; + helper_scope:BufferHistoryScopeWire = Full; + has_helper_scope:bool = false; pty_cols:ushort = 0; pty_rows:ushort = 0; activity:ActivityStateWire = Idle; @@ -366,6 +421,17 @@ table ClientResponse { client:ClientRecord; } +table BufferLocation { + buffer_id:ulong; + session_id:ulong = 0; + node_id:ulong = 0; + floating_id:ulong = 0; +} + +table BufferLocationResponse { + location:BufferLocation; +} + table CursorState { row:ushort = 0; col:ushort = 0; @@ -462,6 +528,7 @@ table Envelope { input_request:InputRequest; subscribe_request:SubscribeRequest; unsubscribe_request:UnsubscribeRequest; + client_request:ClientRequest; ping_response:PingResponse; ok_response:OkResponse; @@ -476,6 +543,9 @@ table Envelope { snapshot_response:SnapshotResponse; visible_snapshot_response:VisibleSnapshotResponse; scrollback_slice_response:ScrollbackSliceResponse; + clients_response:ClientsResponse; + client_response:ClientResponse; + buffer_location_response:BufferLocationResponse; session_created_event:SessionCreatedEvent; session_closed_event:SessionClosedEvent; @@ -487,9 +557,6 @@ table Envelope { render_invalidated_event:RenderInvalidatedEvent; session_renamed_event:SessionRenamedEvent; client_changed_event:ClientChangedEvent; - client_request:ClientRequest; - clients_response:ClientsResponse; - client_response:ClientResponse; } root_type Envelope; diff --git a/crates/embers-protocol/src/codec.rs b/crates/embers-protocol/src/codec.rs index a4fcf974..2d504f23 100644 --- a/crates/embers-protocol/src/codec.rs +++ b/crates/embers-protocol/src/codec.rs @@ -96,6 +96,92 @@ fn encode_cursor_state<'a>( ) } +fn encode_buffer_history_scope(scope: BufferHistoryScope) -> fb::BufferHistoryScopeWire { + match scope { + BufferHistoryScope::Full => fb::BufferHistoryScopeWire::Full, + BufferHistoryScope::Visible => fb::BufferHistoryScopeWire::Visible, + } +} + +fn decode_buffer_history_scope( + scope: fb::BufferHistoryScopeWire, +) -> Result { + match scope { + fb::BufferHistoryScopeWire::Full => Ok(BufferHistoryScope::Full), + fb::BufferHistoryScopeWire::Visible => Ok(BufferHistoryScope::Visible), + _ => Err(ProtocolError::InvalidMessage( + "unknown buffer history scope", + )), + } +} + +fn encode_buffer_history_placement( + placement: BufferHistoryPlacement, +) -> fb::BufferHistoryPlacementWire { + match placement { + BufferHistoryPlacement::Tab => fb::BufferHistoryPlacementWire::Tab, + BufferHistoryPlacement::Floating => fb::BufferHistoryPlacementWire::Floating, + } +} + +fn decode_buffer_history_placement( + placement: fb::BufferHistoryPlacementWire, +) -> Result { + match placement { + fb::BufferHistoryPlacementWire::Tab => Ok(BufferHistoryPlacement::Tab), + fb::BufferHistoryPlacementWire::Floating => Ok(BufferHistoryPlacement::Floating), + _ => Err(ProtocolError::InvalidMessage( + "unknown buffer history placement", + )), + } +} + +fn encode_node_break_destination( + destination: NodeBreakDestination, +) -> fb::NodeBreakDestinationWire { + match destination { + NodeBreakDestination::Tab => fb::NodeBreakDestinationWire::Tab, + NodeBreakDestination::Floating => fb::NodeBreakDestinationWire::Floating, + } +} + +fn decode_node_break_destination( + destination: fb::NodeBreakDestinationWire, +) -> Result { + match destination { + fb::NodeBreakDestinationWire::Tab => Ok(NodeBreakDestination::Tab), + fb::NodeBreakDestinationWire::Floating => Ok(NodeBreakDestination::Floating), + _ => Err(ProtocolError::InvalidMessage( + "unknown node break destination", + )), + } +} + +fn encode_node_join_placement(placement: NodeJoinPlacement) -> fb::NodeJoinPlacementWire { + match placement { + NodeJoinPlacement::Left => fb::NodeJoinPlacementWire::Left, + NodeJoinPlacement::Right => fb::NodeJoinPlacementWire::Right, + NodeJoinPlacement::Up => fb::NodeJoinPlacementWire::Up, + NodeJoinPlacement::Down => fb::NodeJoinPlacementWire::Down, + NodeJoinPlacement::TabBefore => fb::NodeJoinPlacementWire::TabBefore, + NodeJoinPlacement::TabAfter => fb::NodeJoinPlacementWire::TabAfter, + } +} + +fn decode_node_join_placement( + placement: fb::NodeJoinPlacementWire, +) -> Result { + match placement { + fb::NodeJoinPlacementWire::Left => Ok(NodeJoinPlacement::Left), + fb::NodeJoinPlacementWire::Right => Ok(NodeJoinPlacement::Right), + fb::NodeJoinPlacementWire::Up => Ok(NodeJoinPlacement::Up), + fb::NodeJoinPlacementWire::Down => Ok(NodeJoinPlacement::Down), + fb::NodeJoinPlacementWire::TabBefore => Ok(NodeJoinPlacement::TabBefore), + fb::NodeJoinPlacementWire::TabAfter => Ok(NodeJoinPlacement::TabAfter), + _ => Err(ProtocolError::InvalidMessage("unknown node join placement")), + } +} + fn decode_cursor_state(cursor: fb::CursorState<'_>) -> Result { let shape = match cursor.shape() { fb::CursorShapeWire::Block => CursorShape::Block, @@ -344,11 +430,14 @@ fn encode_buffer_request<'a>( op, buffer_id, session_id, + client_id, attached_only, detached_only, force, start_line, line_count, + history_scope, + history_placement, title_str, command_vec, cwd_str, @@ -364,11 +453,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::Create, 0, 0, + 0, false, false, false, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, title.as_deref(), Some(command), cwd.as_deref(), @@ -383,11 +475,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::List, 0, session_id.map(|s| s.into()).unwrap_or(0), + 0, *attached_only, *detached_only, false, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, None, None, None, @@ -397,11 +492,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::Get, (*buffer_id).into(), 0, + 0, false, false, false, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, None, None, None, @@ -411,11 +509,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::Detach, (*buffer_id).into(), 0, + 0, false, false, false, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, None, None, None, @@ -427,11 +528,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::Kill, (*buffer_id).into(), 0, + 0, false, false, *force, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, None, None, None, @@ -441,11 +545,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::Capture, (*buffer_id).into(), 0, + 0, false, false, false, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, None, None, None, @@ -455,11 +562,14 @@ fn encode_buffer_request<'a>( fb::BufferOp::CaptureVisible, (*buffer_id).into(), 0, + 0, false, false, false, 0, 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, None, None, None, @@ -474,11 +584,75 @@ fn encode_buffer_request<'a>( fb::BufferOp::ScrollbackSlice, (*buffer_id).into(), 0, + 0, false, false, false, *start_line, *line_count, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, + None, + None, + None, + None, + ), + BufferRequest::GetLocation { buffer_id, .. } => ( + fb::BufferOp::GetLocation, + (*buffer_id).into(), + 0, + 0, + false, + false, + false, + 0, + 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, + None, + None, + None, + None, + ), + BufferRequest::Reveal { + buffer_id, + client_id, + .. + } => ( + fb::BufferOp::Reveal, + (*buffer_id).into(), + 0, + client_id.unwrap_or(0), + false, + false, + false, + 0, + 0, + fb::BufferHistoryScopeWire::Full, + fb::BufferHistoryPlacementWire::Tab, + None, + None, + None, + None, + ), + BufferRequest::OpenHistory { + buffer_id, + scope, + placement, + client_id, + .. + } => ( + fb::BufferOp::OpenHistory, + (*buffer_id).into(), + 0, + client_id.unwrap_or(0), + false, + false, + false, + 0, + 0, + encode_buffer_history_scope(*scope), + encode_buffer_history_placement(*placement), None, None, None, @@ -507,11 +681,14 @@ fn encode_buffer_request<'a>( op, buffer_id, session_id, + client_id, attached_only, detached_only, force, start_line, line_count, + history_scope, + history_placement, title, command, cwd, @@ -549,10 +726,15 @@ fn encode_node_request<'a>( u32, u32, fb::SplitDirectionWire, + fb::NodeBreakDestinationWire, + fb::NodeJoinPlacementWire, Option<&'a Vec>, Option>, Option>, bool, + u64, + u64, + u64, ); let ( @@ -569,10 +751,15 @@ fn encode_node_request<'a>( index, active, direction, + break_destination, + join_placement, sizes_vec, child_node_ids_vec, titles_vec, insert_before, + first_node_id, + second_node_id, + sibling_node_id, ): EncodedNodeRequest<'_> = match req { NodeRequest::GetTree { session_id, .. } => ( fb::NodeOp::GetTree, @@ -588,10 +775,15 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::Split { leaf_node_id, @@ -617,10 +809,15 @@ fn encode_node_request<'a>( 0, 0, dir, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ) } NodeRequest::CreateSplit { @@ -648,6 +845,8 @@ fn encode_node_request<'a>( 0, 0, dir, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, Some(sizes), Some( child_node_ids @@ -657,6 +856,9 @@ fn encode_node_request<'a>( ), None, false, + 0, + 0, + 0, ) } NodeRequest::CreateTabs { @@ -679,6 +881,8 @@ fn encode_node_request<'a>( 0, *active, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, Some( child_node_ids @@ -688,6 +892,9 @@ fn encode_node_request<'a>( ), Some(titles.clone()), false, + 0, + 0, + 0, ), NodeRequest::ReplaceNode { node_id, @@ -707,10 +914,15 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::WrapInSplit { node_id, @@ -737,10 +949,15 @@ fn encode_node_request<'a>( 0, 0, dir, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, *insert_before, + 0, + 0, + 0, ) } NodeRequest::WrapInTabs { node_id, title, .. } => ( @@ -757,10 +974,15 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::AddTab { tabs_node_id, @@ -783,10 +1005,15 @@ fn encode_node_request<'a>( *index, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::SelectTab { tabs_node_id, @@ -806,10 +1033,15 @@ fn encode_node_request<'a>( *index, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::Focus { session_id, @@ -829,10 +1061,15 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::Close { node_id, .. } => ( fb::NodeOp::Close, @@ -848,10 +1085,15 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::MoveBufferToNode { buffer_id, @@ -871,10 +1113,15 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, None, None, None, false, + 0, + 0, + 0, ), NodeRequest::Resize { node_id, sizes, .. } => ( fb::NodeOp::Resize, @@ -890,10 +1137,228 @@ fn encode_node_request<'a>( 0, 0, fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, Some(sizes), None, None, false, + 0, + 0, + 0, + ), + NodeRequest::Zoom { node_id, .. } => ( + fb::NodeOp::Zoom, + 0, + (*node_id).into(), + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + 0, + 0, + 0, + ), + NodeRequest::Unzoom { session_id, .. } => ( + fb::NodeOp::Unzoom, + (*session_id).into(), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + 0, + 0, + 0, + ), + NodeRequest::ToggleZoom { node_id, .. } => ( + fb::NodeOp::ToggleZoom, + 0, + (*node_id).into(), + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + 0, + 0, + 0, + ), + NodeRequest::SwapSiblings { + first_node_id, + second_node_id, + .. + } => ( + fb::NodeOp::SwapSiblings, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + (*first_node_id).into(), + (*second_node_id).into(), + 0, + ), + NodeRequest::BreakNode { + node_id, + destination, + .. + } => ( + fb::NodeOp::BreakNode, + 0, + (*node_id).into(), + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + encode_node_break_destination(*destination), + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + 0, + 0, + 0, + ), + NodeRequest::JoinBufferAtNode { + node_id, + buffer_id, + placement, + .. + } => ( + fb::NodeOp::JoinBufferAtNode, + 0, + (*node_id).into(), + 0, + 0, + 0, + 0, + (*buffer_id).into(), + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + encode_node_join_placement(*placement), + None, + None, + None, + false, + 0, + 0, + 0, + ), + NodeRequest::MoveNodeBefore { + node_id, + sibling_node_id, + .. + } => ( + fb::NodeOp::MoveNodeBefore, + 0, + (*node_id).into(), + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + 0, + 0, + (*sibling_node_id).into(), + ), + NodeRequest::MoveNodeAfter { + node_id, + sibling_node_id, + .. + } => ( + fb::NodeOp::MoveNodeAfter, + 0, + (*node_id).into(), + 0, + 0, + 0, + 0, + 0, + 0, + None, + 0, + 0, + fb::SplitDirectionWire::Horizontal, + fb::NodeBreakDestinationWire::Tab, + fb::NodeJoinPlacementWire::Left, + None, + None, + None, + false, + 0, + 0, + (*sibling_node_id).into(), ), }; @@ -917,10 +1382,15 @@ fn encode_node_request<'a>( index, active, direction, + break_destination, + join_placement, sizes, child_node_ids, titles, insert_before, + first_node_id, + second_node_id, + sibling_node_id, }, ); @@ -1373,6 +1843,32 @@ fn encode_server_response<'a>( }, ) } + ServerResponse::BufferLocation(r) => { + let location = fb::BufferLocation::create( + builder, + &fb::BufferLocationArgs { + buffer_id: r.location.buffer_id.into(), + session_id: r.location.session_id.map(|id| id.into()).unwrap_or(0), + node_id: r.location.node_id.map(|id| id.into()).unwrap_or(0), + floating_id: r.location.floating_id.map(|id| id.into()).unwrap_or(0), + }, + ); + let response = fb::BufferLocationResponse::create( + builder, + &fb::BufferLocationResponseArgs { + location: Some(location), + }, + ); + fb::Envelope::create( + builder, + &fb::EnvelopeArgs { + request_id: r.request_id.into(), + kind: fb::MessageKind::BufferLocationResponse, + buffer_location_response: Some(response), + ..Default::default() + }, + ) + } ServerResponse::Snapshot(r) => { let title = r.title.as_ref().map(|t| builder.create_string(t)); let cwd = r.cwd.as_ref().map(|c| builder.create_string(c)); @@ -1669,6 +2165,7 @@ fn encode_session_record<'a>( floating_ids: Some(floating_ids_vec), focused_leaf_id: record.focused_leaf_id.map(|n| n.into()).unwrap_or(0), focused_floating_id: record.focused_floating_id.map(|f| f.into()).unwrap_or(0), + zoomed_node_id: record.zoomed_node_id.map(|n| n.into()).unwrap_or(0), }, ) } @@ -1702,6 +2199,14 @@ fn encode_buffer_record<'a>( ActivityState::Activity => fb::ActivityStateWire::Activity, ActivityState::Bell => fb::ActivityStateWire::Bell, }; + let kind = match record.kind { + BufferRecordKind::Pty => fb::BufferKindWire::Pty, + BufferRecordKind::Helper => fb::BufferKindWire::Helper, + }; + let helper_scope = record + .helper_scope + .map(encode_buffer_history_scope) + .unwrap_or(fb::BufferHistoryScopeWire::Full); fb::BufferRecord::create( builder, @@ -1710,10 +2215,18 @@ fn encode_buffer_record<'a>( title: Some(title), command: Some(command), cwd, + kind, state, pid: record.pid.unwrap_or(0), has_pid: record.pid.is_some(), attachment_node_id: record.attachment_node_id.map(|n| n.into()).unwrap_or(0), + read_only: record.read_only, + helper_source_buffer_id: record + .helper_source_buffer_id + .map(|id| id.into()) + .unwrap_or(0), + helper_scope, + has_helper_scope: record.helper_scope.is_some(), pty_cols: record.pty_size.cols, pty_rows: record.pty_size.rows, activity, @@ -2010,6 +2523,22 @@ pub fn decode_client_message(bytes: &[u8]) -> Result BufferRequest::GetLocation { + request_id, + buffer_id: BufferId(req.buffer_id()), + }, + fb::BufferOp::Reveal => BufferRequest::Reveal { + request_id, + buffer_id: BufferId(req.buffer_id()), + client_id: (req.client_id() != 0).then_some(req.client_id()), + }, + fb::BufferOp::OpenHistory => BufferRequest::OpenHistory { + request_id, + buffer_id: BufferId(req.buffer_id()), + scope: decode_buffer_history_scope(req.history_scope())?, + placement: decode_buffer_history_placement(req.history_placement())?, + client_id: (req.client_id() != 0).then_some(req.client_id()), + }, _ => return Err(ProtocolError::InvalidMessage("unknown buffer op")), }; Ok(ClientMessage::Buffer(buffer_request)) @@ -2141,6 +2670,44 @@ pub fn decode_client_message(bytes: &[u8]) -> Result NodeRequest::Zoom { + request_id, + node_id: NodeId(req.node_id()), + }, + fb::NodeOp::Unzoom => NodeRequest::Unzoom { + request_id, + session_id: SessionId(req.session_id()), + }, + fb::NodeOp::ToggleZoom => NodeRequest::ToggleZoom { + request_id, + node_id: NodeId(req.node_id()), + }, + fb::NodeOp::SwapSiblings => NodeRequest::SwapSiblings { + request_id, + first_node_id: NodeId(req.first_node_id()), + second_node_id: NodeId(req.second_node_id()), + }, + fb::NodeOp::BreakNode => NodeRequest::BreakNode { + request_id, + node_id: NodeId(req.node_id()), + destination: decode_node_break_destination(req.break_destination())?, + }, + fb::NodeOp::JoinBufferAtNode => NodeRequest::JoinBufferAtNode { + request_id, + node_id: NodeId(req.node_id()), + buffer_id: BufferId(req.buffer_id()), + placement: decode_node_join_placement(req.join_placement())?, + }, + fb::NodeOp::MoveNodeBefore => NodeRequest::MoveNodeBefore { + request_id, + node_id: NodeId(req.node_id()), + sibling_node_id: NodeId(req.sibling_node_id()), + }, + fb::NodeOp::MoveNodeAfter => NodeRequest::MoveNodeAfter { + request_id, + node_id: NodeId(req.node_id()), + sibling_node_id: NodeId(req.sibling_node_id()), + }, _ => return Err(ProtocolError::InvalidMessage("unknown node op")), }; Ok(ClientMessage::Node(node_request)) @@ -2394,6 +2961,26 @@ pub fn decode_server_envelope(bytes: &[u8]) -> Result { + let resp = required( + envelope.buffer_location_response(), + "buffer_location_response", + )?; + let location = required(resp.location(), "buffer_location_response.location")?; + Ok(ServerEnvelope::Response(ServerResponse::BufferLocation( + BufferLocationResponse { + request_id: RequestId(envelope.request_id()), + location: BufferLocation { + buffer_id: BufferId(location.buffer_id()), + session_id: (location.session_id() != 0) + .then(|| SessionId(location.session_id())), + node_id: (location.node_id() != 0).then(|| NodeId(location.node_id())), + floating_id: (location.floating_id() != 0) + .then(|| FloatingId(location.floating_id())), + }, + }, + ))) + } fb::MessageKind::SnapshotResponse => { let resp = required(envelope.snapshot_response(), "snapshot_response")?; let lines = required(resp.lines(), "snapshot_response.lines")?; @@ -2601,6 +3188,11 @@ fn decode_session_record(record: fb::SessionRecord) -> Result Result return Err(ProtocolError::InvalidMessage("unknown activity state")), }; let env = decode_string_map(record.env_keys(), record.env_values(), "buffer_record.env")?; + let kind = match record.kind() { + fb::BufferKindWire::Pty => BufferRecordKind::Pty, + fb::BufferKindWire::Helper => BufferRecordKind::Helper, + _ => return Err(ProtocolError::InvalidMessage("unknown buffer kind")), + }; + let helper_scope = if record.has_helper_scope() { + Some(decode_buffer_history_scope(record.helper_scope())?) + } else { + None + }; Ok(BufferRecord { id: BufferId(record.id()), title: title.to_owned(), command, cwd: record.cwd().map(|c| c.to_owned()), + kind, state, pid: record.has_pid().then(|| record.pid()), attachment_node_id: if record.attachment_node_id() == 0 { @@ -2637,6 +3240,13 @@ fn decode_buffer_record(record: fb::BufferRecord) -> Result, + }, + OpenHistory { + request_id: RequestId, + buffer_id: BufferId, + scope: BufferHistoryScope, + placement: BufferHistoryPlacement, + client_id: Option, + }, } impl BufferRequest { @@ -136,11 +152,34 @@ impl BufferRequest { | Self::Kill { request_id, .. } | Self::Capture { request_id, .. } | Self::CaptureVisible { request_id, .. } - | Self::ScrollbackSlice { request_id, .. } => *request_id, + | Self::ScrollbackSlice { request_id, .. } + | Self::GetLocation { request_id, .. } + | Self::Reveal { request_id, .. } + | Self::OpenHistory { request_id, .. } => *request_id, } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BufferHistoryScope { + Full, + Visible, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BufferHistoryPlacement { + Tab, + Floating, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BufferLocation { + pub buffer_id: BufferId, + pub session_id: Option, + pub node_id: Option, + pub floating_id: Option, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum NodeRequest { GetTree { @@ -216,6 +255,44 @@ pub enum NodeRequest { node_id: NodeId, sizes: Vec, }, + Zoom { + request_id: RequestId, + node_id: NodeId, + }, + Unzoom { + request_id: RequestId, + session_id: SessionId, + }, + ToggleZoom { + request_id: RequestId, + node_id: NodeId, + }, + SwapSiblings { + request_id: RequestId, + first_node_id: NodeId, + second_node_id: NodeId, + }, + BreakNode { + request_id: RequestId, + node_id: NodeId, + destination: NodeBreakDestination, + }, + JoinBufferAtNode { + request_id: RequestId, + node_id: NodeId, + buffer_id: BufferId, + placement: NodeJoinPlacement, + }, + MoveNodeBefore { + request_id: RequestId, + node_id: NodeId, + sibling_node_id: NodeId, + }, + MoveNodeAfter { + request_id: RequestId, + node_id: NodeId, + sibling_node_id: NodeId, + }, } impl NodeRequest { @@ -233,11 +310,35 @@ impl NodeRequest { | Self::Focus { request_id, .. } | Self::Close { request_id, .. } | Self::MoveBufferToNode { request_id, .. } - | Self::Resize { request_id, .. } => *request_id, + | Self::Resize { request_id, .. } + | Self::Zoom { request_id, .. } + | Self::Unzoom { request_id, .. } + | Self::ToggleZoom { request_id, .. } + | Self::SwapSiblings { request_id, .. } + | Self::BreakNode { request_id, .. } + | Self::JoinBufferAtNode { request_id, .. } + | Self::MoveNodeBefore { request_id, .. } + | Self::MoveNodeAfter { request_id, .. } => *request_id, } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum NodeBreakDestination { + Tab, + Floating, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum NodeJoinPlacement { + Left, + Right, + Up, + Down, + TabBefore, + TabAfter, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum FloatingRequest { Create { @@ -387,6 +488,13 @@ pub struct SessionRecord { pub floating_ids: Vec, pub focused_leaf_id: Option, pub focused_floating_id: Option, + pub zoomed_node_id: Option, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BufferRecordKind { + Pty, + Helper, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -395,9 +503,13 @@ pub struct BufferRecord { pub title: String, pub command: Vec, pub cwd: Option, + pub kind: BufferRecordKind, pub state: BufferRecordState, pub pid: Option, pub attachment_node_id: Option, + pub read_only: bool, + pub helper_source_buffer_id: Option, + pub helper_scope: Option, pub pty_size: PtySize, pub activity: ActivityState, pub last_snapshot_seq: u64, @@ -544,6 +656,12 @@ pub struct ClientResponse { pub client: ClientRecord, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BufferLocationResponse { + pub request_id: RequestId, + pub location: BufferLocation, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct SnapshotResponse { pub request_id: RequestId, @@ -596,6 +714,7 @@ pub enum ServerResponse { SubscriptionAck(SubscriptionAckResponse), Clients(ClientsResponse), Client(ClientResponse), + BufferLocation(BufferLocationResponse), Snapshot(SnapshotResponse), VisibleSnapshot(VisibleSnapshotResponse), ScrollbackSlice(ScrollbackSliceResponse), @@ -616,6 +735,7 @@ impl ServerResponse { Self::SubscriptionAck(response) => Some(response.request_id), Self::Clients(response) => Some(response.request_id), Self::Client(response) => Some(response.request_id), + Self::BufferLocation(response) => Some(response.request_id), Self::Snapshot(response) => Some(response.request_id), Self::VisibleSnapshot(response) => Some(response.request_id), Self::ScrollbackSlice(response) => Some(response.request_id), diff --git a/crates/embers-protocol/tests/family_round_trip.rs b/crates/embers-protocol/tests/family_round_trip.rs index 84c03c68..2ae043ce 100644 --- a/crates/embers-protocol/tests/family_round_trip.rs +++ b/crates/embers-protocol/tests/family_round_trip.rs @@ -90,6 +90,22 @@ fn client_message_families_round_trip() { start_line: 4, line_count: 8, }), + ClientMessage::Buffer(BufferRequest::GetLocation { + request_id: RequestId(153), + buffer_id: BufferId(20), + }), + ClientMessage::Buffer(BufferRequest::Reveal { + request_id: RequestId(154), + buffer_id: BufferId(20), + client_id: Some(7), + }), + ClientMessage::Buffer(BufferRequest::OpenHistory { + request_id: RequestId(155), + buffer_id: BufferId(20), + scope: BufferHistoryScope::Visible, + placement: BufferHistoryPlacement::Floating, + client_id: None, + }), ClientMessage::Node(NodeRequest::GetTree { request_id: RequestId(16), session_id: SessionId(10), @@ -163,6 +179,44 @@ fn client_message_families_round_trip() { node_id: NodeId(35), sizes: vec![3, 2, 1], }), + ClientMessage::Node(NodeRequest::Zoom { + request_id: RequestId(241), + node_id: NodeId(35), + }), + ClientMessage::Node(NodeRequest::Unzoom { + request_id: RequestId(242), + session_id: SessionId(10), + }), + ClientMessage::Node(NodeRequest::ToggleZoom { + request_id: RequestId(243), + node_id: NodeId(35), + }), + ClientMessage::Node(NodeRequest::SwapSiblings { + request_id: RequestId(244), + first_node_id: NodeId(50), + second_node_id: NodeId(51), + }), + ClientMessage::Node(NodeRequest::BreakNode { + request_id: RequestId(245), + node_id: NodeId(35), + destination: NodeBreakDestination::Floating, + }), + ClientMessage::Node(NodeRequest::JoinBufferAtNode { + request_id: RequestId(246), + node_id: NodeId(35), + buffer_id: BufferId(22), + placement: NodeJoinPlacement::TabAfter, + }), + ClientMessage::Node(NodeRequest::MoveNodeBefore { + request_id: RequestId(247), + node_id: NodeId(35), + sibling_node_id: NodeId(36), + }), + ClientMessage::Node(NodeRequest::MoveNodeAfter { + request_id: RequestId(248), + node_id: NodeId(35), + sibling_node_id: NodeId(36), + }), ClientMessage::Floating(FloatingRequest::Create { request_id: RequestId(25), session_id: SessionId(10), @@ -253,6 +307,15 @@ fn server_envelope_families_round_trip() { request_id: RequestId(36), buffer: buffers[0].clone(), })), + ServerEnvelope::Response(ServerResponse::BufferLocation(BufferLocationResponse { + request_id: RequestId(361), + location: BufferLocation { + buffer_id: BufferId(11), + session_id: Some(SessionId(10)), + node_id: Some(NodeId(21)), + floating_id: None, + }, + })), ServerEnvelope::Response(ServerResponse::FloatingList(FloatingListResponse { request_id: RequestId(37), floating: floating.clone(), @@ -345,6 +408,7 @@ fn sample_snapshot() -> SessionSnapshot { floating_ids: vec![FloatingId(30)], focused_leaf_id: Some(NodeId(21)), focused_floating_id: Some(FloatingId(30)), + zoomed_node_id: Some(NodeId(24)), }, nodes: vec![ NodeRecord { @@ -475,9 +539,13 @@ fn sample_buffer_record( title: format!("buffer-{id}"), command: vec!["bash".to_owned(), "-lc".to_owned(), "echo mux".to_owned()], cwd: Some("/tmp".to_owned()), + kind: BufferRecordKind::Pty, state, pid: Some(4242), attachment_node_id, + read_only: false, + helper_source_buffer_id: None, + helper_scope: None, pty_size: PtySize::new(120, 40), activity, last_snapshot_seq: 9, diff --git a/crates/embers-server/Cargo.toml b/crates/embers-server/Cargo.toml index 6960cf38..7ac0a85d 100644 --- a/crates/embers-server/Cargo.toml +++ b/crates/embers-server/Cargo.toml @@ -6,6 +6,9 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[lib] +doctest = false + [dependencies] alacritty_terminal = "0.25.1" base64.workspace = true diff --git a/crates/embers-server/src/model.rs b/crates/embers-server/src/model.rs index dffa4d59..5fc23ebf 100644 --- a/crates/embers-server/src/model.rs +++ b/crates/embers-server/src/model.rs @@ -15,9 +15,29 @@ pub struct Session { pub floating: Vec, pub focused_leaf: Option, pub focused_floating: Option, + pub zoomed_node: Option, pub created_at: Timestamp, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct HelperBuffer { + pub source_buffer_id: BufferId, + pub scope: HelperBufferScope, + pub lines: Vec, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum HelperBufferScope { + Full, + Visible, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum BufferKind { + Pty, + Helper(HelperBuffer), +} + #[derive(Clone)] pub struct Buffer { pub id: BufferId, @@ -31,6 +51,7 @@ pub struct Buffer { pub pty_size: PtySize, pub activity: ActivityState, pub last_snapshot_seq: u64, + pub kind: BufferKind, pub created_at: Timestamp, } @@ -54,6 +75,7 @@ impl Buffer { pty_size: PtySize::new(80, 24), activity: ActivityState::Idle, last_snapshot_seq: 0, + kind: BufferKind::Pty, created_at: Timestamp::now(), } } @@ -81,6 +103,7 @@ impl fmt::Debug for Buffer { .field("pty_size", &self.pty_size) .field("activity", &self.activity) .field("last_snapshot_seq", &self.last_snapshot_seq) + .field("kind", &self.kind) .field("created_at", &self.created_at) .finish() } @@ -98,6 +121,7 @@ impl PartialEq for Buffer { && self.pty_size == other.pty_size && self.activity == other.activity && self.last_snapshot_seq == other.last_snapshot_seq + && self.kind == other.kind && self.created_at == other.created_at } } diff --git a/crates/embers-server/src/persist.rs b/crates/embers-server/src/persist.rs index 302abb74..dd1e989c 100644 --- a/crates/embers-server/src/persist.rs +++ b/crates/embers-server/src/persist.rs @@ -14,8 +14,9 @@ use embers_core::{ use serde::{Deserialize, Serialize}; use crate::model::{ - Buffer, BufferAttachment, BufferState, BufferViewNode, BufferViewState, ExitedBuffer, - FloatingWindow, InterruptedBuffer, Node, Session, SplitNode, TabEntry, TabsNode, + Buffer, BufferAttachment, BufferKind, BufferState, BufferViewNode, BufferViewState, + ExitedBuffer, FloatingWindow, HelperBuffer, HelperBufferScope, InterruptedBuffer, Node, + Session, SplitNode, TabEntry, TabsNode, }; use crate::state::ServerState; @@ -44,6 +45,8 @@ pub struct PersistedSession { pub floating: Vec, pub focused_leaf: Option, pub focused_floating: Option, + #[serde(default)] + pub zoomed_node: Option, pub created_at_ms: u64, } @@ -61,9 +64,31 @@ pub struct PersistedBuffer { pub pty_size: PtySize, pub activity: PersistedActivityState, pub last_snapshot_seq: u64, + #[serde(default)] + pub kind: PersistedBufferKind, pub created_at_ms: u64, } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "kind", rename_all = "snake_case")] +#[derive(Default)] +pub enum PersistedBufferKind { + #[default] + Pty, + Helper { + source_buffer_id: u64, + scope: PersistedHelperBufferScope, + lines: Vec, + }, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum PersistedHelperBufferScope { + Full, + Visible, +} + #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum PersistedBufferState { @@ -274,6 +299,7 @@ pub fn persisted_session(session: &Session) -> PersistedSession { floating: session.floating.iter().map(|id| id.0).collect(), focused_leaf: session.focused_leaf.map(|id| id.0), focused_floating: session.focused_floating.map(|id| id.0), + zoomed_node: session.zoomed_node.map(|id| id.0), created_at_ms: timestamp_to_millis(session.created_at), } } @@ -286,6 +312,7 @@ pub fn restored_session(session: PersistedSession) -> Result { floating: session.floating.into_iter().map(FloatingId).collect(), focused_leaf: session.focused_leaf.map(NodeId), focused_floating: session.focused_floating.map(FloatingId), + zoomed_node: session.zoomed_node.map(NodeId), created_at: timestamp_from_millis(session.created_at_ms)?, }) } @@ -303,6 +330,7 @@ pub fn persisted_buffer(buffer: &Buffer) -> PersistedBuffer { pty_size: buffer.pty_size, activity: persisted_activity(buffer.activity), last_snapshot_seq: buffer.last_snapshot_seq, + kind: persisted_buffer_kind(&buffer.kind), created_at_ms: timestamp_to_millis(buffer.created_at), } } @@ -321,6 +349,7 @@ pub fn restored_buffer(buffer: PersistedBuffer) -> Result { restored.pty_size = buffer.pty_size; restored.activity = restored_activity(buffer.activity); restored.last_snapshot_seq = buffer.last_snapshot_seq; + restored.kind = restored_buffer_kind(buffer.kind); restored.created_at = timestamp_from_millis(buffer.created_at_ms)?; Ok(restored) } @@ -537,6 +566,46 @@ fn restored_activity(activity: PersistedActivityState) -> ActivityState { } } +fn persisted_buffer_kind(kind: &BufferKind) -> PersistedBufferKind { + match kind { + BufferKind::Pty => PersistedBufferKind::Pty, + BufferKind::Helper(helper) => PersistedBufferKind::Helper { + source_buffer_id: helper.source_buffer_id.0, + scope: persisted_helper_scope(helper.scope), + lines: helper.lines.clone(), + }, + } +} + +fn restored_buffer_kind(kind: PersistedBufferKind) -> BufferKind { + match kind { + PersistedBufferKind::Pty => BufferKind::Pty, + PersistedBufferKind::Helper { + source_buffer_id, + scope, + lines, + } => BufferKind::Helper(HelperBuffer { + source_buffer_id: BufferId(source_buffer_id), + scope: restored_helper_scope(scope), + lines, + }), + } +} + +fn persisted_helper_scope(scope: HelperBufferScope) -> PersistedHelperBufferScope { + match scope { + HelperBufferScope::Full => PersistedHelperBufferScope::Full, + HelperBufferScope::Visible => PersistedHelperBufferScope::Visible, + } +} + +fn restored_helper_scope(scope: PersistedHelperBufferScope) -> HelperBufferScope { + match scope { + PersistedHelperBufferScope::Full => HelperBufferScope::Full, + PersistedHelperBufferScope::Visible => HelperBufferScope::Visible, + } +} + fn timestamp_to_millis(timestamp: Timestamp) -> u64 { timestamp .0 diff --git a/crates/embers-server/src/protocol.rs b/crates/embers-server/src/protocol.rs index e907b88e..18ec35c3 100644 --- a/crates/embers-server/src/protocol.rs +++ b/crates/embers-server/src/protocol.rs @@ -1,10 +1,14 @@ use embers_core::{MuxError, Result}; use embers_protocol::{ - BufferRecord, BufferRecordState, BufferViewRecord, FloatingRecord, NodeRecord, NodeRecordKind, - SessionRecord, SessionSnapshot, SplitRecord, TabRecord, TabsRecord, + BufferHistoryScope, BufferLocation, BufferRecord, BufferRecordKind, BufferRecordState, + BufferViewRecord, FloatingRecord, NodeRecord, NodeRecordKind, SessionRecord, SessionSnapshot, + SplitRecord, TabRecord, TabsRecord, }; -use crate::model::{Buffer, BufferAttachment, BufferState, FloatingWindow, Node, Session}; +use crate::model::{ + Buffer, BufferAttachment, BufferKind, BufferState, FloatingWindow, HelperBufferScope, Node, + Session, +}; use crate::state::ServerState; pub fn session_record(session: &Session) -> SessionRecord { @@ -15,6 +19,7 @@ pub fn session_record(session: &Session) -> SessionRecord { floating_ids: session.floating.clone(), focused_leaf_id: session.focused_leaf, focused_floating_id: session.focused_floating, + zoomed_node_id: session.zoomed_node, } } @@ -29,6 +34,18 @@ pub fn buffer_record(buffer: &Buffer) -> BufferRecord { ), BufferState::Exited(exited) => (BufferRecordState::Exited, None, exited.exit_code), }; + let (kind, read_only, helper_source_buffer_id, helper_scope) = match &buffer.kind { + BufferKind::Pty => (BufferRecordKind::Pty, false, None, None), + BufferKind::Helper(helper) => ( + BufferRecordKind::Helper, + true, + Some(helper.source_buffer_id), + Some(match helper.scope { + HelperBufferScope::Full => BufferHistoryScope::Full, + HelperBufferScope::Visible => BufferHistoryScope::Visible, + }), + ), + }; BufferRecord { id: buffer.id, @@ -38,12 +55,16 @@ pub fn buffer_record(buffer: &Buffer) -> BufferRecord { .cwd .as_ref() .map(|path| path.to_string_lossy().into_owned()), + kind, state, pid, attachment_node_id: match buffer.attachment { BufferAttachment::Attached(node_id) => Some(node_id), BufferAttachment::Detached => None, }, + read_only, + helper_source_buffer_id, + helper_scope, pty_size: buffer.pty_size, activity: buffer.activity, last_snapshot_seq: buffer.last_snapshot_seq, @@ -52,6 +73,31 @@ pub fn buffer_record(buffer: &Buffer) -> BufferRecord { } } +pub fn buffer_location( + state: &ServerState, + buffer_id: embers_core::BufferId, +) -> Result { + let buffer = state.buffer(buffer_id)?; + let node_id = match buffer.attachment { + BufferAttachment::Attached(node_id) => Some(node_id), + BufferAttachment::Detached => None, + }; + let session_id = node_id + .map(|node_id| state.node(node_id).map(|node| node.session_id())) + .transpose()?; + let floating_id = node_id + .map(|node_id| state.floating_id_for_node(node_id)) + .transpose()? + .flatten(); + + Ok(BufferLocation { + buffer_id, + session_id, + node_id, + floating_id, + }) +} + pub fn node_record(node: &Node) -> NodeRecord { match node { Node::BufferView(view) => NodeRecord { diff --git a/crates/embers-server/src/server.rs b/crates/embers-server/src/server.rs index 04e9c4e2..ea74fcdf 100644 --- a/crates/embers-server/src/server.rs +++ b/crates/embers-server/src/server.rs @@ -13,15 +13,16 @@ use embers_core::{ BufferId, ErrorCode, MuxError, PtySize, RequestId, Result, WireError, request_span, }; use embers_protocol::{ - BufferCreatedEvent, BufferDetachedEvent, BufferRequest, BufferResponse, BuffersResponse, - ClientChangedEvent, ClientMessage, ClientRecord, ClientRequest, ClientResponse, - ClientsResponse, ErrorResponse, FloatingChangedEvent, FloatingRequest, FloatingResponse, - FocusChangedEvent, FrameType, InputRequest, NodeChangedEvent, OkResponse, PingResponse, - ProtocolError, RawFrame, RenderInvalidatedEvent, ScrollbackSliceResponse, ServerEnvelope, - ServerEvent, ServerResponse, SessionClosedEvent, SessionCreatedEvent, SessionRenamedEvent, - SessionRequest, SessionSnapshotResponse, SessionsResponse, SnapshotResponse, - SubscriptionAckResponse, VisibleSnapshotResponse, decode_client_message, - encode_server_envelope, read_frame, write_frame_no_flush, + BufferCreatedEvent, BufferDetachedEvent, BufferHistoryPlacement, BufferHistoryScope, + BufferLocationResponse, BufferRequest, BufferResponse, BuffersResponse, ClientChangedEvent, + ClientMessage, ClientRecord, ClientRequest, ClientResponse, ClientsResponse, ErrorResponse, + FloatingChangedEvent, FloatingRequest, FloatingResponse, FocusChangedEvent, FrameType, + InputRequest, NodeChangedEvent, OkResponse, PingResponse, ProtocolError, RawFrame, + RenderInvalidatedEvent, ScrollbackSliceResponse, ServerEnvelope, ServerEvent, ServerResponse, + SessionClosedEvent, SessionCreatedEvent, SessionRenamedEvent, SessionRequest, + SessionSnapshotResponse, SessionsResponse, SnapshotResponse, SubscriptionAckResponse, + VisibleSnapshotResponse, decode_client_message, encode_server_envelope, read_frame, + write_frame_no_flush, }; use tokio::net::UnixListener; use tokio::net::unix::{OwnedReadHalf, OwnedWriteHalf}; @@ -29,8 +30,11 @@ use tokio::sync::{Mutex, Notify, mpsc, oneshot, watch}; use tokio::task::JoinHandle; use tracing::{debug, error, info}; +use crate::model::{BufferKind, HelperBufferScope}; use crate::persist::{load_workspace, save_workspace}; -use crate::protocol::{buffer_record, floating_record, session_record, session_snapshot}; +use crate::protocol::{ + buffer_location, buffer_record, floating_record, session_record, session_snapshot, +}; use crate::{ BufferAttachment, BufferRuntimeCallbacks, BufferRuntimeHandle, BufferRuntimeStatus, BufferRuntimeUpdate, BufferState, ServerConfig, ServerState, TabEntry, @@ -531,7 +535,7 @@ impl Runtime { (resp, events, None) } ClientMessage::Buffer(request) => { - let (resp, events) = self.dispatch_buffer(request).await; + let (resp, events) = self.dispatch_buffer(connection_id, request).await; (resp, events, None) } ClientMessage::Node(request) => { @@ -855,6 +859,7 @@ impl Runtime { async fn dispatch_buffer( self: &Arc, + connection_id: u64, request: BufferRequest, ) -> (ServerResponse, Vec) { match request { @@ -1048,6 +1053,82 @@ impl Runtime { Ok(snapshot) => (ServerResponse::ScrollbackSlice(snapshot), Vec::new()), Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), }, + BufferRequest::GetLocation { + request_id, + buffer_id, + } => { + let state = self.state.lock().await; + match buffer_location(&state, buffer_id) { + Ok(location) => ( + ServerResponse::BufferLocation(BufferLocationResponse { + request_id, + location, + }), + Vec::new(), + ), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + BufferRequest::Reveal { + request_id, + buffer_id, + client_id, + } => match self + .reveal_buffer(connection_id, client_id, buffer_id) + .await + { + Ok((location, events)) => ( + ServerResponse::BufferLocation(BufferLocationResponse { + request_id, + location, + }), + events, + ), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + }, + BufferRequest::OpenHistory { + request_id, + buffer_id, + scope, + placement, + client_id, + } => match self + .open_history_buffer(connection_id, client_id, buffer_id, scope, placement) + .await + { + Ok((location, mut reveal_events)) => { + let mut events = Vec::new(); + { + let state = self.state.lock().await; + let buffer = match state.buffer(location.buffer_id) { + Ok(buffer) => buffer_record(buffer), + Err(error) => { + return (mux_error_response(Some(request_id), error), Vec::new()); + } + }; + events.push(ServerEvent::BufferCreated(BufferCreatedEvent { buffer })); + } + if let Some(session_id) = location.session_id { + if location.floating_id.is_some() { + events.push(ServerEvent::FloatingChanged(FloatingChangedEvent { + session_id, + floating_id: location.floating_id, + })); + } else { + events.push(ServerEvent::NodeChanged(NodeChangedEvent { session_id })); + } + } + events.append(&mut reveal_events); + ( + ServerResponse::BufferLocation(BufferLocationResponse { + request_id, + location, + }), + events, + ) + } + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + }, } } @@ -1429,6 +1510,21 @@ impl Runtime { } layout_snapshot_response(&state, request_id, session_id) } + embers_protocol::NodeRequest::Zoom { request_id, .. } + | embers_protocol::NodeRequest::Unzoom { request_id, .. } + | embers_protocol::NodeRequest::ToggleZoom { request_id, .. } + | embers_protocol::NodeRequest::SwapSiblings { request_id, .. } + | embers_protocol::NodeRequest::BreakNode { request_id, .. } + | embers_protocol::NodeRequest::JoinBufferAtNode { request_id, .. } + | embers_protocol::NodeRequest::MoveNodeBefore { request_id, .. } + | embers_protocol::NodeRequest::MoveNodeAfter { request_id, .. } => ( + error_response( + Some(request_id), + ErrorCode::Unsupported, + "node ergonomics commands are not implemented yet", + ), + Vec::new(), + ), } } @@ -1644,6 +1740,199 @@ impl Runtime { } } + async fn resolve_reveal_client_id( + &self, + connection_id: u64, + requested: Option, + ) -> Result { + if let Some(client_id) = requested { + if self.clients.lock().await.contains_key(&client_id) { + return Ok(client_id); + } + return Err(MuxError::not_found(format!("unknown client {client_id}"))); + } + + let clients = self.clients.lock().await; + if clients + .get(&connection_id) + .is_some_and(|client| client.current_session_id.is_some()) + { + return Ok(connection_id); + } + + clients + .iter() + .rev() + .find(|(_, client)| client.current_session_id.is_some()) + .map(|(client_id, _)| *client_id) + .ok_or_else(|| MuxError::conflict("no interactive client is currently attached")) + } + + async fn has_attached_client(&self) -> bool { + self.clients + .lock() + .await + .values() + .any(|client| client.current_session_id.is_some()) + } + + async fn reveal_buffer( + &self, + connection_id: u64, + requested_client_id: Option, + buffer_id: BufferId, + ) -> Result<(embers_protocol::BufferLocation, Vec)> { + let (location, mut events) = { + let mut state = self.state.lock().await; + let location = buffer_location(&state, buffer_id)?; + let Some(session_id) = location.session_id else { + return Ok((location, Vec::new())); + }; + let events = match (location.node_id, location.floating_id) { + (Some(node_id), _) => { + state.focus_leaf(session_id, node_id)?; + let mut events = + vec![ServerEvent::NodeChanged(NodeChangedEvent { session_id })]; + if let Some(focus_event) = focus_changed_event(&state, session_id) { + events.push(ServerEvent::FocusChanged(focus_event)); + } + events + } + (None, Some(floating_id)) => { + state.focus_floating(floating_id)?; + let mut events = Vec::new(); + if let Some(focus_event) = focus_changed_event(&state, session_id) { + events.push(ServerEvent::FocusChanged(focus_event)); + } + events + } + (None, None) => Vec::new(), + }; + (buffer_location(&state, buffer_id)?, events) + }; + + if let Some(session_id) = location.session_id + && (requested_client_id.is_some() || self.has_attached_client().await) + { + let client_id = self + .resolve_reveal_client_id(connection_id, requested_client_id) + .await?; + let (_, event) = self.set_client_session(client_id, Some(session_id)).await?; + events.push(event); + } + + Ok((location, events)) + } + + async fn open_history_buffer( + &self, + connection_id: u64, + requested_client_id: Option, + source_buffer_id: BufferId, + scope: BufferHistoryScope, + placement: BufferHistoryPlacement, + ) -> Result<(embers_protocol::BufferLocation, Vec)> { + let (source_title, source_cwd, source_location, source_kind) = { + let state = self.state.lock().await; + let buffer = state.buffer(source_buffer_id)?.clone(); + let location = buffer_location(&state, source_buffer_id)?; + ( + buffer.title.clone(), + buffer.cwd.clone(), + location, + buffer.kind.clone(), + ) + }; + + let lines = match source_kind { + BufferKind::Helper(helper) => match scope { + BufferHistoryScope::Full => helper.lines, + BufferHistoryScope::Visible => { + let count = { + let state = self.state.lock().await; + u64::from(state.buffer(source_buffer_id)?.pty_size.rows).max(1) + } as usize; + helper + .lines + .into_iter() + .rev() + .take(count) + .collect::>() + .into_iter() + .rev() + .collect() + } + }, + BufferKind::Pty => match scope { + BufferHistoryScope::Full => { + self.capture_snapshot(RequestId(0), source_buffer_id) + .await? + .lines + } + BufferHistoryScope::Visible => { + self.capture_visible_snapshot(RequestId(0), source_buffer_id) + .await? + .lines + } + }, + }; + + let target_session_id = match source_location.session_id { + Some(session_id) => session_id, + None => { + let client_id = self + .resolve_reveal_client_id(connection_id, requested_client_id) + .await?; + let clients = self.clients.lock().await; + clients + .get(&client_id) + .and_then(|client| client.current_session_id) + .ok_or_else(|| { + MuxError::conflict( + "history for detached buffers requires an attached client session", + ) + })? + } + }; + + let helper_scope = match scope { + BufferHistoryScope::Full => HelperBufferScope::Full, + BufferHistoryScope::Visible => HelperBufferScope::Visible, + }; + let helper_title = format!("{} history", source_title); + let helper_buffer_id = { + let mut state = self.state.lock().await; + let helper_buffer_id = state.create_helper_buffer( + helper_title.clone(), + source_buffer_id, + helper_scope, + source_cwd, + lines, + ); + match placement { + BufferHistoryPlacement::Tab => { + state.add_root_tab_from_buffer( + target_session_id, + helper_title, + helper_buffer_id, + )?; + } + BufferHistoryPlacement::Floating => { + state.create_floating_from_buffer( + target_session_id, + helper_buffer_id, + embers_core::FloatGeometry::new(10, 3, 100, 26), + Some(helper_title), + )?; + } + } + helper_buffer_id + }; + + self.reveal_buffer(connection_id, requested_client_id, helper_buffer_id) + .await + } + async fn capture_snapshot( &self, request_id: RequestId, @@ -1653,6 +1942,17 @@ impl Runtime { let state = self.state.lock().await; state.buffer(buffer_id)?.clone() }; + if let BufferKind::Helper(helper) = &buffer.kind { + return Ok(SnapshotResponse { + request_id, + buffer_id, + sequence: buffer.last_snapshot_seq, + size: buffer.pty_size, + lines: helper.lines.clone(), + title: Some(buffer.title), + cwd: buffer.cwd.map(|path| path.display().to_string()), + }); + } let runtime = self.buffer_runtime(buffer_id).await?; let snapshot = runtime.capture_snapshot(buffer.cwd.clone()).await?; self.sync_buffer_runtime_status(buffer_id, &runtime).await?; @@ -1677,6 +1977,25 @@ impl Runtime { let state = self.state.lock().await; state.buffer(buffer_id)?.clone() }; + if let BufferKind::Helper(helper) = &buffer.kind { + let total_lines = u64::try_from(helper.lines.len()).unwrap_or(u64::MAX).max(1); + return Ok(VisibleSnapshotResponse { + request_id, + buffer_id, + sequence: buffer.last_snapshot_seq, + size: buffer.pty_size, + lines: helper.lines.clone(), + title: Some(buffer.title), + cwd: buffer.cwd.map(|path| path.display().to_string()), + viewport_top_line: 0, + total_lines, + alternate_screen: false, + mouse_reporting: false, + focus_reporting: false, + bracketed_paste: false, + cursor: None, + }); + } let runtime = self.buffer_runtime(buffer_id).await?; let snapshot = runtime.capture_visible_snapshot(buffer.cwd.clone()).await?; self.sync_buffer_runtime_status(buffer_id, &runtime).await?; @@ -1706,6 +2025,29 @@ impl Runtime { start_line: u64, line_count: u32, ) -> Result { + let helper_lines = { + let state = self.state.lock().await; + match &state.buffer(buffer_id)?.kind { + BufferKind::Helper(helper) => Some(helper.lines.clone()), + BufferKind::Pty => None, + } + }; + if let Some(lines) = helper_lines { + let total_lines = u64::try_from(lines.len()).unwrap_or(u64::MAX); + let start = usize::try_from(start_line) + .unwrap_or(usize::MAX) + .min(lines.len()); + let end = start + .saturating_add(usize::try_from(line_count).unwrap_or(usize::MAX)) + .min(lines.len()); + return Ok(ScrollbackSliceResponse { + request_id, + buffer_id, + start_line, + total_lines, + lines: lines[start..end].to_vec(), + }); + } let runtime = self.buffer_runtime(buffer_id).await?; let slice = runtime .capture_scrollback_slice(start_line, line_count) @@ -1731,7 +2073,7 @@ impl Runtime { false } else { buffer.last_snapshot_seq = update.sequence; - buffer.activity = update.activity; + buffer.activity = max_activity(buffer.activity, update.activity); if let Some(title) = update.title { match title { Some(title) => buffer.title = title, @@ -2291,7 +2633,10 @@ fn apply_runtime_status( if let Some(title) = &status.title { let _ = state.set_buffer_title(buffer_id, title.clone()); } - let _ = state.set_buffer_activity(buffer_id, status.activity); + if let Some(buffer) = state.buffers.get(&buffer_id) { + let _ = + state.set_buffer_activity(buffer_id, max_activity(buffer.activity, status.activity)); + } if status.running { let _ = state.mark_buffer_running(buffer_id, status.pid); } else { @@ -2299,6 +2644,19 @@ fn apply_runtime_status( } } +fn max_activity( + left: embers_core::ActivityState, + right: embers_core::ActivityState, +) -> embers_core::ActivityState { + use embers_core::ActivityState; + + match (left, right) { + (ActivityState::Bell, _) | (_, ActivityState::Bell) => ActivityState::Bell, + (ActivityState::Activity, _) | (_, ActivityState::Activity) => ActivityState::Activity, + _ => ActivityState::Idle, + } +} + fn buffer_pid_hint(state: &BufferState) -> Option { match state { BufferState::Running(running) => running.pid, diff --git a/crates/embers-server/src/state.rs b/crates/embers-server/src/state.rs index 416d58d2..4581d39e 100644 --- a/crates/embers-server/src/state.rs +++ b/crates/embers-server/src/state.rs @@ -7,8 +7,9 @@ use embers_core::{ }; use crate::model::{ - Buffer, BufferAttachment, BufferState, BufferViewNode, BufferViewState, ExitedBuffer, - FloatingWindow, InterruptedBuffer, Node, RunningBuffer, Session, SplitNode, TabEntry, TabsNode, + Buffer, BufferAttachment, BufferKind, BufferState, BufferViewNode, BufferViewState, + ExitedBuffer, FloatingWindow, HelperBuffer, HelperBufferScope, InterruptedBuffer, Node, + RunningBuffer, Session, SplitNode, TabEntry, TabsNode, }; use crate::persist::{ CURRENT_FORMAT_VERSION, PersistedWorkspace, persisted_buffer, persisted_floating, @@ -322,6 +323,7 @@ impl ServerState { floating: Vec::new(), focused_leaf: None, focused_floating: None, + zoomed_node: None, created_at: Timestamp::now(), }, ); @@ -350,6 +352,28 @@ impl ServerState { buffer_id } + pub fn create_helper_buffer( + &mut self, + title: impl Into, + source_buffer_id: BufferId, + scope: HelperBufferScope, + cwd: Option, + lines: Vec, + ) -> BufferId { + let buffer_id = self.buffer_ids.next(); + let rows = u16::try_from(lines.len().max(1)).unwrap_or(u16::MAX); + let mut buffer = Buffer::new(buffer_id, title, Vec::new(), cwd, BTreeMap::new()); + buffer.pty_size = PtySize::new(80, rows); + buffer.last_snapshot_seq = 1; + buffer.kind = BufferKind::Helper(HelperBuffer { + source_buffer_id, + scope, + lines, + }); + self.buffers.insert(buffer_id, buffer); + buffer_id + } + pub fn remove_buffer(&mut self, buffer_id: BufferId) -> Result { let buffer = self.buffer(buffer_id)?.clone(); if !matches!(buffer.attachment, BufferAttachment::Detached) { @@ -1671,7 +1695,7 @@ impl ServerState { .map(|floating| floating.id) } - fn floating_id_for_node(&self, node_id: NodeId) -> Result> { + pub fn floating_id_for_node(&self, node_id: NodeId) -> Result> { let root = self.top_root_for_node(node_id)?; Ok(self.floating_id_by_root(root)) } diff --git a/crates/embers-test-support/Cargo.toml b/crates/embers-test-support/Cargo.toml index b3961c04..e2c11150 100644 --- a/crates/embers-test-support/Cargo.toml +++ b/crates/embers-test-support/Cargo.toml @@ -6,6 +6,9 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[lib] +doctest = false + [dependencies] assert_cmd.workspace = true embers-core = { path = "../embers-core" } From 9952c25547246a96a6fa2ce478b1acbcec1ccf07 Mon Sep 17 00:00:00 2001 From: Emma <817422+Pajn@users.noreply.github.com> Date: Sun, 22 Mar 2026 22:03:35 +0100 Subject: [PATCH 3/5] Add native node ergonomics and script actions --- crates/embers-cli/src/interactive.rs | 10 +- crates/embers-cli/tests/interactive.rs | 3 + crates/embers-cli/tests/panes.rs | 148 +++++++ crates/embers-client/src/client.rs | 13 + crates/embers-client/src/configured_client.rs | 159 +++++++- crates/embers-client/src/presentation.rs | 166 ++++++-- crates/embers-client/src/scripting/model.rs | 38 ++ crates/embers-client/src/scripting/runtime.rs | 161 +++++++- crates/embers-client/tests/e2e.rs | 55 ++- crates/embers-client/tests/script_actions.rs | 95 +++++ crates/embers-client/tests/support/mod.rs | 8 +- crates/embers-server/src/server.rs | 122 +++++- crates/embers-server/src/state.rs | 371 +++++++++++++++++ crates/embers-server/tests/model_state.rs | 97 +++++ docs/config-api-book/404.html | 2 +- docs/config-api-book/action.html | 191 ++++++++- docs/config-api-book/buffer-ref.html | 2 +- docs/config-api-book/context.html | 2 +- docs/config-api-book/defs/registration.rhai | 27 ++ docs/config-api-book/defs/runtime.rhai | 27 ++ docs/config-api-book/event-info.html | 2 +- docs/config-api-book/example.html | 2 +- docs/config-api-book/floating-ref.html | 2 +- docs/config-api-book/index.html | 2 +- docs/config-api-book/mouse.html | 2 +- docs/config-api-book/mux.html | 2 +- docs/config-api-book/node-ref.html | 2 +- docs/config-api-book/print.html | 380 +++++++++++++++++- docs/config-api-book/registration-action.html | 191 ++++++++- .../config-api-book/registration-globals.html | 2 +- docs/config-api-book/registration-system.html | 2 +- docs/config-api-book/registration-tree.html | 2 +- docs/config-api-book/registration-ui.html | 2 +- docs/config-api-book/runtime-theme.html | 2 +- docs/config-api-book/searcher-c2a407aa.js | 2 +- docs/config-api-book/searchindex-256e957a.js | 1 - docs/config-api-book/searchindex-6f9ff0e9.js | 1 + docs/config-api-book/session-ref.html | 2 +- docs/config-api-book/system-runtime.html | 2 +- docs/config-api-book/tab-bar-context.html | 2 +- docs/config-api-book/tab-info.html | 2 +- docs/config-api-book/tabbar.html | 2 +- docs/config-api-book/theme.html | 2 +- docs/config-api-book/tree.html | 2 +- docs/config-api-book/ui.html | 2 +- docs/config-api/action.md | 198 +++++++++ docs/config-api/defs/registration.rhai | 27 ++ docs/config-api/defs/runtime.rhai | 27 ++ docs/config-api/registration-action.md | 198 +++++++++ 49 files changed, 2653 insertions(+), 109 deletions(-) delete mode 100644 docs/config-api-book/searchindex-256e957a.js create mode 100644 docs/config-api-book/searchindex-6f9ff0e9.js diff --git a/crates/embers-cli/src/interactive.rs b/crates/embers-cli/src/interactive.rs index 05e49d22..8c928173 100644 --- a/crates/embers-cli/src/interactive.rs +++ b/crates/embers-cli/src/interactive.rs @@ -133,9 +133,11 @@ pub async fn run( continue; } - match tokio::time::timeout(EVENT_POLL_INTERVAL, configured.process_next_event()).await { - Ok(result) => { - let event = result?; + match configured + .process_next_event_timeout(EVENT_POLL_INTERVAL) + .await? + { + Some(event) => { match switched_session_id(&event, attached_client_id) { SwitchedSession::Switched(next_session_id) => { ensure_root_window(configured.client_mut(), next_session_id).await?; @@ -149,7 +151,7 @@ pub async fn run( terminal.write_bytes(&drain_terminal_output(&mut configured))?; dirty = true; } - Err(_) => { + None => { continue; } } diff --git a/crates/embers-cli/tests/interactive.rs b/crates/embers-cli/tests/interactive.rs index d35a6c28..190873dc 100644 --- a/crates/embers-cli/tests/interactive.rs +++ b/crates/embers-cli/tests/interactive.rs @@ -404,6 +404,9 @@ async fn local_selection_yank_emits_osc52_clipboard_sequence() { populate_scrollback_or_wait(&mut harness, 40).await; page_up_until_visible(&mut harness, "line-1"); + harness + .wait_for_quiet(Duration::from_millis(200), IO_TIMEOUT) + .unwrap_or_else(|error| panic!("scrollback render settled: {error}")); harness.write_all("vly").expect("select and yank"); let output = harness .read_until_contains("]52;c;", IO_TIMEOUT) diff --git a/crates/embers-cli/tests/panes.rs b/crates/embers-cli/tests/panes.rs index 048cf184..a7a21ad0 100644 --- a/crates/embers-cli/tests/panes.rs +++ b/crates/embers-cli/tests/panes.rs @@ -372,3 +372,151 @@ async fn buffer_show_and_history_open_helper_buffers() { server.shutdown().await.expect("shutdown server"); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn node_commands_cover_zoom_swap_break_join_and_reorder() { + let server = TestServer::start().await.expect("start server"); + + run_cli(&server, ["new-session", "alpha"]); + run_cli( + &server, + [ + "new-window", + "-t", + "alpha", + "--title", + "work", + "--", + "/bin/sh", + ], + ); + let split = run_cli(&server, ["split-window", "--", "/bin/sh"]); + let second_pane_id = stdout(&split) + .trim() + .parse::() + .expect("split-window returns pane id"); + + let mut connection = TestConnection::connect(server.socket_path()) + .await + .expect("connect protocol client"); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + let first_pane_id = snapshot + .nodes + .iter() + .find(|node| node.buffer_view.as_ref().is_some() && node.id.0 != second_pane_id) + .map(|node| node.id.0) + .expect("first pane id exists"); + + run_cli(&server, ["node", "zoom", &first_pane_id.to_string()]); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + assert_eq!( + snapshot.session.zoomed_node_id, + Some(embers_core::NodeId(first_pane_id)) + ); + + run_cli(&server, ["node", "unzoom", "-t", "alpha"]); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + assert_eq!(snapshot.session.zoomed_node_id, None); + + let parent_split_id = snapshot + .nodes + .iter() + .find(|node| { + node.split.as_ref().is_some_and(|split| { + split + .child_ids + .contains(&embers_core::NodeId(first_pane_id)) + && split + .child_ids + .contains(&embers_core::NodeId(second_pane_id)) + }) + }) + .map(|node| node.id) + .expect("parent split exists"); + + run_cli( + &server, + [ + "node", + "swap", + &first_pane_id.to_string(), + &second_pane_id.to_string(), + ], + ); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + let split = snapshot + .nodes + .iter() + .find(|node| node.id == parent_split_id) + .and_then(|node| node.split.as_ref()) + .expect("split still exists"); + assert_eq!(split.child_ids[0], embers_core::NodeId(second_pane_id)); + + run_cli( + &server, + [ + "node", + "move-before", + &first_pane_id.to_string(), + &second_pane_id.to_string(), + ], + ); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + let split = snapshot + .nodes + .iter() + .find(|node| node.id == parent_split_id) + .and_then(|node| node.split.as_ref()) + .expect("split still exists after reorder"); + assert_eq!(split.child_ids[0], embers_core::NodeId(first_pane_id)); + + run_cli( + &server, + [ + "node", + "break", + &second_pane_id.to_string(), + "--to", + "floating", + ], + ); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + assert_eq!(snapshot.floating.len(), 1); + + let detached = connection + .request(&ClientMessage::Buffer(BufferRequest::Create { + request_id: RequestId(10), + title: Some("notes".to_owned()), + command: vec!["/bin/sh".to_owned()], + cwd: None, + env: Default::default(), + })) + .await + .expect("buffer create succeeds"); + let detached_buffer_id = match detached { + ServerResponse::Buffer(response) => response.buffer.id, + other => panic!("expected buffer response, got {other:?}"), + }; + + run_cli( + &server, + [ + "node", + "join-buffer", + &first_pane_id.to_string(), + &detached_buffer_id.to_string(), + "--as", + "tab-after", + ], + ); + let snapshot = session_snapshot_by_name(&mut connection, "alpha").await; + assert!( + snapshot + .nodes + .iter() + .any(|node| node.tabs.as_ref().is_some_and(|tabs| tabs.tabs.len() >= 2)), + "join-buffer created or reused a tabs container" + ); + + server.shutdown().await.expect("shutdown server"); +} diff --git a/crates/embers-client/src/client.rs b/crates/embers-client/src/client.rs index 92c6a5ce..7552cc2c 100644 --- a/crates/embers-client/src/client.rs +++ b/crates/embers-client/src/client.rs @@ -121,6 +121,19 @@ where } } + pub async fn process_next_event_timeout( + &mut self, + timeout: std::time::Duration, + ) -> Result> { + let event = match tokio::time::timeout(timeout, self.transport.next_event()).await { + Ok(result) => result?, + Err(_) => return Ok(None), + }; + self.state.apply_event(&event); + self.resync_for_event(&event).await?; + Ok(Some(event)) + } + pub async fn resync_session(&mut self, session_id: SessionId) -> Result<()> { let response = self .transport diff --git a/crates/embers-client/src/configured_client.rs b/crates/embers-client/src/configured_client.rs index 85ae8aeb..cdad9aa8 100644 --- a/crates/embers-client/src/configured_client.rs +++ b/crates/embers-client/src/configured_client.rs @@ -326,12 +326,28 @@ where pub async fn process_next_event(&mut self) -> Result { let event = self.client.process_next_event().await?; + self.apply_processed_event(&event).await?; + Ok(event) + } + + pub async fn process_next_event_timeout( + &mut self, + timeout: std::time::Duration, + ) -> Result> { + let Some(event) = self.client.process_next_event_timeout(timeout).await? else { + return Ok(None); + }; + self.apply_processed_event(&event).await?; + Ok(Some(event)) + } + + async fn apply_processed_event(&mut self, event: &ServerEvent) -> Result<()> { if let ServerEvent::RenderInvalidated(event) = &event { self.client.refresh_buffer_snapshot(event.buffer_id).await?; } - let session_id = self.event_session_id(&event); - let mut event_names = vec![event_name(&event).to_owned()]; + let session_id = self.event_session_id(event); + let mut event_names = vec![event_name(event).to_owned()]; if let ServerEvent::RenderInvalidated(render) = &event && self .client @@ -347,7 +363,7 @@ where let context = self.context_for( session_id, self.viewport, - Some(event_info(&event_name, &event)), + Some(event_info(&event_name, event)), ); match self .config @@ -362,7 +378,7 @@ where Err(error) => self.record_notification(error.to_string()), } } - Ok(event) + Ok(()) } pub async fn render_session( @@ -899,6 +915,141 @@ where .await?; self.client.resync_all_sessions().await } + Action::OpenBufferHistory { + buffer_id, + scope, + placement, + } => { + self.client + .request_message(ClientMessage::Buffer(BufferRequest::OpenHistory { + request_id: self.client.next_request_id(), + buffer_id, + scope, + placement, + client_id: None, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::ZoomNode { node_id } => { + let node_id = node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| MuxError::invalid_input("no focused node to zoom"))?; + self.client + .request_message(ClientMessage::Node(NodeRequest::Zoom { + request_id: self.client.next_request_id(), + node_id, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::UnzoomNode { + session_id: target_session_id, + } => { + self.client + .request_message(ClientMessage::Node(NodeRequest::Unzoom { + request_id: self.client.next_request_id(), + session_id: target_session_id.unwrap_or(session_id), + })) + .await?; + self.client.resync_all_sessions().await + } + Action::ToggleZoomNode { node_id } => { + let node_id = node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| MuxError::invalid_input("no focused node to toggle zoom"))?; + self.client + .request_message(ClientMessage::Node(NodeRequest::ToggleZoom { + request_id: self.client.next_request_id(), + node_id, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::SwapSiblingNodes { + first_node_id, + second_node_id, + } => { + let first_node_id = first_node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| MuxError::invalid_input("no focused node to swap"))?; + self.client + .request_message(ClientMessage::Node(NodeRequest::SwapSiblings { + request_id: self.client.next_request_id(), + first_node_id, + second_node_id, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::BreakNode { + node_id, + destination, + } => { + let node_id = node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| MuxError::invalid_input("no focused node to break"))?; + self.client + .request_message(ClientMessage::Node(NodeRequest::BreakNode { + request_id: self.client.next_request_id(), + node_id, + destination, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::JoinBufferAtNode { + node_id, + buffer_id, + placement, + } => { + let node_id = node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| { + MuxError::invalid_input("no focused node to join buffer into") + })?; + self.client + .request_message(ClientMessage::Node(NodeRequest::JoinBufferAtNode { + request_id: self.client.next_request_id(), + node_id, + buffer_id, + placement, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::MoveNodeBefore { + node_id, + sibling_node_id, + } => { + let node_id = node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| MuxError::invalid_input("no focused node to reorder"))?; + self.client + .request_message(ClientMessage::Node(NodeRequest::MoveNodeBefore { + request_id: self.client.next_request_id(), + node_id, + sibling_node_id, + })) + .await?; + self.client.resync_all_sessions().await + } + Action::MoveNodeAfter { + node_id, + sibling_node_id, + } => { + let node_id = node_id + .or_else(|| presentation.focused_leaf().map(|leaf| leaf.node_id)) + .ok_or_else(|| MuxError::invalid_input("no focused node to reorder"))?; + self.client + .request_message(ClientMessage::Node(NodeRequest::MoveNodeAfter { + request_id: self.client.next_request_id(), + node_id, + sibling_node_id, + })) + .await?; + self.client.resync_all_sessions().await + } other => Err(MuxError::invalid_input(format!( "action '{other:?}' is not supported by the live executor yet" ))), diff --git a/crates/embers-client/src/presentation.rs b/crates/embers-client/src/presentation.rs index b36a720d..a77c17ba 100644 --- a/crates/embers-client/src/presentation.rs +++ b/crates/embers-client/src/presentation.rs @@ -92,38 +92,44 @@ impl PresentationModel { activity_by_node: BTreeMap::new(), buffer_count_by_node: BTreeMap::new(), }; - projector.project_node(session.root_node_id, root_bounds, None, true, Vec::new())?; - - let overlay_bounds = root_bounds; - for floating_id in &session.floating_ids { - let Some(window) = state.floating.get(floating_id) else { - continue; - }; - if !window.visible { - continue; - } + if let Some(zoomed_node_id) = session.zoomed_node_id + && state.nodes.contains_key(&zoomed_node_id) + { + projector.project_node(zoomed_node_id, root_bounds, None, false, Vec::new())?; + } else { + projector.project_node(session.root_node_id, root_bounds, None, true, Vec::new())?; + + let overlay_bounds = root_bounds; + for floating_id in &session.floating_ids { + let Some(window) = state.floating.get(floating_id) else { + continue; + }; + if !window.visible { + continue; + } - let rect = clip_rect(geometry_rect(window.geometry), overlay_bounds); - if rect.size.width == 0 || rect.size.height == 0 { - continue; - } + let rect = clip_rect(geometry_rect(window.geometry), overlay_bounds); + if rect.size.width == 0 || rect.size.height == 0 { + continue; + } - let content_rect = inset_border(rect); - projector.projection.floating.push(FloatingFrame { - floating_id: window.id, - rect, - content_rect, - title: window.title.clone(), - focused: window.focused, - }); - - projector.project_node( - window.root_node_id, - content_rect, - Some(window.id), - false, - Vec::new(), - )?; + let content_rect = inset_border(rect); + projector.projection.floating.push(FloatingFrame { + floating_id: window.id, + rect, + content_rect, + title: window.title.clone(), + focused: window.focused, + }); + + projector.project_node( + window.root_node_id, + content_rect, + Some(window.id), + false, + Vec::new(), + )?; + } } let root_tabs = projection.tab_bars.iter().find(|bar| bar.is_root).cloned(); @@ -628,6 +634,106 @@ fn inset_top(rect: Rect, amount: u16) -> Rect { } } +#[cfg(test)] +mod zoom_tests { + use super::PresentationModel; + use crate::state::ClientState; + use embers_core::{ActivityState, BufferId, NodeId, PtySize, SessionId, Size}; + use embers_protocol::{ + BufferRecord, BufferRecordKind, BufferRecordState, BufferViewRecord, NodeRecord, + NodeRecordKind, SessionRecord, SplitRecord, + }; + + #[test] + fn zoomed_node_projects_only_the_zoomed_subtree() { + let mut state = ClientState::default(); + state.sessions.insert( + SessionId(1), + SessionRecord { + id: SessionId(1), + name: "main".to_owned(), + root_node_id: NodeId(1), + floating_ids: Vec::new(), + focused_leaf_id: Some(NodeId(3)), + focused_floating_id: None, + zoomed_node_id: Some(NodeId(3)), + }, + ); + state.nodes.insert( + NodeId(1), + NodeRecord { + id: NodeId(1), + session_id: SessionId(1), + parent_id: None, + kind: NodeRecordKind::Split, + buffer_view: None, + split: Some(SplitRecord { + direction: embers_core::SplitDirection::Vertical, + child_ids: vec![NodeId(2), NodeId(3)], + sizes: vec![1, 1], + }), + tabs: None, + }, + ); + for (node_id, buffer_id, focused) in [ + (NodeId(2), BufferId(10), false), + (NodeId(3), BufferId(11), true), + ] { + state.nodes.insert( + node_id, + NodeRecord { + id: node_id, + session_id: SessionId(1), + parent_id: Some(NodeId(1)), + kind: NodeRecordKind::BufferView, + buffer_view: Some(BufferViewRecord { + buffer_id, + focused, + zoomed: node_id == NodeId(3), + follow_output: true, + last_render_size: PtySize::new(80, 24), + }), + split: None, + tabs: None, + }, + ); + state.buffers.insert( + buffer_id, + BufferRecord { + id: buffer_id, + title: format!("buffer-{buffer_id}"), + command: vec!["sh".to_owned()], + cwd: None, + kind: BufferRecordKind::Pty, + state: BufferRecordState::Running, + pid: Some(1), + attachment_node_id: Some(node_id), + read_only: false, + helper_source_buffer_id: None, + helper_scope: None, + pty_size: PtySize::new(80, 24), + activity: ActivityState::Idle, + last_snapshot_seq: 0, + exit_code: None, + env: Default::default(), + }, + ); + } + + let presentation = PresentationModel::project( + &state, + SessionId(1), + Size { + width: 80, + height: 24, + }, + ) + .expect("project zoomed session"); + assert_eq!(presentation.leaves.len(), 1); + assert_eq!(presentation.leaves[0].node_id, NodeId(3)); + } +} + fn inset_border(rect: Rect) -> Rect { Rect { origin: Point { diff --git a/crates/embers-client/src/scripting/model.rs b/crates/embers-client/src/scripting/model.rs index e201d699..f00e4333 100644 --- a/crates/embers-client/src/scripting/model.rs +++ b/crates/embers-client/src/scripting/model.rs @@ -1,6 +1,9 @@ use std::collections::BTreeMap; use embers_core::{BufferId, FloatingId, NodeId, SplitDirection}; +use embers_protocol::{ + BufferHistoryPlacement, BufferHistoryScope, NodeBreakDestination, NodeJoinPlacement, +}; use crate::input::KeySequence; use crate::presentation::NavigationDirection; @@ -37,6 +40,11 @@ pub enum Action { RevealBuffer { buffer_id: BufferId, }, + OpenBufferHistory { + buffer_id: BufferId, + scope: BufferHistoryScope, + placement: BufferHistoryPlacement, + }, SplitCurrent { direction: SplitDirection, new_child: TreeSpec, @@ -81,6 +89,36 @@ pub enum Action { focus: bool, close_on_empty: bool, }, + ZoomNode { + node_id: Option, + }, + UnzoomNode { + session_id: Option, + }, + ToggleZoomNode { + node_id: Option, + }, + SwapSiblingNodes { + first_node_id: Option, + second_node_id: NodeId, + }, + BreakNode { + node_id: Option, + destination: NodeBreakDestination, + }, + JoinBufferAtNode { + node_id: Option, + buffer_id: BufferId, + placement: NodeJoinPlacement, + }, + MoveNodeBefore { + node_id: Option, + sibling_node_id: NodeId, + }, + MoveNodeAfter { + node_id: Option, + sibling_node_id: NodeId, + }, SendKeys { buffer_id: Option, keys: KeySequence, diff --git a/crates/embers-client/src/scripting/runtime.rs b/crates/embers-client/src/scripting/runtime.rs index 955a463a..300ff96c 100644 --- a/crates/embers-client/src/scripting/runtime.rs +++ b/crates/embers-client/src/scripting/runtime.rs @@ -21,6 +21,9 @@ use super::model::{ }; use super::types::{BarSegment, BarSpec, BarTarget, RgbColor, StyleSpec, ThemeSpec}; use super::{RhaiResultOf, ScriptResult}; +use embers_protocol::{ + BufferHistoryPlacement, BufferHistoryScope, NodeBreakDestination, NodeJoinPlacement, +}; #[derive(Clone, Default)] pub(crate) struct ActionApi; @@ -915,8 +918,9 @@ mod documented_mux_api { #[export_module] mod documented_action_api { use super::{ - Action, ActionApi, Array, ImmutableString, Map, NativeCallContext, NavigationDirection, - TreeSpec, parse_action_array, parse_buffer_id, parse_bytes, parse_floating_id, + Action, ActionApi, Array, BufferHistoryPlacement, BufferHistoryScope, ImmutableString, Map, + NativeCallContext, NavigationDirection, NodeBreakDestination, NodeJoinPlacement, TreeSpec, + parse_action_array, parse_buffer_id, parse_bytes, parse_floating_id, parse_floating_options, parse_floating_spec, parse_index, parse_key_sequence, parse_node_id, parse_notify_level, parse_split_direction, runtime_error_at, with_call_position, @@ -1295,6 +1299,159 @@ mod documented_action_api { }) } + /// Open the history of a buffer in a new view. + #[rhai_fn(return_raw, name = "open_buffer_history")] + pub fn open_buffer_history( + ctx: NativeCallContext, + _: &mut ActionApi, + buffer_id: i64, + scope: &str, + placement: &str, + ) -> RhaiResultOf { + let position = ctx.call_position(); + with_call_position(ctx, || { + let scope = match scope { + "visible" => BufferHistoryScope::Visible, + "full" => BufferHistoryScope::Full, + _ => { + return Err(runtime_error_at("invalid scope", position)); + } + }; + let placement = match placement { + "floating" => BufferHistoryPlacement::Floating, + "tab" => BufferHistoryPlacement::Tab, + _ => { + return Err(runtime_error_at("invalid placement", position)); + } + }; + Ok(Action::OpenBufferHistory { + buffer_id: parse_buffer_id(buffer_id)?, + scope, + placement, + }) + }) + } + + /// Zoom the current node. + #[rhai_fn(name = "zoom_current_node")] + pub fn zoom_current_node(_: &mut ActionApi) -> Action { + Action::ZoomNode { node_id: None } + } + + /// Unzoom the current session. + #[rhai_fn(name = "unzoom_current_session")] + pub fn unzoom_current_session(_: &mut ActionApi) -> Action { + Action::UnzoomNode { session_id: None } + } + + /// Toggle zoom on a node. + #[rhai_fn(return_raw, name = "toggle_zoom_node")] + pub fn toggle_zoom_node( + ctx: NativeCallContext, + _: &mut ActionApi, + node_id: i64, + ) -> RhaiResultOf { + with_call_position(ctx, || { + Ok(Action::ToggleZoomNode { + node_id: Some(parse_node_id(node_id)?), + }) + }) + } + + /// Swap the current node with a sibling. + #[rhai_fn(return_raw, name = "swap_current_node")] + pub fn swap_current_node( + ctx: NativeCallContext, + _: &mut ActionApi, + second_node_id: i64, + ) -> RhaiResultOf { + with_call_position(ctx, || { + Ok(Action::SwapSiblingNodes { + first_node_id: None, + second_node_id: parse_node_id(second_node_id)?, + }) + }) + } + + /// Break the current node into a new tab or floating window. + #[rhai_fn(return_raw, name = "break_current_node")] + pub fn break_current_node( + ctx: NativeCallContext, + _: &mut ActionApi, + destination: &str, + ) -> RhaiResultOf { + let position = ctx.call_position(); + with_call_position(ctx, || { + let destination = match destination { + "tab" => NodeBreakDestination::Tab, + "floating" => NodeBreakDestination::Floating, + _ => return Err(runtime_error_at("invalid destination", position)), + }; + Ok(Action::BreakNode { + node_id: None, + destination, + }) + }) + } + + /// Join a buffer at the current node. + #[rhai_fn(return_raw, name = "join_buffer_here")] + pub fn join_buffer_here( + ctx: NativeCallContext, + _: &mut ActionApi, + buffer_id: i64, + placement: &str, + ) -> RhaiResultOf { + let position = ctx.call_position(); + with_call_position(ctx, || { + let placement = match placement { + "tab-after" => NodeJoinPlacement::TabAfter, + "tab-before" => NodeJoinPlacement::TabBefore, + "left" => NodeJoinPlacement::Left, + "right" => NodeJoinPlacement::Right, + "up" => NodeJoinPlacement::Up, + "down" => NodeJoinPlacement::Down, + _ => return Err(runtime_error_at("invalid placement", position)), + }; + Ok(Action::JoinBufferAtNode { + node_id: None, + buffer_id: parse_buffer_id(buffer_id)?, + placement, + }) + }) + } + + /// Move the current node before a sibling. + #[rhai_fn(return_raw, name = "move_current_node_before")] + pub fn move_current_node_before( + ctx: NativeCallContext, + _: &mut ActionApi, + sibling_node_id: i64, + ) -> RhaiResultOf { + with_call_position(ctx, || { + Ok(Action::MoveNodeBefore { + node_id: None, + sibling_node_id: parse_node_id(sibling_node_id)?, + }) + }) + } + + /// Move a node after a sibling. + #[rhai_fn(return_raw, name = "move_node_after")] + pub fn move_node_after( + ctx: NativeCallContext, + _: &mut ActionApi, + node_id: i64, + sibling_node_id: i64, + ) -> RhaiResultOf { + with_call_position(ctx, || { + Ok(Action::MoveNodeAfter { + node_id: Some(parse_node_id(node_id)?), + sibling_node_id: parse_node_id(sibling_node_id)?, + }) + }) + } + /// Move a buffer into a specific node. #[rhai_fn(return_raw, name = "move_buffer_to_node")] pub fn move_buffer_to_node( diff --git a/crates/embers-client/tests/e2e.rs b/crates/embers-client/tests/e2e.rs index bbd25064..48c227ce 100644 --- a/crates/embers-client/tests/e2e.rs +++ b/crates/embers-client/tests/e2e.rs @@ -637,30 +637,41 @@ async fn hidden_activity_is_visible_and_reconnect_rehydrates_state() { let mut first_client = MuxClient::connect(server.socket_path()) .await .expect("first client connects"); - first_client - .resync_all_sessions() - .await - .expect("first client resyncs"); - refresh_all_snapshots(&mut first_client).await; - let session_id = session_id_by_name(&first_client, "alpha"); - let model = PresentationModel::project( - first_client.state(), - session_id, - Size { - width: 80, - height: 24, - }, - ) - .expect("projection succeeds"); - let tabs = model - .tab_bars - .iter() - .find(|tabs| tabs.node_id == nested_tabs_id) - .expect("nested tabs frame exists"); - assert!( - tabs.tabs + let mut saw_hidden_activity = false; + for _ in 0..10 { + first_client + .resync_all_sessions() + .await + .expect("first client resyncs"); + refresh_all_snapshots(&mut first_client).await; + let session_id = session_id_by_name(&first_client, "alpha"); + let model = PresentationModel::project( + first_client.state(), + session_id, + Size { + width: 80, + height: 24, + }, + ) + .expect("projection succeeds"); + let tabs = model + .tab_bars + .iter() + .find(|tabs| tabs.node_id == nested_tabs_id) + .expect("nested tabs frame exists"); + if tabs + .tabs .iter() .any(|tab| tab.title == "bg" && tab.activity != ActivityState::Idle) + { + saw_hidden_activity = true; + break; + } + tokio::time::sleep(Duration::from_millis(50)).await; + } + assert!( + saw_hidden_activity, + "hidden tab activity should propagate before reconnect" ); drop(first_client); diff --git a/crates/embers-client/tests/script_actions.rs b/crates/embers-client/tests/script_actions.rs index 065271bc..18162db9 100644 --- a/crates/embers-client/tests/script_actions.rs +++ b/crates/embers-client/tests/script_actions.rs @@ -7,6 +7,9 @@ use embers_client::{ config::{ConfigOrigin, LoadedConfigSource}, }; use embers_core::{BufferId, FloatingId, NodeId, Size, SplitDirection}; +use embers_protocol::{ + BufferHistoryPlacement, BufferHistoryScope, NodeBreakDestination, NodeJoinPlacement, +}; use crate::support::{SESSION_ID, demo_state}; @@ -46,6 +49,17 @@ fn action_helpers_roundtrip_to_typed_actions() { fn select_move_action(ctx) { action.select_move_left() } fn yank_action(ctx) { action.yank_selection() } fn notify_user_action(ctx) { action.notify("info", "hello") } + fn open_history_action(ctx) { + action.open_buffer_history(4, "visible", "floating") + } + fn zoom_action(ctx) { action.zoom_current_node() } + fn unzoom_action(ctx) { action.unzoom_current_session() } + fn toggle_zoom_action(ctx) { action.toggle_zoom_node(7) } + fn swap_nodes_action(ctx) { action.swap_current_node(8) } + fn break_node_action(ctx) { action.break_current_node("tab") } + fn join_buffer_action(ctx) { action.join_buffer_here(9, "tab-after") } + fn move_before_action(ctx) { action.move_current_node_before(10) } + fn move_after_action(ctx) { action.move_node_after(11, 12) } define_action("enter-copy", enter_copy_action); define_action("focus-left", focus_left_action); @@ -67,6 +81,15 @@ fn action_helpers_roundtrip_to_typed_actions() { define_action("select-move", select_move_action); define_action("yank", yank_action); define_action("notify-user", notify_user_action); + define_action("open-history", open_history_action); + define_action("zoom", zoom_action); + define_action("unzoom", unzoom_action); + define_action("toggle-zoom", toggle_zoom_action); + define_action("swap-nodes", swap_nodes_action); + define_action("break-node", break_node_action); + define_action("join-buffer", join_buffer_action); + define_action("move-before", move_before_action); + define_action("move-after", move_after_action); "#, ); let context = demo_context(); @@ -250,6 +273,78 @@ fn action_helpers_roundtrip_to_typed_actions() { message: "hello".to_owned(), }] ); + assert_eq!( + engine + .run_named_action("open-history", demo_context()) + .unwrap(), + vec![Action::OpenBufferHistory { + buffer_id: BufferId(4), + scope: BufferHistoryScope::Visible, + placement: BufferHistoryPlacement::Floating, + }] + ); + assert_eq!( + engine.run_named_action("zoom", demo_context()).unwrap(), + vec![Action::ZoomNode { node_id: None }] + ); + assert_eq!( + engine.run_named_action("unzoom", demo_context()).unwrap(), + vec![Action::UnzoomNode { session_id: None }] + ); + assert_eq!( + engine + .run_named_action("toggle-zoom", demo_context()) + .unwrap(), + vec![Action::ToggleZoomNode { + node_id: Some(NodeId(7)), + }] + ); + assert_eq!( + engine + .run_named_action("swap-nodes", demo_context()) + .unwrap(), + vec![Action::SwapSiblingNodes { + first_node_id: None, + second_node_id: NodeId(8), + }] + ); + assert_eq!( + engine + .run_named_action("break-node", demo_context()) + .unwrap(), + vec![Action::BreakNode { + node_id: None, + destination: NodeBreakDestination::Tab, + }] + ); + assert_eq!( + engine + .run_named_action("join-buffer", demo_context()) + .unwrap(), + vec![Action::JoinBufferAtNode { + node_id: None, + buffer_id: BufferId(9), + placement: NodeJoinPlacement::TabAfter, + }] + ); + assert_eq!( + engine + .run_named_action("move-before", demo_context()) + .unwrap(), + vec![Action::MoveNodeBefore { + node_id: None, + sibling_node_id: NodeId(10), + }] + ); + assert_eq!( + engine + .run_named_action("move-after", demo_context()) + .unwrap(), + vec![Action::MoveNodeAfter { + node_id: Some(NodeId(11)), + sibling_node_id: NodeId(12), + }] + ); } #[test] diff --git a/crates/embers-client/tests/support/mod.rs b/crates/embers-client/tests/support/mod.rs index 0bb083fb..d08d39b2 100644 --- a/crates/embers-client/tests/support/mod.rs +++ b/crates/embers-client/tests/support/mod.rs @@ -5,9 +5,9 @@ use embers_core::{ ActivityState, BufferId, FloatGeometry, FloatingId, NodeId, PtySize, SessionId, SplitDirection, }; use embers_protocol::{ - BufferRecord, BufferRecordKind, BufferRecordState, BufferViewRecord, FloatingRecord, - NodeRecord, NodeRecordKind, SessionRecord, SessionSnapshot, SplitRecord, TabRecord, TabsRecord, - VisibleSnapshotResponse, + BufferHistoryScope, BufferRecord, BufferRecordKind, BufferRecordState, BufferViewRecord, + FloatingRecord, NodeRecord, NodeRecordKind, SessionRecord, SessionSnapshot, SplitRecord, + TabRecord, TabsRecord, VisibleSnapshotResponse, }; pub const SESSION_ID: SessionId = SessionId(1); @@ -317,7 +317,7 @@ fn buffer( attachment_node_id, read_only: false, helper_source_buffer_id: None, - helper_scope: None, + helper_scope: None::, pty_size: PtySize::new(80, 24), activity, last_snapshot_seq: 0, diff --git a/crates/embers-server/src/server.rs b/crates/embers-server/src/server.rs index ea74fcdf..dc474f1e 100644 --- a/crates/embers-server/src/server.rs +++ b/crates/embers-server/src/server.rs @@ -1510,21 +1510,113 @@ impl Runtime { } layout_snapshot_response(&state, request_id, session_id) } - embers_protocol::NodeRequest::Zoom { request_id, .. } - | embers_protocol::NodeRequest::Unzoom { request_id, .. } - | embers_protocol::NodeRequest::ToggleZoom { request_id, .. } - | embers_protocol::NodeRequest::SwapSiblings { request_id, .. } - | embers_protocol::NodeRequest::BreakNode { request_id, .. } - | embers_protocol::NodeRequest::JoinBufferAtNode { request_id, .. } - | embers_protocol::NodeRequest::MoveNodeBefore { request_id, .. } - | embers_protocol::NodeRequest::MoveNodeAfter { request_id, .. } => ( - error_response( - Some(request_id), - ErrorCode::Unsupported, - "node ergonomics commands are not implemented yet", - ), - Vec::new(), - ), + embers_protocol::NodeRequest::Zoom { + request_id, + node_id, + } => { + let session_id = match state.node(node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.zoom_node(node_id) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + embers_protocol::NodeRequest::Unzoom { + request_id, + session_id, + } => match state.unzoom_session(session_id) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + }, + embers_protocol::NodeRequest::ToggleZoom { + request_id, + node_id, + } => { + let session_id = match state.node(node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.toggle_zoom_node(node_id) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + embers_protocol::NodeRequest::SwapSiblings { + request_id, + first_node_id, + second_node_id, + } => { + let session_id = match state.node(first_node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.swap_sibling_nodes(first_node_id, second_node_id) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + embers_protocol::NodeRequest::BreakNode { + request_id, + node_id, + destination, + } => { + let session_id = match state.node(node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.break_node( + node_id, + matches!(destination, embers_protocol::NodeBreakDestination::Floating), + ) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + embers_protocol::NodeRequest::JoinBufferAtNode { + request_id, + node_id, + buffer_id, + placement, + } => { + let session_id = match state.node(node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.join_buffer_at_node(node_id, buffer_id, placement) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + embers_protocol::NodeRequest::MoveNodeBefore { + request_id, + node_id, + sibling_node_id, + } => { + let session_id = match state.node(node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.move_node_before(node_id, sibling_node_id) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } + embers_protocol::NodeRequest::MoveNodeAfter { + request_id, + node_id, + sibling_node_id, + } => { + let session_id = match state.node(node_id) { + Ok(node) => node.session_id(), + Err(error) => return (mux_error_response(Some(request_id), error), Vec::new()), + }; + match state.move_node_after(node_id, sibling_node_id) { + Ok(()) => layout_snapshot_response(&state, request_id, session_id), + Err(error) => (mux_error_response(Some(request_id), error), Vec::new()), + } + } } } diff --git a/crates/embers-server/src/state.rs b/crates/embers-server/src/state.rs index 4581d39e..1a3dc947 100644 --- a/crates/embers-server/src/state.rs +++ b/crates/embers-server/src/state.rs @@ -5,6 +5,7 @@ use embers_core::{ ActivityState, BufferId, FloatGeometry, FloatingId, IdAllocator, MuxError, NodeId, PtySize, Result, SessionId, SplitDirection, Timestamp, }; +use embers_protocol::NodeJoinPlacement; use crate::model::{ Buffer, BufferAttachment, BufferKind, BufferState, BufferViewNode, BufferViewState, @@ -1236,6 +1237,214 @@ impl ServerState { self.focus_leaf(target_session, target_leaf) } + pub fn zoom_node(&mut self, node_id: NodeId) -> Result<()> { + let session_id = self.node_session_id(node_id)?; + self.session_mut(session_id)?.zoomed_node = Some(node_id); + Ok(()) + } + + pub fn unzoom_session(&mut self, session_id: SessionId) -> Result<()> { + self.session_mut(session_id)?.zoomed_node = None; + Ok(()) + } + + pub fn toggle_zoom_node(&mut self, node_id: NodeId) -> Result<()> { + let session_id = self.node_session_id(node_id)?; + let next = if self.session(session_id)?.zoomed_node == Some(node_id) { + None + } else { + Some(node_id) + }; + self.session_mut(session_id)?.zoomed_node = next; + Ok(()) + } + + pub fn swap_sibling_nodes( + &mut self, + first_node_id: NodeId, + second_node_id: NodeId, + ) -> Result<()> { + if first_node_id == second_node_id { + return Ok(()); + } + let parent_id = self.shared_parent(first_node_id, second_node_id)?; + match self.node_mut(parent_id)? { + Node::Split(split) => { + let first = split + .children + .iter() + .position(|child| *child == first_node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {first_node_id} is not a child of split {parent_id}" + )) + })?; + let second = split + .children + .iter() + .position(|child| *child == second_node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {second_node_id} is not a child of split {parent_id}" + )) + })?; + split.children.swap(first, second); + split.sizes.swap(first, second); + } + Node::Tabs(tabs) => { + let first = tabs + .tabs + .iter() + .position(|tab| tab.child == first_node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {first_node_id} is not a child of tabs {parent_id}" + )) + })?; + let second = tabs + .tabs + .iter() + .position(|tab| tab.child == second_node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {second_node_id} is not a child of tabs {parent_id}" + )) + })?; + tabs.tabs.swap(first, second); + match tabs.active { + active if active == first => tabs.active = second, + active if active == second => tabs.active = first, + _ => {} + } + } + Node::BufferView(_) => { + return Err(MuxError::invalid_input( + "buffer views do not have sibling children", + )); + } + } + Ok(()) + } + + pub fn move_node_before(&mut self, node_id: NodeId, sibling_node_id: NodeId) -> Result<()> { + self.reorder_sibling_node(node_id, sibling_node_id, true) + } + + pub fn move_node_after(&mut self, node_id: NodeId, sibling_node_id: NodeId) -> Result<()> { + self.reorder_sibling_node(node_id, sibling_node_id, false) + } + + pub fn break_node(&mut self, node_id: NodeId, to_floating: bool) -> Result<()> { + let session_id = self.node_session_id(node_id)?; + let title = self.default_tab_title(node_id)?; + let (old_parent, _) = self.detach_node_from_owner(node_id)?; + + if to_floating { + self.create_floating_window_with_options( + session_id, + node_id, + FloatGeometry::new(10, 3, 100, 26), + Some(title), + true, + true, + )?; + } else { + let tabs_id = self + .nearest_tabs_ancestor(old_parent)? + .unwrap_or(self.ensure_root_tabs_container(session_id)?); + self.add_tab_sibling(tabs_id, title, node_id)?; + } + + if let Some(parent_id) = old_parent { + self.normalize_upwards(parent_id)?; + } + self.normalize_zoomed_node(session_id)?; + Ok(()) + } + + pub fn join_buffer_at_node( + &mut self, + node_id: NodeId, + buffer_id: BufferId, + placement: NodeJoinPlacement, + ) -> Result<()> { + let target_session = self.node_session_id(node_id)?; + if let BufferAttachment::Attached(source_view) = self.buffer(buffer_id)?.attachment + && source_view != node_id + { + self.close_node(source_view)?; + } + + let new_view = self.create_buffer_view(target_session, buffer_id)?; + let result = match placement { + NodeJoinPlacement::Left => self + .wrap_node_in_split(node_id, SplitDirection::Vertical, new_view, true) + .map(|_| ()), + NodeJoinPlacement::Right => self + .wrap_node_in_split(node_id, SplitDirection::Vertical, new_view, false) + .map(|_| ()), + NodeJoinPlacement::Up => self + .wrap_node_in_split(node_id, SplitDirection::Horizontal, new_view, true) + .map(|_| ()), + NodeJoinPlacement::Down => self + .wrap_node_in_split(node_id, SplitDirection::Horizontal, new_view, false) + .map(|_| ()), + NodeJoinPlacement::TabBefore | NodeJoinPlacement::TabAfter => { + let title = self.buffer(buffer_id)?.title.clone(); + let tabs_id = if matches!(self.node(node_id)?, Node::Tabs(_)) { + node_id + } else if matches!( + self.node_parent(node_id)? + .map(|id| self.node(id)) + .transpose()?, + Some(Node::Tabs(_)) + ) { + self.node_parent(node_id)?.expect("checked parent exists") + } else { + self.wrap_node_in_tabs(node_id, self.default_tab_title(node_id)?)? + }; + let insert_index = { + let tabs = match self.node(tabs_id)? { + Node::Tabs(tabs) => tabs, + _ => return Err(MuxError::invalid_input("node is not a tabs container")), + }; + if tabs_id == node_id { + let active = tabs.active; + match placement { + NodeJoinPlacement::TabBefore => active, + NodeJoinPlacement::TabAfter => active + 1, + _ => unreachable!(), + } + } else { + let current = tabs + .tabs + .iter() + .position(|tab| tab.child == node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {node_id} is not a child of tabs {tabs_id}" + )) + })?; + match placement { + NodeJoinPlacement::TabBefore => current, + NodeJoinPlacement::TabAfter => current + 1, + _ => unreachable!(), + } + } + }; + self.add_tab_sibling_at(tabs_id, insert_index, title, new_view) + .map(|_| ()) + } + }; + + if let Err(error) = result { + self.discard_buffer_view(new_view); + return Err(error); + } + self.normalize_zoomed_node(target_session)?; + Ok(()) + } + pub fn detach_buffer(&mut self, buffer_id: BufferId) -> Result<()> { match self.buffer(buffer_id)?.attachment { BufferAttachment::Attached(node_id) => self.close_node(node_id), @@ -1363,6 +1572,7 @@ impl ServerState { ))); } + self.normalize_zoomed_node(session_id)?; self.heal_focus(session_id) } @@ -1395,6 +1605,7 @@ impl ServerState { } else { self.heal_focus(session_id)?; } + self.normalize_zoomed_node(session_id)?; Ok(()) } @@ -1462,6 +1673,20 @@ impl ServerState { ))); } } + + if let Some(zoomed_node) = session.zoomed_node { + if !self.nodes.contains_key(&zoomed_node) { + return Err(MuxError::conflict(format!( + "zoomed node {zoomed_node} is missing from session {}", + session.id + ))); + } + if self.node(zoomed_node)?.session_id() != session.id { + return Err(MuxError::conflict(format!( + "zoomed node {zoomed_node} belongs to the wrong session" + ))); + } + } } if seen.len() != self.nodes.len() { @@ -1518,6 +1743,7 @@ impl ServerState { }), ); self.session_mut(session_id)?.root_node = new_root; + self.session_mut(session_id)?.zoomed_node = None; self.heal_focus(session_id) } @@ -1682,6 +1908,151 @@ impl ServerState { self.ensure_leaf(node_id) } + fn shared_parent(&self, first_node_id: NodeId, second_node_id: NodeId) -> Result { + if first_node_id == second_node_id { + return Err(MuxError::invalid_input( + "sibling operations require two distinct nodes", + )); + } + let first_parent = self.node_parent(first_node_id)?.ok_or_else(|| { + MuxError::invalid_input(format!("node {first_node_id} has no parent")) + })?; + let second_parent = self.node_parent(second_node_id)?.ok_or_else(|| { + MuxError::invalid_input(format!("node {second_node_id} has no parent")) + })?; + if first_parent != second_parent { + return Err(MuxError::conflict( + "node ergonomics are restricted to siblings with the same parent".to_owned(), + )); + } + Ok(first_parent) + } + + fn reorder_sibling_node( + &mut self, + node_id: NodeId, + sibling_node_id: NodeId, + before: bool, + ) -> Result<()> { + if node_id == sibling_node_id { + return Ok(()); + } + let parent_id = self.shared_parent(node_id, sibling_node_id)?; + match self.node_mut(parent_id)? { + Node::Split(split) => { + let from = split + .children + .iter() + .position(|child| *child == node_id) + .ok_or_else(|| { + MuxError::not_found(format!("node {node_id} is not in split {parent_id}")) + })?; + let target = split + .children + .iter() + .position(|child| *child == sibling_node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {sibling_node_id} is not in split {parent_id}" + )) + })?; + let child = split.children.remove(from); + let size = split.sizes.remove(from); + let mut insert_at = target; + if from < target { + insert_at = insert_at.saturating_sub(1); + } + if !before { + insert_at = insert_at.saturating_add(1); + } + split.children.insert(insert_at, child); + split.sizes.insert(insert_at, size); + } + Node::Tabs(tabs) => { + let from = tabs + .tabs + .iter() + .position(|tab| tab.child == node_id) + .ok_or_else(|| { + MuxError::not_found(format!("node {node_id} is not in tabs {parent_id}")) + })?; + let target = tabs + .tabs + .iter() + .position(|tab| tab.child == sibling_node_id) + .ok_or_else(|| { + MuxError::not_found(format!( + "node {sibling_node_id} is not in tabs {parent_id}" + )) + })?; + let tab = tabs.tabs.remove(from); + let mut insert_at = target; + if from < target { + insert_at = insert_at.saturating_sub(1); + } + if !before { + insert_at = insert_at.saturating_add(1); + } + tabs.tabs.insert(insert_at, tab); + if tabs.active == from { + tabs.active = insert_at; + } else if from < tabs.active && insert_at >= tabs.active { + tabs.active = tabs.active.saturating_sub(1); + } else if from > tabs.active && insert_at <= tabs.active { + tabs.active = tabs.active.saturating_add(1); + } + } + Node::BufferView(_) => { + return Err(MuxError::invalid_input( + "buffer views do not have sibling children", + )); + } + } + Ok(()) + } + + fn detach_node_from_owner( + &mut self, + node_id: NodeId, + ) -> Result<(Option, Option)> { + if self.is_session_root(node_id) { + return Err(MuxError::conflict( + "session root cannot be broken out of its owner".to_owned(), + )); + } + if let Some(parent_id) = self.node_parent(node_id)? { + self.remove_child(parent_id, node_id)?; + return Ok((Some(parent_id), None)); + } + if let Some(floating_id) = self.floating_id_by_root(node_id) { + let _ = self.remove_floating_window(floating_id)?; + return Ok((None, Some(floating_id))); + } + Err(MuxError::invalid_input(format!( + "node {node_id} has no owning container" + ))) + } + + fn nearest_tabs_ancestor(&self, mut node_id: Option) -> Result> { + while let Some(current) = node_id { + if matches!(self.node(current)?, Node::Tabs(_)) { + return Ok(Some(current)); + } + node_id = self.node_parent(current)?; + } + Ok(None) + } + + fn normalize_zoomed_node(&mut self, session_id: SessionId) -> Result<()> { + let keep = self.session(session_id)?.zoomed_node.filter(|node_id| { + self.nodes + .get(node_id) + .is_some_and(|node| node.session_id() == session_id) + }); + self.session_mut(session_id)?.zoomed_node = keep; + Ok(()) + } + fn is_session_root(&self, node_id: NodeId) -> bool { self.sessions .values() diff --git a/crates/embers-server/tests/model_state.rs b/crates/embers-server/tests/model_state.rs index 64d1c31e..01058933 100644 --- a/crates/embers-server/tests/model_state.rs +++ b/crates/embers-server/tests/model_state.rs @@ -1,6 +1,7 @@ use std::collections::BTreeSet; use embers_core::{BufferId, FloatGeometry, NodeId, SessionId, SplitDirection}; +use embers_protocol::NodeJoinPlacement; use embers_server::{BufferAttachment, Node, ServerState}; use proptest::prelude::*; @@ -313,6 +314,102 @@ fn public_detach_buffer_closes_live_views() { state.validate().expect("state remains valid"); } +#[test] +fn zoom_toggle_tracks_session_zoomed_node_and_clears_on_close() { + let mut state = ServerState::new(); + let (session_id, _, leaf_id) = seed_single_leaf_session(&mut state, "alpha"); + + state.toggle_zoom_node(leaf_id).expect("zoom leaf"); + assert_eq!( + state.session(session_id).expect("session").zoomed_node, + Some(leaf_id) + ); + + state.close_node(leaf_id).expect("close zoomed leaf"); + assert_eq!( + state.session(session_id).expect("session").zoomed_node, + None + ); + state.validate().expect("state remains valid"); +} + +#[test] +fn swap_and_reorder_operate_only_on_siblings() { + let mut state = ServerState::new(); + let (session_id, _, leaf_id) = seed_single_leaf_session(&mut state, "alpha"); + let second = new_buffer(&mut state, "second"); + let third = new_buffer(&mut state, "third"); + let split_id = state + .split_leaf_with_new_buffer(leaf_id, SplitDirection::Vertical, second) + .expect("split root"); + let _second_leaf = attached_view(&state, second); + let third_leaf = state + .create_buffer_view(session_id, third) + .expect("third leaf"); + state + .wrap_node_in_split(split_id, SplitDirection::Vertical, third_leaf, false) + .expect("wrap split with third leaf"); + + let root = root_tab_child(&state, session_id, 0); + let split = match state.node(root).expect("root split") { + Node::Split(split) => split.clone(), + other => panic!("expected split, got {other:?}"), + }; + let first_child = split.children[0]; + let second_child = split.children[1]; + + state + .swap_sibling_nodes(first_child, second_child) + .expect("swap siblings"); + state + .move_node_before(first_child, second_child) + .expect("move sibling before"); + state.validate().expect("state remains valid"); +} + +#[test] +fn break_node_to_floating_preserves_subtree_and_focuses_popup() { + let mut state = ServerState::new(); + let (session_id, _, leaf_id) = seed_single_leaf_session(&mut state, "alpha"); + let buffer_id = new_buffer(&mut state, "beta"); + state + .split_leaf_with_new_buffer(leaf_id, SplitDirection::Horizontal, buffer_id) + .expect("split root"); + let new_leaf = attached_view(&state, buffer_id); + + state.break_node(new_leaf, true).expect("break to floating"); + + let session = state.session(session_id).expect("session"); + assert_eq!(session.floating.len(), 1); + let floating = state + .floating_window(session.floating[0]) + .expect("floating exists"); + assert_eq!(floating.root_node, new_leaf); + assert_eq!(session.focused_floating, Some(floating.id)); + state.validate().expect("state remains valid"); +} + +#[test] +fn join_buffer_at_node_can_insert_tabs_and_splits() { + let mut state = ServerState::new(); + let (session_id, _, leaf_id) = seed_single_leaf_session(&mut state, "alpha"); + let detached = new_buffer(&mut state, "tools"); + + state + .join_buffer_at_node(leaf_id, detached, NodeJoinPlacement::Right) + .expect("join right"); + let root = root_tab_child(&state, session_id, 0); + assert!(matches!(state.node(root).expect("root"), Node::Split(_))); + + let detached_again = state.create_buffer("logs", vec!["sh".to_owned()], None); + state + .join_buffer_at_node(root, detached_again, NodeJoinPlacement::TabAfter) + .expect("join after as tab"); + let root = session_root(&state, session_id); + assert!(matches!(state.node(root).expect("root"), Node::Tabs(_))); + state.validate().expect("state remains valid"); +} + #[test] fn focused_floating_transfers_back_to_root_when_closed() { let mut state = ServerState::new(); diff --git a/docs/config-api-book/404.html b/docs/config-api-book/404.html index b105977b..9e992e43 100644 --- a/docs/config-api-book/404.html +++ b/docs/config-api-book/404.html @@ -36,7 +36,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/action.html b/docs/config-api-book/action.html index eeecb4ea..9c5bf32e 100644 --- a/docs/config-api-book/action.html +++ b/docs/config-api-book/action.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; @@ -178,6 +178,27 @@

Action

Namespace: global

+

fn break_current_node

+ +
fn break_current_node(_: ActionApi, destination: String) -> Action
+
+
+ +
+ +
+Break the current node into a new tab or floating window. +
+ +
+ +
+ + +
+

fn cancel_search

fn cancel_search(_: ActionApi) -> Action
@@ -730,6 +751,27 @@

fn insert_tab_before_current

+
+ +

fn join_buffer_here

+ +
fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action
+
+
+ +
+ +
+Join a buffer at the current node. +
+ +
+ +
+ +

fn kill_buffer

@@ -851,6 +893,48 @@

fn move_buffer_to_node

+
+ +

fn move_current_node_before

+ +
fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move the current node before a sibling. +
+ +
+ +
+ + +
+ +

fn move_node_after

+ +
fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move a node after a sibling. +
+ +
+ +
+ +

fn next_current_tabs

@@ -935,6 +1019,27 @@

fn notify

+
+ +

fn open_buffer_history

+ +
fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action
+
+
+ +
+ +
+Open the history of a buffer in a new view. +
+ +
+ +
+ +

fn open_floating

@@ -1483,6 +1588,27 @@

fn split_with

+
+ +

fn swap_current_node

+ +
fn swap_current_node(_: ActionApi, second_node_id: int) -> Action
+
+
+ +
+ +
+Swap the current node with a sibling. +
+ +
+ +
+ +

fn toggle_mode

@@ -1504,6 +1630,48 @@

fn toggle_mode

+
+ +

fn toggle_zoom_node

+ +
fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action
+
+
+ +
+ +
+Toggle zoom on a node. +
+ +
+ +
+ + +
+ +

fn unzoom_current_session

+ +
fn unzoom_current_session(_: ActionApi) -> Action
+
+
+ +
+ +
+Unzoom the current session. +
+ +
+ +
+ +

fn yank_selection

@@ -1525,6 +1693,27 @@

fn yank_selection

+
+ +

fn zoom_current_node

+ +
fn zoom_current_node(_: ActionApi) -> Action
+
+
+ +
+ +
+Zoom the current node. +
+ +
+ +
+ + diff --git a/docs/config-api-book/buffer-ref.html b/docs/config-api-book/buffer-ref.html index 407ef6c1..984cc486 100644 --- a/docs/config-api-book/buffer-ref.html +++ b/docs/config-api-book/buffer-ref.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/context.html b/docs/config-api-book/context.html index 1ee9a8fc..c03503a4 100644 --- a/docs/config-api-book/context.html +++ b/docs/config-api-book/context.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/defs/registration.rhai b/docs/config-api-book/defs/registration.rhai index 752c140c..2e3faf94 100644 --- a/docs/config-api-book/defs/registration.rhai +++ b/docs/config-api-book/defs/registration.rhai @@ -82,6 +82,9 @@ fn tabs(_: TreeApi, tabs: array) -> TreeSpec; /// Build a tabs container with an explicit active tab. fn tabs_with_active(_: TreeApi, tabs: array, active: int) -> TreeSpec; +/// Break the current node into a new tab or floating window. +fn break_current_node(_: ActionApi, destination: string) -> Action; + /// Cancel the active search. fn cancel_search(_: ActionApi) -> Action; @@ -166,6 +169,9 @@ fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: string, tree: TreeS /// Insert a tab before the current tab. fn insert_tab_before_current(_: ActionApi, title: string, tree: TreeSpec) -> Action; +/// Join a buffer at the current node. +fn join_buffer_here(_: ActionApi, buffer_id: int, placement: string) -> Action; + /// Kill the currently focused buffer. fn kill_buffer(_: ActionApi) -> Action; @@ -192,6 +198,12 @@ fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: map) -> Action /// Move a buffer into a specific node. fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action; +/// Move the current node before a sibling. +fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action; + +/// Move a node after a sibling. +fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action; + /// Select the next tab in the currently focused tabs node. fn next_current_tabs(_: ActionApi) -> Action; @@ -204,6 +216,9 @@ fn noop(_: ActionApi) -> Action; /// Emit a client notification. fn notify(_: ActionApi, level: string, message: string) -> Action; +/// Open the history of a buffer in a new view. +fn open_buffer_history(_: ActionApi, buffer_id: int, scope: string, placement: string) -> Action; + /// Open a floating view around the provided tree. fn open_floating(_: ActionApi, tree: TreeSpec, options: map) -> Action; @@ -297,12 +312,24 @@ fn send_keys_current(_: ActionApi, notation: string) -> Action; /// Split the current node and attach the provided tree as the new sibling. fn split_with(_: ActionApi, direction: string, tree: TreeSpec) -> Action; +/// Swap the current node with a sibling. +fn swap_current_node(_: ActionApi, second_node_id: int) -> Action; + /// Toggle a named input mode. fn toggle_mode(_: ActionApi, mode: string) -> Action; +/// Toggle zoom on a node. +fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action; + +/// Unzoom the current session. +fn unzoom_current_session(_: ActionApi) -> Action; + /// Copy the current selection into the clipboard. fn yank_selection(_: ActionApi) -> Action; +/// Zoom the current node. +fn zoom_current_node(_: ActionApi) -> Action; + /// Toggle focus-on-click behavior. /// /// # rhai-autodocs:index:22 diff --git a/docs/config-api-book/defs/runtime.rhai b/docs/config-api-book/defs/runtime.rhai index ca8da201..65a0985a 100644 --- a/docs/config-api-book/defs/runtime.rhai +++ b/docs/config-api-book/defs/runtime.rhai @@ -131,6 +131,9 @@ fn tabs(_: TreeApi, tabs: array) -> TreeSpec; /// Build a tabs container with an explicit active tab. fn tabs_with_active(_: TreeApi, tabs: array, active: int) -> TreeSpec; +/// Break the current node into a new tab or floating window. +fn break_current_node(_: ActionApi, destination: string) -> Action; + /// Cancel the active search. fn cancel_search(_: ActionApi) -> Action; @@ -215,6 +218,9 @@ fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: string, tree: TreeS /// Insert a tab before the current tab. fn insert_tab_before_current(_: ActionApi, title: string, tree: TreeSpec) -> Action; +/// Join a buffer at the current node. +fn join_buffer_here(_: ActionApi, buffer_id: int, placement: string) -> Action; + /// Kill the currently focused buffer. fn kill_buffer(_: ActionApi) -> Action; @@ -241,6 +247,12 @@ fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: map) -> Action /// Move a buffer into a specific node. fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action; +/// Move the current node before a sibling. +fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action; + +/// Move a node after a sibling. +fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action; + /// Select the next tab in the currently focused tabs node. fn next_current_tabs(_: ActionApi) -> Action; @@ -253,6 +265,9 @@ fn noop(_: ActionApi) -> Action; /// Emit a client notification. fn notify(_: ActionApi, level: string, message: string) -> Action; +/// Open the history of a buffer in a new view. +fn open_buffer_history(_: ActionApi, buffer_id: int, scope: string, placement: string) -> Action; + /// Open a floating view around the provided tree. fn open_floating(_: ActionApi, tree: TreeSpec, options: map) -> Action; @@ -346,12 +361,24 @@ fn send_keys_current(_: ActionApi, notation: string) -> Action; /// Split the current node and attach the provided tree as the new sibling. fn split_with(_: ActionApi, direction: string, tree: TreeSpec) -> Action; +/// Swap the current node with a sibling. +fn swap_current_node(_: ActionApi, second_node_id: int) -> Action; + /// Toggle a named input mode. fn toggle_mode(_: ActionApi, mode: string) -> Action; +/// Toggle zoom on a node. +fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action; + +/// Unzoom the current session. +fn unzoom_current_session(_: ActionApi) -> Action; + /// Copy the current selection into the clipboard. fn yank_selection(_: ActionApi) -> Action; +/// Zoom the current node. +fn zoom_current_node(_: ActionApi) -> Action; + /// Return the active tab index. fn active_index(bar: TabBarContext) -> int; diff --git a/docs/config-api-book/event-info.html b/docs/config-api-book/event-info.html index 0f3cd3d4..8f8a19d4 100644 --- a/docs/config-api-book/event-info.html +++ b/docs/config-api-book/event-info.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/example.html b/docs/config-api-book/example.html index 36c442aa..4960d69d 100644 --- a/docs/config-api-book/example.html +++ b/docs/config-api-book/example.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/floating-ref.html b/docs/config-api-book/floating-ref.html index 5fb8fd09..52897b4d 100644 --- a/docs/config-api-book/floating-ref.html +++ b/docs/config-api-book/floating-ref.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/index.html b/docs/config-api-book/index.html index 241c2b32..b5676bdc 100644 --- a/docs/config-api-book/index.html +++ b/docs/config-api-book/index.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/mouse.html b/docs/config-api-book/mouse.html index 22fc3e5b..cc7c74ca 100644 --- a/docs/config-api-book/mouse.html +++ b/docs/config-api-book/mouse.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/mux.html b/docs/config-api-book/mux.html index 3cb17e04..06fd7ab6 100644 --- a/docs/config-api-book/mux.html +++ b/docs/config-api-book/mux.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/node-ref.html b/docs/config-api-book/node-ref.html index f9c5ef08..3ce98569 100644 --- a/docs/config-api-book/node-ref.html +++ b/docs/config-api-book/node-ref.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/print.html b/docs/config-api-book/print.html index a445bd08..011eae24 100644 --- a/docs/config-api-book/print.html +++ b/docs/config-api-book/print.html @@ -36,7 +36,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; @@ -412,6 +412,27 @@

Actio

Namespace: global

+

fn break_current_node

+ +
fn break_current_node(_: ActionApi, destination: String) -> Action
+
+
+ +
+ +
+Break the current node into a new tab or floating window. +
+ +
+ +
+ + +
+

fn cancel_search

fn cancel_search(_: ActionApi) -> Action
@@ -964,6 +985,27 @@

fn insert_tab_before_current

+
+ +

fn join_buffer_here

+ +
fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action
+
+
+ +
+ +
+Join a buffer at the current node. +
+ +
+ +
+ +

fn kill_buffer

@@ -1085,6 +1127,48 @@

fn move_buffer_to_node

+
+ +

fn move_current_node_before

+ +
fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move the current node before a sibling. +
+ +
+ +
+ + +
+ +

fn move_node_after

+ +
fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move a node after a sibling. +
+ +
+ +
+ +

fn next_current_tabs

@@ -1169,6 +1253,27 @@

fn notify

+
+ +

fn open_buffer_history

+ +
fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action
+
+
+ +
+ +
+Open the history of a buffer in a new view. +
+ +
+ +
+ +

fn open_floating

@@ -1717,6 +1822,27 @@

fn split_with

+
+ +

fn swap_current_node

+ +
fn swap_current_node(_: ActionApi, second_node_id: int) -> Action
+
+
+ +
+ +
+Swap the current node with a sibling. +
+ +
+ +
+ +

fn toggle_mode

@@ -1738,6 +1864,48 @@

fn toggle_mode

+
+ +

fn toggle_zoom_node

+ +
fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action
+
+
+ +
+ +
+Toggle zoom on a node. +
+ +
+ +
+ + +
+ +

fn unzoom_current_session

+ +
fn unzoom_current_session(_: ActionApi) -> Action
+
+
+ +
+ +
+Unzoom the current session. +
+ +
+ +
+ +

fn yank_selection

@@ -1759,6 +1927,27 @@

fn yank_selection

+
+ +

fn zoom_current_node

+ +
fn zoom_current_node(_: ActionApi) -> Action
+
+
+ +
+ +
+Zoom the current node. +
+ +
+ +
+ +

Tree (Registration)

Namespace: global

@@ -2282,6 +2471,27 @@

Action

Namespace: global

+

fn break_current_node

+ +
fn break_current_node(_: ActionApi, destination: String) -> Action
+
+
+ +
+ +
+Break the current node into a new tab or floating window. +
+ +
+ +
+ + +
+

fn cancel_search

fn cancel_search(_: ActionApi) -> Action
@@ -2834,6 +3044,27 @@

fn insert_tab_before_current

+
+ +

fn join_buffer_here

+ +
fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action
+
+
+ +
+ +
+Join a buffer at the current node. +
+ +
+ +
+ +

fn kill_buffer

@@ -2955,6 +3186,48 @@

fn move_buffer_to_node

+
+ +

fn move_current_node_before

+ +
fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move the current node before a sibling. +
+ +
+ +
+ + +
+ +

fn move_node_after

+ +
fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move a node after a sibling. +
+ +
+ +
+ +

fn next_current_tabs

@@ -3039,6 +3312,27 @@

fn notify

+
+ +

fn open_buffer_history

+ +
fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action
+
+
+ +
+ +
+Open the history of a buffer in a new view. +
+ +
+ +
+ +

fn open_floating

@@ -3587,6 +3881,27 @@

fn split_with

+
+ +

fn swap_current_node

+ +
fn swap_current_node(_: ActionApi, second_node_id: int) -> Action
+
+
+ +
+ +
+Swap the current node with a sibling. +
+ +
+ +
+ +

fn toggle_mode

@@ -3608,6 +3923,48 @@

fn toggle_mode

+
+ +

fn toggle_zoom_node

+ +
fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action
+
+
+ +
+ +
+Toggle zoom on a node. +
+ +
+ +
+ + +
+ +

fn unzoom_current_session

+ +
fn unzoom_current_session(_: ActionApi) -> Action
+
+
+ +
+ +
+Unzoom the current session. +
+ +
+ +
+ +

fn yank_selection

@@ -3629,6 +3986,27 @@

fn yank_selection

+
+ +

fn zoom_current_node

+ +
fn zoom_current_node(_: ActionApi) -> Action
+
+
+ +
+ +
+Zoom the current node. +
+ +
+ +
+ +

Tree

Namespace: global

diff --git a/docs/config-api-book/registration-action.html b/docs/config-api-book/registration-action.html index 9964117a..b3cb17de 100644 --- a/docs/config-api-book/registration-action.html +++ b/docs/config-api-book/registration-action.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; @@ -178,6 +178,27 @@

Actio

Namespace: global

+

fn break_current_node

+ +
fn break_current_node(_: ActionApi, destination: String) -> Action
+
+
+ +
+ +
+Break the current node into a new tab or floating window. +
+ +
+ +
+ + +
+

fn cancel_search

fn cancel_search(_: ActionApi) -> Action
@@ -730,6 +751,27 @@

fn insert_tab_before_current

+
+ +

fn join_buffer_here

+ +
fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action
+
+
+ +
+ +
+Join a buffer at the current node. +
+ +
+ +
+ +

fn kill_buffer

@@ -851,6 +893,48 @@

fn move_buffer_to_node

+
+ +

fn move_current_node_before

+ +
fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move the current node before a sibling. +
+ +
+ +
+ + +
+ +

fn move_node_after

+ +
fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action
+
+
+ +
+ +
+Move a node after a sibling. +
+ +
+ +
+ +

fn next_current_tabs

@@ -935,6 +1019,27 @@

fn notify

+
+ +

fn open_buffer_history

+ +
fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action
+
+
+ +
+ +
+Open the history of a buffer in a new view. +
+ +
+ +
+ +

fn open_floating

@@ -1483,6 +1588,27 @@

fn split_with

+
+ +

fn swap_current_node

+ +
fn swap_current_node(_: ActionApi, second_node_id: int) -> Action
+
+
+ +
+ +
+Swap the current node with a sibling. +
+ +
+ +
+ +

fn toggle_mode

@@ -1504,6 +1630,48 @@

fn toggle_mode

+
+ +

fn toggle_zoom_node

+ +
fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action
+
+
+ +
+ +
+Toggle zoom on a node. +
+ +
+ +
+ + +
+ +

fn unzoom_current_session

+ +
fn unzoom_current_session(_: ActionApi) -> Action
+
+
+ +
+ +
+Unzoom the current session. +
+ +
+ +
+ +

fn yank_selection

@@ -1525,6 +1693,27 @@

fn yank_selection

+
+ +

fn zoom_current_node

+ +
fn zoom_current_node(_: ActionApi) -> Action
+
+
+ +
+ +
+Zoom the current node. +
+ +
+ +
+ + diff --git a/docs/config-api-book/registration-globals.html b/docs/config-api-book/registration-globals.html index 04c20807..7418635d 100644 --- a/docs/config-api-book/registration-globals.html +++ b/docs/config-api-book/registration-globals.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/registration-system.html b/docs/config-api-book/registration-system.html index c439a4cf..b4432978 100644 --- a/docs/config-api-book/registration-system.html +++ b/docs/config-api-book/registration-system.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/registration-tree.html b/docs/config-api-book/registration-tree.html index b7d47267..fdd73ee7 100644 --- a/docs/config-api-book/registration-tree.html +++ b/docs/config-api-book/registration-tree.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/registration-ui.html b/docs/config-api-book/registration-ui.html index d2e0b04c..8b9c0354 100644 --- a/docs/config-api-book/registration-ui.html +++ b/docs/config-api-book/registration-ui.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/runtime-theme.html b/docs/config-api-book/runtime-theme.html index dc17ddc0..0b09e49b 100644 --- a/docs/config-api-book/runtime-theme.html +++ b/docs/config-api-book/runtime-theme.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/searcher-c2a407aa.js b/docs/config-api-book/searcher-c2a407aa.js index db84c4f1..9d5ab5e7 100644 --- a/docs/config-api-book/searcher-c2a407aa.js +++ b/docs/config-api-book/searcher-c2a407aa.js @@ -437,7 +437,7 @@ window.search = window.search || {}; if (yes) { loadSearchScript( window.path_to_searchindex_js || - path_to_root + 'searchindex-256e957a.js', + path_to_root + 'searchindex-6f9ff0e9.js', 'mdbook-search-index'); search_wrap.classList.remove('hidden'); searchicon.setAttribute('aria-expanded', 'true'); diff --git a/docs/config-api-book/searchindex-256e957a.js b/docs/config-api-book/searchindex-256e957a.js deleted file mode 100644 index 70994c4e..00000000 --- a/docs/config-api-book/searchindex-256e957a.js +++ /dev/null @@ -1 +0,0 @@ -window.search = Object.assign(window.search, JSON.parse('{"doc_urls":["index.html#embers-config-api","index.html#pages","index.html#definitions","index.html#example","example.html#example","registration-globals.html#registration-globals","registration-action.html#action-registration","registration-tree.html#tree-registration","registration-system.html#system-registration","registration-ui.html#ui-registration","mouse.html#mouse","theme.html#theme","tabbar.html#tabbar","action.html#action","tree.html#tree","context.html#context","mux.html#mux","event-info.html#eventinfo","session-ref.html#sessionref","buffer-ref.html#bufferref","node-ref.html#noderef","floating-ref.html#floatingref","tab-bar-context.html#tabbarcontext","tab-info.html#tabinfo","system-runtime.html#system","ui.html#ui","runtime-theme.html#runtime-theme"],"index":{"documentStore":{"docInfo":{"0":{"body":41,"breadcrumbs":4,"title":3},"1":{"body":37,"breadcrumbs":2,"title":1},"10":{"body":55,"breadcrumbs":6,"title":1},"11":{"body":15,"breadcrumbs":3,"title":1},"12":{"body":16,"breadcrumbs":3,"title":1},"13":{"body":918,"breadcrumbs":65,"title":1},"14":{"body":202,"breadcrumbs":14,"title":1},"15":{"body":165,"breadcrumbs":14,"title":1},"16":{"body":136,"breadcrumbs":12,"title":1},"17":{"body":91,"breadcrumbs":9,"title":1},"18":{"body":48,"breadcrumbs":6,"title":1},"19":{"body":230,"breadcrumbs":20,"title":1},"2":{"body":2,"breadcrumbs":2,"title":1},"20":{"body":178,"breadcrumbs":17,"title":1},"21":{"body":78,"breadcrumbs":9,"title":1},"22":{"body":75,"breadcrumbs":8,"title":1},"23":{"body":70,"breadcrumbs":8,"title":1},"24":{"body":41,"breadcrumbs":5,"title":1},"25":{"body":61,"breadcrumbs":4,"title":1},"26":{"body":19,"breadcrumbs":6,"title":2},"3":{"body":1,"breadcrumbs":2,"title":1},"4":{"body":50,"breadcrumbs":2,"title":1},"5":{"body":136,"breadcrumbs":16,"title":2},"6":{"body":918,"breadcrumbs":130,"title":2},"7":{"body":202,"breadcrumbs":28,"title":2},"8":{"body":41,"breadcrumbs":10,"title":2},"9":{"body":61,"breadcrumbs":8,"title":2}},"docs":{"0":{"body":"This reference is generated from the Rust-backed Rhai exports used by Embers. There are two execution phases: registration time: the top-level config file where you declare modes, bindings, named actions, and visual settings runtime: named actions, event handlers, and tab bar formatters that run against live client state Definition files live in defs/.","breadcrumbs":"Overview » Embers Config API","id":"0","title":"Embers Config API"},"1":{"body":"action buffer-ref context event-info floating-ref mouse mux node-ref registration-action registration-globals registration-system registration-tree registration-ui runtime-theme session-ref system-runtime tab-bar-context tab-info tabbar theme tree ui","breadcrumbs":"Overview » Pages","id":"1","title":"Pages"},"10":{"body":"Namespace: global fn set_click_focus fn set_click_focus(mouse: MouseApi, value: bool) Description Toggle focus-on-click behavior. fn set_click_forward fn set_click_forward(mouse: MouseApi, value: bool) Description Toggle forwarding mouse clicks into the focused buffer. fn set_wheel_forward fn set_wheel_forward(mouse: MouseApi, value: bool) Description Toggle wheel event forwarding into the focused buffer. fn set_wheel_scroll fn set_wheel_scroll(mouse: MouseApi, value: bool) Description Toggle client-side wheel scrolling.","breadcrumbs":"Mouse » Mouse » Mouse » Mouse » Mouse » Mouse","id":"10","title":"Mouse"},"11":{"body":"Namespace: global fn set_palette fn set_palette(theme: ThemeApi, palette: Map) Description Add named colors to the theme palette.","breadcrumbs":"Theme » Theme » Theme","id":"11","title":"Theme"},"12":{"body":"Namespace: global fn set_formatter fn set_formatter(tabbar: TabbarApi, callback: FnPtr) Description Register the function used to format the tab bar.","breadcrumbs":"Tabbar » Tabbar » Tabbar","id":"12","title":"Tabbar"},"13":{"body":"Namespace: global fn cancel_search fn cancel_search(_: ActionApi) -> Action Description Cancel the active search. fn cancel_selection fn cancel_selection(_: ActionApi) -> Action Description Cancel the current selection. fn chain fn chain(_: ActionApi, actions: Array) -> Action Description Chain multiple actions into one composite action. fn clear_pending_keys fn clear_pending_keys(_: ActionApi) -> Action Description Clear any partially-entered key sequence. fn close_floating fn close_floating(_: ActionApi) -> Action Description Close the currently focused floating window. fn close_floating_id fn close_floating_id(_: ActionApi, floating_id: int) -> Action Description Close a floating window by id. fn close_node fn close_node(_: ActionApi, node_id: int) -> Action Description Close a view by node id. fn close_view fn close_view(_: ActionApi) -> Action Description Close the currently focused view. fn copy_selection fn copy_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard. fn detach_buffer fn detach_buffer(_: ActionApi) -> Action Description Detach the currently focused buffer. fn detach_buffer_id fn detach_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Detach a buffer by id. fn enter_mode fn enter_mode(_: ActionApi, mode: String) -> Action Description Enter a specific input mode by name. fn enter_search_mode fn enter_search_mode(_: ActionApi) -> Action Description Enter incremental search mode. fn enter_select_block fn enter_select_block(_: ActionApi) -> Action Description Enter block selection mode. fn enter_select_char fn enter_select_char(_: ActionApi) -> Action Description Enter character selection mode. fn enter_select_line fn enter_select_line(_: ActionApi) -> Action Description Enter line selection mode. fn focus_buffer fn focus_buffer(_: ActionApi, buffer_id: int) -> Action Description Focus a specific buffer by id. fn focus_down fn focus_down(_: ActionApi) -> Action Description Focus the view below the current node. fn focus_left fn focus_left(_: ActionApi) -> Action Description Example Focus the view to the left of the current node. action.focus_left() fn focus_right fn focus_right(_: ActionApi) -> Action Description Focus the view to the right of the current node. fn focus_up fn focus_up(_: ActionApi) -> Action Description Focus the view above the current node. fn follow_output fn follow_output(_: ActionApi) -> Action Description Re-enable following live output. fn insert_tab_after fn insert_tab_after(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab after a specific tabs node. fn insert_tab_after_current fn insert_tab_after_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab after the current tab in the focused tabs node. fn insert_tab_before fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab before a specific tabs node. fn insert_tab_before_current fn insert_tab_before_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab before the current tab. fn kill_buffer fn kill_buffer(_: ActionApi) -> Action Description Kill the currently focused buffer. fn kill_buffer_id fn kill_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Kill a buffer by id. fn leave_mode fn leave_mode(_: ActionApi) -> Action Description Leave the active input mode. fn move_buffer_to_floating fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: Map) -> Action Description Options Move a buffer into a new floating window. x (i16): horizontal offset from the anchor (default: 0) y (i16): vertical offset from the anchor (default: 0) width (FloatingSize): window width, as a percentage (e.g., 50%) or pixel value (default: 50%) height (FloatingSize): window height, as a percentage or pixel value (default: 50%) anchor (FloatingAnchor): anchor point for positioning, e.g., “top_left”, “center” (default: center) title (Option): window title (default: none) focus (bool): whether to focus the window after creation (default: true) close_on_empty (bool): whether to close the window when its buffer empties (default: true) fn move_buffer_to_node fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action Description Move a buffer into a specific node. fn next_current_tabs fn next_current_tabs(_: ActionApi) -> Action Description Select the next tab in the currently focused tabs node. fn next_tab fn next_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the next tab in a specific tabs node. fn noop fn noop(_: ActionApi) -> Action Description Build a no-op action. fn notify fn notify(_: ActionApi, level: String, message: String) -> Action Description Emit a client notification. fn open_floating fn open_floating(_: ActionApi, tree: TreeSpec, options: Map) -> Action Description Open a floating view around the provided tree. fn prev_current_tabs fn prev_current_tabs(_: ActionApi) -> Action Description Select the previous tab in the currently focused tabs node. fn prev_tab fn prev_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the previous tab in a specific tabs node. fn replace_current_with fn replace_current_with(_: ActionApi, tree: TreeSpec) -> Action Description Replace the focused node with a new tree. fn replace_node fn replace_node(_: ActionApi, node_id: int, tree: TreeSpec) -> Action Description Replace a specific node by id with a new tree. fn reveal_buffer fn reveal_buffer(_: ActionApi, buffer_id: int) -> Action Description Reveal a specific buffer by id. fn run_named_action fn run_named_action(_: ActionApi, name: String) -> Action Description Run another named action by name. fn scroll_line_down fn scroll_line_down(_: ActionApi) -> Action Description Scroll one line downward in local scrollback. fn scroll_line_up fn scroll_line_up(_: ActionApi) -> Action Description Scroll one line upward in local scrollback. fn scroll_page_down fn scroll_page_down(_: ActionApi) -> Action Description Scroll one page downward in local scrollback. fn scroll_page_up fn scroll_page_up(_: ActionApi) -> Action Description Scroll one page upward in local scrollback. fn scroll_to_bottom fn scroll_to_bottom(_: ActionApi) -> Action Description Scroll to the bottom of local scrollback. fn scroll_to_top fn scroll_to_top(_: ActionApi) -> Action Description Scroll to the top of local scrollback. fn search_next fn search_next(_: ActionApi) -> Action Description Jump to the next search match. fn search_prev fn search_prev(_: ActionApi) -> Action Description Jump to the previous search match. fn select_current_tabs fn select_current_tabs(_: ActionApi, index: int) -> Action Description Select a tab by index in the currently focused tabs node. fn select_move_down fn select_move_down(_: ActionApi) -> Action Description Move the active selection down. fn select_move_left fn select_move_left(_: ActionApi) -> Action Description Move the active selection left. fn select_move_right fn select_move_right(_: ActionApi) -> Action Description Move the active selection right. fn select_move_up fn select_move_up(_: ActionApi) -> Action Description Move the active selection up. fn select_tab fn select_tab(_: ActionApi, tabs_node_id: int, index: int) -> Action Description Select a tab by index in a specific tabs node. fn send_bytes fn send_bytes(_: ActionApi, buffer_id: int, bytes: String) -> Action\\nfn send_bytes(_: ActionApi, buffer_id: int, bytes: Array) -> Action Description Send a string of bytes to a specific buffer. fn send_bytes_current fn send_bytes_current(_: ActionApi, bytes: String) -> Action\\nfn send_bytes_current(_: ActionApi, bytes: Array) -> Action Description Send a string of bytes to the focused buffer. fn send_keys fn send_keys(_: ActionApi, buffer_id: int, notation: String) -> Action Description Send a key notation sequence to a specific buffer. fn send_keys_current fn send_keys_current(_: ActionApi, notation: String) -> Action Description Send a key notation sequence to the focused buffer. fn split_with fn split_with(_: ActionApi, direction: String, tree: TreeSpec) -> Action Description Split the current node and attach the provided tree as the new sibling. fn toggle_mode fn toggle_mode(_: ActionApi, mode: String) -> Action Description Toggle a named input mode. fn yank_selection fn yank_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard.","breadcrumbs":"Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action","id":"13","title":"Action"},"14":{"body":"Namespace: global fn buffer_attach fn buffer_attach(_: TreeApi, buffer_id: int) -> TreeSpec Description Attach an existing buffer by id. fn buffer_current fn buffer_current(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn buffer_empty fn buffer_empty(_: TreeApi) -> TreeSpec Description Build an empty buffer tree node. fn buffer_spawn fn buffer_spawn(_: TreeApi, command: Array) -> TreeSpec\\nfn buffer_spawn(_: TreeApi, command: Array, options: Map) -> TreeSpec Description Example Spawn a new buffer from a command array. Supported options keys are title ( string), cwd ( string), and env\\n( map). Unknown keys are rejected. tree.buffer_spawn([\\"/bin/zsh\\"], #{ title: \\"shell\\" }) fn current_buffer fn current_buffer(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn current_node fn current_node(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused node. fn split fn split(_: TreeApi, direction: String, children: Array) -> TreeSpec\\nfn split(_: TreeApi, direction: String, children: Array, sizes: Array) -> TreeSpec Description Build a split with an explicit direction string. fn split_h fn split_h(_: TreeApi, children: Array) -> TreeSpec Description Build a horizontal split. fn split_v fn split_v(_: TreeApi, children: Array) -> TreeSpec Description Build a vertical split. fn tab fn tab(_: TreeApi, title: String, tree: TreeSpec) -> TabSpec Description Build a single tab specification. fn tabs fn tabs(_: TreeApi, tabs: Array) -> TreeSpec Description Build a tabs container with the first tab active. fn tabs_with_active fn tabs_with_active(_: TreeApi, tabs: Array, active: int) -> TreeSpec Description Build a tabs container with an explicit active tab.","breadcrumbs":"Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree","id":"14","title":"Tree"},"15":{"body":"Namespace: global fn current_buffer fn current_buffer(context: Context) -> ? Description Example Return the currently focused buffer, if any. ReturnType: BufferRef | () let buffer = ctx.current_buffer();\\nif buffer != () { print(buffer.title());\\n} fn current_floating fn current_floating(context: Context) -> ? Description Return the currently focused floating window, if any. ReturnType: FloatingRef | () fn current_mode fn current_mode(context: Context) -> String Description Return the active input mode name. fn current_node fn current_node(context: Context) -> ? Description Return the currently focused node, if any. ReturnType: NodeRef | () fn current_session fn current_session(context: Context) -> ? Description Return the current session reference, if any. ReturnType: SessionRef | () fn detached_buffers fn detached_buffers(context: Context) -> Array Description Return detached buffers in the current model snapshot. fn event fn event(context: Context) -> ? Description Return the current event payload, if any. ReturnType: EventInfo | () fn find_buffer fn find_buffer(context: Context, buffer_id: int) -> ? Description Find a buffer by numeric id. Returns `()` when it does not exist. ReturnType: BufferRef | () fn find_floating fn find_floating(context: Context, floating_id: int) -> ? Description Find a floating window by numeric id. Returns `()` when it does not exist. ReturnType: FloatingRef | () fn find_node fn find_node(context: Context, node_id: int) -> ? Description Find a node by numeric id. Returns `()` when it does not exist. ReturnType: NodeRef | () fn sessions fn sessions(context: Context) -> Array Description Return every visible session. fn visible_buffers fn visible_buffers(context: Context) -> Array Description Return visible buffers in the current model snapshot.","breadcrumbs":"Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context","id":"15","title":"Context"},"16":{"body":"Namespace: global fn current_buffer fn current_buffer(mux: MuxApi) -> ? Description Return the currently focused buffer, if any. ReturnType: BufferRef | () fn current_floating fn current_floating(mux: MuxApi) -> ? Description Return the currently focused floating window, if any. ReturnType: FloatingRef | () fn current_node fn current_node(mux: MuxApi) -> ? Description Return the currently focused node, if any. ReturnType: NodeRef | () fn current_session fn current_session(mux: MuxApi) -> ? Description Return the current session reference, if any. ReturnType: SessionRef | () fn detached_buffers fn detached_buffers(mux: MuxApi) -> Array Description Return detached buffers in the current model snapshot. fn find_buffer fn find_buffer(mux: MuxApi, buffer_id: int) -> ? Description Find a buffer by numeric id. Returns `()` when it does not exist. ReturnType: BufferRef | () fn find_floating fn find_floating(mux: MuxApi, floating_id: int) -> ? Description Find a floating window by numeric id. Returns `()` when it does not exist. ReturnType: FloatingRef | () fn find_node fn find_node(mux: MuxApi, node_id: int) -> ? Description Find a node by numeric id. Returns `()` when it does not exist. ReturnType: NodeRef | () fn sessions fn sessions(mux: MuxApi) -> Array Description Return every visible session. fn visible_buffers fn visible_buffers(mux: MuxApi) -> Array Description Return visible buffers in the current model snapshot.","breadcrumbs":"Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux","id":"16","title":"Mux"},"17":{"body":"Namespace: global fn buffer_id fn buffer_id(event: EventInfo) -> ? Description Return the buffer id attached to an event, or `()`. ReturnType: int | () fn client_id fn client_id(event: EventInfo) -> ? Description Return the client id attached to an event, or `()`. ReturnType: int | () fn floating_id fn floating_id(event: EventInfo) -> ? Description Return the floating id attached to an event, or `()`. ReturnType: int | () fn name fn name(event: EventInfo) -> String Description Return the event name. fn node_id fn node_id(event: EventInfo) -> ? Description Return the node id attached to an event, or `()`. ReturnType: int | () fn previous_session_id fn previous_session_id(event: EventInfo) -> ? Description Return the previous session id attached to an event, or `()`. ReturnType: int | () fn session_id fn session_id(event: EventInfo) -> ? Description Return the session id attached to an event, or `()`. ReturnType: int | ()","breadcrumbs":"EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo","id":"17","title":"EventInfo"},"18":{"body":"Namespace: global fn floating fn floating(session: SessionRef) -> Array Description Return floating window ids attached to the session. fn id fn id(session: SessionRef) -> int Description Return the numeric session id. fn name fn name(session: SessionRef) -> String Description Return the session name. fn root_node fn root_node(session: SessionRef) -> int Description Return the root tabs node for the session.","breadcrumbs":"SessionRef » SessionRef » SessionRef » SessionRef » SessionRef » SessionRef","id":"18","title":"SessionRef"},"19":{"body":"Namespace: global fn activity fn activity(buffer: BufferRef) -> String Description Return the current activity state name. fn command fn command(buffer: BufferRef) -> Array Description Return the original command vector. fn cwd fn cwd(buffer: BufferRef) -> ? Description Return the working directory, if any. ReturnType: string | () fn env_hint fn env_hint(buffer: BufferRef, key: String) -> ? Description Look up a single environment hint captured on the buffer. ReturnType: string | () fn exit_code fn exit_code(buffer: BufferRef) -> ? Description Return the process exit code, if any. ReturnType: int | () fn history_text fn history_text(buffer: BufferRef) -> String Description Example Return the full captured history text for the buffer. let buffer = ctx.current_buffer();\\nif buffer != () { let history = buffer.history_text();\\n} fn id fn id(buffer: BufferRef) -> int Description Return the numeric buffer id. fn is_attached fn is_attached(buffer: BufferRef) -> bool Description Return whether the buffer is currently attached to a node. fn is_detached fn is_detached(buffer: BufferRef) -> bool Description Return whether the buffer has been detached. fn is_running fn is_running(buffer: BufferRef) -> bool Description Return whether the buffer process is still running. fn is_visible fn is_visible(buffer: BufferRef) -> bool Description Return whether the buffer is visible in the current presentation. fn node_id fn node_id(buffer: BufferRef) -> ? Description Return the attached node id, if any. ReturnType: int | () fn pid fn pid(buffer: BufferRef) -> ? Description Return the process id, if any. ReturnType: int | () fn process_name fn process_name(buffer: BufferRef) -> ? Description Return the detected process name, if any. ReturnType: string | () fn session_id fn session_id(buffer: BufferRef) -> ? Description Return the attached session id, if any. ReturnType: int | () fn snapshot_text fn snapshot_text(buffer: BufferRef, limit: int) -> String Description Return a text snapshot limited to the requested line count. fn title fn title(buffer: BufferRef) -> String Description Return the buffer title. fn tty_path fn tty_path(buffer: BufferRef) -> ? Description Return the controlling TTY path, if any. ReturnType: string | ()","breadcrumbs":"BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef","id":"19","title":"BufferRef"},"2":{"body":"registration.rhai runtime.rhai","breadcrumbs":"Overview » Definitions","id":"2","title":"Definitions"},"20":{"body":"Namespace: global fn active_tab_index fn active_tab_index(node: NodeRef) -> ? Description Return the active tab index, if any. ReturnType: int | () fn buffer fn buffer(node: NodeRef) -> ? Description Return the attached buffer id, if any. ReturnType: int | () fn children fn children(node: NodeRef) -> Array Description Return child node ids. fn geometry fn geometry(node: NodeRef) -> ? Description Return the geometry map, if any. ReturnType: Map | () fn id fn id(node: NodeRef) -> int Description Return the node id. fn is_floating_root fn is_floating_root(node: NodeRef) -> bool Description Return whether the node is the root of a floating window. fn is_focused fn is_focused(node: NodeRef) -> bool Description Return whether the node is focused. fn is_root fn is_root(node: NodeRef) -> bool Description Return whether the node is the session root. fn is_visible fn is_visible(node: NodeRef) -> bool Description Return whether the node is visible in the current presentation. fn kind fn kind(node: NodeRef) -> String Description Return the node kind such as `buffer_view`, `split`, or `tabs`. fn parent fn parent(node: NodeRef) -> ? Description Return the parent node id, if any. ReturnType: int | () fn session_id fn session_id(node: NodeRef) -> int Description Return the owning session id. fn split_direction fn split_direction(node: NodeRef) -> ? Description Return the split direction, if any. ReturnType: string | () fn split_weights fn split_weights(node: NodeRef) -> ? Description Return split weights, if any. ReturnType: Array | () fn tab_titles fn tab_titles(node: NodeRef) -> Array Description Return tab titles on a tabs node.","breadcrumbs":"NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef","id":"20","title":"NodeRef"},"21":{"body":"Namespace: global fn geometry fn geometry(floating: FloatingRef) -> Map Description Return the floating geometry map. fn id fn id(floating: FloatingRef) -> int Description Return the floating id. fn is_focused fn is_focused(floating: FloatingRef) -> bool Description Return whether the floating is focused. fn is_visible fn is_visible(floating: FloatingRef) -> bool Description Return whether the floating is visible. fn root_node fn root_node(floating: FloatingRef) -> int Description Return the root node id. fn session_id fn session_id(floating: FloatingRef) -> int Description Return the owning session id. fn title fn title(floating: FloatingRef) -> ? Description Return the floating title, if any. ReturnType: string | ()","breadcrumbs":"FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef","id":"21","title":"FloatingRef"},"22":{"body":"Namespace: global fn active_index fn active_index(bar: TabBarContext) -> int Description Return the active tab index. fn is_root fn is_root(bar: TabBarContext) -> bool Description Return whether the formatted tabs are the root tabs. fn mode fn mode(bar: TabBarContext) -> String Description Return the formatter mode name. fn node_id fn node_id(bar: TabBarContext) -> int Description Return the tabs node id currently being formatted. fn tabs fn tabs(bar: TabBarContext) -> Array Description Return tab metadata used by the formatter. fn viewport_width fn viewport_width(bar: TabBarContext) -> int Description Return the formatter viewport width in cells.","breadcrumbs":"TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext","id":"22","title":"TabBarContext"},"23":{"body":"Namespace: global fn buffer_count fn buffer_count(tab: TabInfo) -> int Description Return how many buffers are attached to the tab. fn has_activity fn has_activity(tab: TabInfo) -> bool Description Return whether the tab has activity. fn has_bell fn has_bell(tab: TabInfo) -> bool Description Return whether the tab has a bell marker. fn index fn index(tab: TabInfo) -> int Description Return the zero-based tab index. fn is_active fn is_active(tab: TabInfo) -> bool Description Return whether the tab is active. fn title fn title(tab: TabInfo) -> String Description Return the tab title.","breadcrumbs":"TabInfo » TabInfo » TabInfo » TabInfo » TabInfo » TabInfo » TabInfo » TabInfo","id":"23","title":"TabInfo"},"24":{"body":"Namespace: global fn env fn env(_: SystemApi, name: String) -> ? Description Read an environment variable, if it is set. ReturnType: string | () fn now fn now(_: SystemApi) -> int Description Return the current Unix timestamp in seconds. fn which fn which(_: SystemApi, name: String) -> ? Description Resolve an executable from `PATH`, if it is found. ReturnType: string | ()","breadcrumbs":"System » System » System » System » System","id":"24","title":"System"},"25":{"body":"Namespace: global fn bar fn bar(_: UiApi, left: Array, center: Array, right: Array) -> BarSpec Description Build a full bar specification from left, center, and right segments. fn segment fn segment(_: UiApi, text: String) -> BarSegment\\nfn segment(_: UiApi, text: String, options: Map) -> BarSegment Description Create a [`BarSegment`] from a [`UiApi`] receiver and text using default styling. segment(_: UiApi, text: String) -> BarSegment produces plain text with default\\n[ StyleSpec] values and no click target.","breadcrumbs":"UI » UI » UI » UI","id":"25","title":"UI"},"26":{"body":"Namespace: global fn color fn color(theme: ThemeRuntimeApi, name: String) -> ? Description Read a named color from the active runtime palette, if it exists. ReturnType: RgbColor | ()","breadcrumbs":"Runtime Theme » Runtime Theme » Runtime Theme","id":"26","title":"Runtime Theme"},"3":{"body":"example.md","breadcrumbs":"Overview » Example","id":"3","title":"Example"},"4":{"body":"This is a trimmed example based on the repository fixture config. It shows the two main phases together. set_leader(\\"\\"); fn shell_tree(ctx) { tree.buffer_spawn( [\\"/bin/zsh\\"], #{ title: \\"shell\\", cwd: if ctx.current_buffer() == () { () } else { ctx.current_buffer().cwd() } } )\\n} fn split_below(ctx) { action.split_with(\\"horizontal\\", shell_tree(ctx))\\n} fn format_tabs(ctx) { let active = ctx.tabs()[ctx.active_index()]; ui.bar([ ui.segment(\\" \\" + active.title() + \\" \\", #{ fg: theme.color(\\"active_fg\\"), bg: theme.color(\\"active_bg\\") }) ], [], [])\\n} define_action(\\"split-below\\", split_below);\\nbind(\\"normal\\", \\"\\\\\\"\\", \\"split-below\\");\\ntheme.set_palette(#{ active_fg: \\"#303446\\", active_bg: \\"#c6d0f5\\"\\n});\\ntabbar.set_formatter(format_tabs);\\nmouse.set_click_focus(true);","breadcrumbs":"Example » Example","id":"4","title":"Example"},"5":{"body":"Namespace: global fn bind fn bind(mode: String, notation: String, action: Action)\\nfn bind(mode: String, notation: String, action_name: String)\\nfn bind(mode: String, notation: String, actions: Array) Description Example Bind a key notation to an [`Action`], a string action name, or an array of actions. Use the Action overload for inline builders such as action.focus_left(), the string\\noverload for a named action registered with define_action, or an array to chain multiple\\nactions in sequence. bind(\\"normal\\", \\"ws\\", \\"workspace-split\\"); fn define_action fn define_action(name: String, callback: FnPtr) Description Register a function pointer as a named action callable from bindings. fn define_mode fn define_mode(mode_name: String)\\nfn define_mode(mode_name: String, options: Map) Description Define a custom input mode with hooks and fallback options. Supported options are fallback, on_enter, and on_leave. fn on fn on(event_name: String, callback: FnPtr) Description Attach a callback to an emitted event such as `buffer_bell`. fn set_leader fn set_leader(notation: String) Description Example Set the leader sequence used in binding notations. set_leader(\\"\\"); fn unbind fn unbind(mode: String, notation: String) Description Remove a previously bound key sequence.","breadcrumbs":"Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals","id":"5","title":"Registration Globals"},"6":{"body":"Namespace: global fn cancel_search fn cancel_search(_: ActionApi) -> Action Description Cancel the active search. fn cancel_selection fn cancel_selection(_: ActionApi) -> Action Description Cancel the current selection. fn chain fn chain(_: ActionApi, actions: Array) -> Action Description Chain multiple actions into one composite action. fn clear_pending_keys fn clear_pending_keys(_: ActionApi) -> Action Description Clear any partially-entered key sequence. fn close_floating fn close_floating(_: ActionApi) -> Action Description Close the currently focused floating window. fn close_floating_id fn close_floating_id(_: ActionApi, floating_id: int) -> Action Description Close a floating window by id. fn close_node fn close_node(_: ActionApi, node_id: int) -> Action Description Close a view by node id. fn close_view fn close_view(_: ActionApi) -> Action Description Close the currently focused view. fn copy_selection fn copy_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard. fn detach_buffer fn detach_buffer(_: ActionApi) -> Action Description Detach the currently focused buffer. fn detach_buffer_id fn detach_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Detach a buffer by id. fn enter_mode fn enter_mode(_: ActionApi, mode: String) -> Action Description Enter a specific input mode by name. fn enter_search_mode fn enter_search_mode(_: ActionApi) -> Action Description Enter incremental search mode. fn enter_select_block fn enter_select_block(_: ActionApi) -> Action Description Enter block selection mode. fn enter_select_char fn enter_select_char(_: ActionApi) -> Action Description Enter character selection mode. fn enter_select_line fn enter_select_line(_: ActionApi) -> Action Description Enter line selection mode. fn focus_buffer fn focus_buffer(_: ActionApi, buffer_id: int) -> Action Description Focus a specific buffer by id. fn focus_down fn focus_down(_: ActionApi) -> Action Description Focus the view below the current node. fn focus_left fn focus_left(_: ActionApi) -> Action Description Example Focus the view to the left of the current node. action.focus_left() fn focus_right fn focus_right(_: ActionApi) -> Action Description Focus the view to the right of the current node. fn focus_up fn focus_up(_: ActionApi) -> Action Description Focus the view above the current node. fn follow_output fn follow_output(_: ActionApi) -> Action Description Re-enable following live output. fn insert_tab_after fn insert_tab_after(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab after a specific tabs node. fn insert_tab_after_current fn insert_tab_after_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab after the current tab in the focused tabs node. fn insert_tab_before fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab before a specific tabs node. fn insert_tab_before_current fn insert_tab_before_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab before the current tab. fn kill_buffer fn kill_buffer(_: ActionApi) -> Action Description Kill the currently focused buffer. fn kill_buffer_id fn kill_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Kill a buffer by id. fn leave_mode fn leave_mode(_: ActionApi) -> Action Description Leave the active input mode. fn move_buffer_to_floating fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: Map) -> Action Description Options Move a buffer into a new floating window. x (i16): horizontal offset from the anchor (default: 0) y (i16): vertical offset from the anchor (default: 0) width (FloatingSize): window width, as a percentage (e.g., 50%) or pixel value (default: 50%) height (FloatingSize): window height, as a percentage or pixel value (default: 50%) anchor (FloatingAnchor): anchor point for positioning, e.g., “top_left”, “center” (default: center) title (Option): window title (default: none) focus (bool): whether to focus the window after creation (default: true) close_on_empty (bool): whether to close the window when its buffer empties (default: true) fn move_buffer_to_node fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action Description Move a buffer into a specific node. fn next_current_tabs fn next_current_tabs(_: ActionApi) -> Action Description Select the next tab in the currently focused tabs node. fn next_tab fn next_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the next tab in a specific tabs node. fn noop fn noop(_: ActionApi) -> Action Description Build a no-op action. fn notify fn notify(_: ActionApi, level: String, message: String) -> Action Description Emit a client notification. fn open_floating fn open_floating(_: ActionApi, tree: TreeSpec, options: Map) -> Action Description Open a floating view around the provided tree. fn prev_current_tabs fn prev_current_tabs(_: ActionApi) -> Action Description Select the previous tab in the currently focused tabs node. fn prev_tab fn prev_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the previous tab in a specific tabs node. fn replace_current_with fn replace_current_with(_: ActionApi, tree: TreeSpec) -> Action Description Replace the focused node with a new tree. fn replace_node fn replace_node(_: ActionApi, node_id: int, tree: TreeSpec) -> Action Description Replace a specific node by id with a new tree. fn reveal_buffer fn reveal_buffer(_: ActionApi, buffer_id: int) -> Action Description Reveal a specific buffer by id. fn run_named_action fn run_named_action(_: ActionApi, name: String) -> Action Description Run another named action by name. fn scroll_line_down fn scroll_line_down(_: ActionApi) -> Action Description Scroll one line downward in local scrollback. fn scroll_line_up fn scroll_line_up(_: ActionApi) -> Action Description Scroll one line upward in local scrollback. fn scroll_page_down fn scroll_page_down(_: ActionApi) -> Action Description Scroll one page downward in local scrollback. fn scroll_page_up fn scroll_page_up(_: ActionApi) -> Action Description Scroll one page upward in local scrollback. fn scroll_to_bottom fn scroll_to_bottom(_: ActionApi) -> Action Description Scroll to the bottom of local scrollback. fn scroll_to_top fn scroll_to_top(_: ActionApi) -> Action Description Scroll to the top of local scrollback. fn search_next fn search_next(_: ActionApi) -> Action Description Jump to the next search match. fn search_prev fn search_prev(_: ActionApi) -> Action Description Jump to the previous search match. fn select_current_tabs fn select_current_tabs(_: ActionApi, index: int) -> Action Description Select a tab by index in the currently focused tabs node. fn select_move_down fn select_move_down(_: ActionApi) -> Action Description Move the active selection down. fn select_move_left fn select_move_left(_: ActionApi) -> Action Description Move the active selection left. fn select_move_right fn select_move_right(_: ActionApi) -> Action Description Move the active selection right. fn select_move_up fn select_move_up(_: ActionApi) -> Action Description Move the active selection up. fn select_tab fn select_tab(_: ActionApi, tabs_node_id: int, index: int) -> Action Description Select a tab by index in a specific tabs node. fn send_bytes fn send_bytes(_: ActionApi, buffer_id: int, bytes: String) -> Action\\nfn send_bytes(_: ActionApi, buffer_id: int, bytes: Array) -> Action Description Send a string of bytes to a specific buffer. fn send_bytes_current fn send_bytes_current(_: ActionApi, bytes: String) -> Action\\nfn send_bytes_current(_: ActionApi, bytes: Array) -> Action Description Send a string of bytes to the focused buffer. fn send_keys fn send_keys(_: ActionApi, buffer_id: int, notation: String) -> Action Description Send a key notation sequence to a specific buffer. fn send_keys_current fn send_keys_current(_: ActionApi, notation: String) -> Action Description Send a key notation sequence to the focused buffer. fn split_with fn split_with(_: ActionApi, direction: String, tree: TreeSpec) -> Action Description Split the current node and attach the provided tree as the new sibling. fn toggle_mode fn toggle_mode(_: ActionApi, mode: String) -> Action Description Toggle a named input mode. fn yank_selection fn yank_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard.","breadcrumbs":"Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration)","id":"6","title":"Action (Registration)"},"7":{"body":"Namespace: global fn buffer_attach fn buffer_attach(_: TreeApi, buffer_id: int) -> TreeSpec Description Attach an existing buffer by id. fn buffer_current fn buffer_current(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn buffer_empty fn buffer_empty(_: TreeApi) -> TreeSpec Description Build an empty buffer tree node. fn buffer_spawn fn buffer_spawn(_: TreeApi, command: Array) -> TreeSpec\\nfn buffer_spawn(_: TreeApi, command: Array, options: Map) -> TreeSpec Description Example Spawn a new buffer from a command array. Supported options keys are title ( string), cwd ( string), and env\\n( map). Unknown keys are rejected. tree.buffer_spawn([\\"/bin/zsh\\"], #{ title: \\"shell\\" }) fn current_buffer fn current_buffer(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn current_node fn current_node(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused node. fn split fn split(_: TreeApi, direction: String, children: Array) -> TreeSpec\\nfn split(_: TreeApi, direction: String, children: Array, sizes: Array) -> TreeSpec Description Build a split with an explicit direction string. fn split_h fn split_h(_: TreeApi, children: Array) -> TreeSpec Description Build a horizontal split. fn split_v fn split_v(_: TreeApi, children: Array) -> TreeSpec Description Build a vertical split. fn tab fn tab(_: TreeApi, title: String, tree: TreeSpec) -> TabSpec Description Build a single tab specification. fn tabs fn tabs(_: TreeApi, tabs: Array) -> TreeSpec Description Build a tabs container with the first tab active. fn tabs_with_active fn tabs_with_active(_: TreeApi, tabs: Array, active: int) -> TreeSpec Description Build a tabs container with an explicit active tab.","breadcrumbs":"Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration)","id":"7","title":"Tree (Registration)"},"8":{"body":"Namespace: global fn env fn env(_: SystemApi, name: String) -> ? Description Read an environment variable, if it is set. ReturnType: string | () fn now fn now(_: SystemApi) -> int Description Return the current Unix timestamp in seconds. fn which fn which(_: SystemApi, name: String) -> ? Description Resolve an executable from `PATH`, if it is found. ReturnType: string | ()","breadcrumbs":"System (Registration) » System (Registration) » System (Registration) » System (Registration) » System (Registration)","id":"8","title":"System (Registration)"},"9":{"body":"Namespace: global fn bar fn bar(_: UiApi, left: Array, center: Array, right: Array) -> BarSpec Description Build a full bar specification from left, center, and right segments. fn segment fn segment(_: UiApi, text: String) -> BarSegment\\nfn segment(_: UiApi, text: String, options: Map) -> BarSegment Description Create a [`BarSegment`] from a [`UiApi`] receiver and text using default styling. segment(_: UiApi, text: String) -> BarSegment produces plain text with default\\n[ StyleSpec] values and no click target.","breadcrumbs":"UI (Registration) » UI (Registration) » UI (Registration) » UI (Registration)","id":"9","title":"UI (Registration)"}},"length":27,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"3":{"0":{"3":{"4":{"4":{"6":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"a":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"\\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":8.06225774829855},"6":{"tf":8.06225774829855}}}}},"df":5,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"13":{"tf":8.426149773176359},"5":{"tf":3.1622776601683795},"6":{"tf":8.426149773176359}}}},"v":{"df":11,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}},"t":{"a":{"b":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"d":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"g":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":13,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":3.1622776601683795},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":1.0},"25":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":3.1622776601683795},"9":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":10,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"17":{"tf":2.449489742783178},"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"23":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"12":{"tf":1.0},"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":2,"docs":{"25":{"tf":2.0},"9":{"tf":2.0}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":1,"docs":{"22":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"h":{"a":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"w":{"df":3,"docs":{"13":{"tf":1.0},"4":{"tf":1.4142135623730951},"6":{"tf":1.0}}}}}},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"d":{"(":{"\\"":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"df":2,"docs":{"0":{"tf":1.0},"5":{"tf":2.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":8,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},".":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}}},"_":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":1,"docs":{"23":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":3.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":3.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":12,"docs":{"1":{"tf":1.0},"10":{"tf":1.4142135623730951},"13":{"tf":3.605551275463989},"14":{"tf":2.23606797749979},"15":{"tf":2.449489742783178},"16":{"tf":2.0},"17":{"tf":1.0},"19":{"tf":3.1622776601683795},"20":{"tf":1.4142135623730951},"23":{"tf":1.0},"6":{"tf":3.605551275463989},"7":{"tf":2.23606797749979}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":4.358898943540674}}}}}}}}},"i":{"df":0,"docs":{},"l":{"d":{"df":6,"docs":{"13":{"tf":1.0},"14":{"tf":3.1622776601683795},"25":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":3.1622776601683795},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}},"df":0,"docs":{}}}},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}},"c":{"6":{"d":{"0":{"df":0,"docs":{},"f":{"5":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"h":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"13":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.4142135623730951}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"d":{"df":1,"docs":{"20":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":3,"docs":{"14":{"tf":2.0},"20":{"tf":1.0},"7":{"tf":2.0}}}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":5,"docs":{"0":{"tf":1.0},"10":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"b":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":2,"docs":{"11":{"tf":1.0},"26":{"tf":1.4142135623730951}}}}},"m":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"7":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"0":{"tf":1.4142135623730951},"4":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"15":{"tf":3.605551275463989}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"x":{".":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{")":{".":{"c":{"df":0,"docs":{},"w":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{")":{"[":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{".":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"15":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"d":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}}},"df":11,"docs":{"13":{"tf":4.123105625617661},"14":{"tf":1.7320508075688772},"15":{"tf":2.6457513110645907},"16":{"tf":2.449489742783178},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.0},"6":{"tf":4.123105625617661},"7":{"tf":1.7320508075688772},"8":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"w":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"25":{"tf":1.4142135623730951},"6":{"tf":2.8284271247461903},"9":{"tf":1.4142135623730951}}}}}},"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.4142135623730951}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"\\"":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}},"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"2":{"tf":1.0}}}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":22,"docs":{"10":{"tf":2.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":7.937253933193772},"14":{"tf":3.4641016151377544},"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.242640687119285},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.7320508075688772},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"5":{"tf":2.449489742783178},"6":{"tf":7.937253933193772},"7":{"tf":3.4641016151377544},"8":{"tf":1.7320508075688772},"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}},"t":{"a":{"c":{"df":0,"docs":{},"h":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":5,"docs":{"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"16":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.4142135623730951}},"e":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":5,"docs":{"13":{"tf":1.0},"14":{"tf":1.7320508075688772},"20":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.7320508075688772}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}},"v":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":4,"docs":{"14":{"tf":1.0},"24":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"10":{"tf":1.0},"15":{"tf":1.4142135623730951},"17":{"tf":2.6457513110645907},"5":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":2,"docs":{"15":{"tf":1.0},"17":{"tf":2.8284271247461903}}}}}}}}}},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"19":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.4142135623730951},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0}},"e":{".":{"df":0,"docs":{},"m":{"d":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"26":{"tf":1.0},"7":{"tf":1.0}}}},"t":{"_":{"c":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"f":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":9,"docs":{"1":{"tf":1.0},"13":{"tf":2.0},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":2.23606797749979},"6":{"tf":2.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":5,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"21":{"tf":2.8284271247461903}}}}},"s":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}},"n":{"df":23,"docs":{"10":{"tf":2.8284271247461903},"11":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951},"13":{"tf":11.313708498984761},"14":{"tf":5.0990195135927845},"15":{"tf":4.898979485566356},"16":{"tf":4.47213595499958},"17":{"tf":3.7416573867739413},"18":{"tf":2.8284271247461903},"19":{"tf":6.0},"20":{"tf":5.477225575051661},"21":{"tf":3.7416573867739413},"22":{"tf":3.4641016151377544},"23":{"tf":3.4641016151377544},"24":{"tf":2.449489742783178},"25":{"tf":2.23606797749979},"26":{"tf":1.4142135623730951},"4":{"tf":1.7320508075688772},"5":{"tf":3.872983346207417},"6":{"tf":11.313708498984761},"7":{"tf":5.0990195135927845},"8":{"tf":2.449489742783178},"9":{"tf":2.23606797749979}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}}}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.6457513110645907},"6":{"tf":2.6457513110645907}},"s":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":9,"docs":{"10":{"tf":1.4142135623730951},"13":{"tf":3.3166247903554},"14":{"tf":1.7320508075688772},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"6":{"tf":3.3166247903554},"7":{"tf":1.7320508075688772}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"12":{"tf":1.0},"22":{"tf":1.4142135623730951}},"t":{"df":2,"docs":{"0":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":3,"docs":{"19":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951}}},"y":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"l":{"df":0,"docs":{},"o":{"b":{"a":{"df":0,"docs":{},"l":{"df":23,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"df":0,"docs":{}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}}}}}},"i":{"1":{"6":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"21":{"tf":1.0}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":12,"docs":{"13":{"tf":2.6457513110645907},"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.7320508075688772},"19":{"tf":2.23606797749979},"20":{"tf":2.449489742783178},"21":{"tf":2.0},"22":{"tf":1.0},"6":{"tf":2.6457513110645907},"7":{"tf":1.0}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":5,"docs":{"13":{"tf":2.0},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"6":{"tf":2.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.7320508075688772},"15":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"_":{"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"t":{"df":15,"docs":{"13":{"tf":4.47213595499958},"14":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.4142135623730951},"19":{"tf":2.449489742783178},"20":{"tf":2.23606797749979},"21":{"tf":1.7320508075688772},"22":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"6":{"tf":4.47213595499958},"7":{"tf":1.4142135623730951},"8":{"tf":1.0}}}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"d":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":2,"docs":{"20":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":3,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"i":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"j":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":6,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"19":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"n":{"d":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{">":{"df":0,"docs":{},"w":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}},"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"19":{"tf":1.0},"6":{"tf":1.7320508075688772}}}},"v":{"df":0,"docs":{},"e":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"13":{"tf":1.0},"6":{"tf":1.0}}}}},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"23":{"tf":1.0}}}},"p":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":10,"docs":{"11":{"tf":1.0},"13":{"tf":1.4142135623730951},"14":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.4142135623730951},"7":{"tf":1.0},"9":{"tf":1.0}}},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"a":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"e":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"13":{"tf":3.0},"15":{"tf":1.0},"22":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":3.0}},"l":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"10":{"tf":1.4142135623730951}},"e":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":2.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"x":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"16":{"tf":3.1622776601683795}}}}},"df":2,"docs":{"1":{"tf":1.0},"16":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":13,"docs":{"0":{"tf":1.4142135623730951},"11":{"tf":1.0},"13":{"tf":2.23606797749979},"15":{"tf":1.0},"17":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"5":{"tf":1.7320508075688772},"6":{"tf":2.23606797749979},"8":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":22,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":4,"docs":{"13":{"tf":2.0},"14":{"tf":1.0},"6":{"tf":2.0},"7":{"tf":1.0}}},"x":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}}}},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":1.7320508075688772},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"19":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":13,"docs":{"1":{"tf":1.0},"13":{"tf":4.242640687119285},"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":3.0},"21":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":4.242640687119285},"7":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"20":{"tf":4.0}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":2.0},"5":{"tf":2.449489742783178},"6":{"tf":2.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"w":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"n":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"p":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":7,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":3,"docs":{"1":{"tf":1.0},"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":2,"docs":{"11":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"h":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"19":{"tf":1.0},"20":{"tf":1.0}}}}}},"v":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"17":{"tf":1.0},"6":{"tf":1.7320508075688772}},"s":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"5":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":1,"docs":{"19":{"tf":2.0}}}}}},"d":{"df":0,"docs":{},"u":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"24":{"tf":1.0},"26":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"f":{"df":1,"docs":{"1":{"tf":2.0}},"e":{"df":0,"docs":{},"r":{"df":5,"docs":{"0":{"tf":1.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.7320508075688772}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":7,"docs":{"0":{"tf":1.0},"1":{"tf":2.23606797749979},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}},"e":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"v":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":11,"docs":{"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.123105625617661},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.0},"8":{"tf":1.0}},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":9,"docs":{"15":{"tf":2.8284271247461903},"16":{"tf":2.6457513110645907},"17":{"tf":2.449489742783178},"19":{"tf":2.8284271247461903},"20":{"tf":2.449489742783178},"21":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"8":{"tf":1.4142135623730951}}}}}}}}},"v":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"b":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"18":{"tf":1.0},"21":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":4,"docs":{"18":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"d":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951}},"e":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"o":{"_":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}},"df":0,"docs":{}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.7320508075688772},"9":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"df":2,"docs":{"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":4.0},"6":{"tf":4.0}}}},"df":0,"docs":{}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}},"df":0,"docs":{}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":4,"docs":{"17":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}},"df":0,"docs":{}}},"df":8,"docs":{"1":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":1.4142135623730951},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":2.23606797749979}}}}},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"10":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"\\"":{"<":{"c":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"11":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"5":{"tf":1.0},"8":{"tf":1.0}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"4":{"tf":1.0}}}}},"i":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"7":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":6,"docs":{"13":{"tf":3.4641016151377544},"14":{"tf":1.0},"25":{"tf":1.0},"6":{"tf":3.4641016151377544},"7":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"v":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":7,"docs":{"13":{"tf":1.0},"14":{"tf":2.0},"20":{"tf":1.7320508075688772},"4":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":2.0}}}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"19":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":18,"docs":{"13":{"tf":4.0},"14":{"tf":2.6457513110645907},"15":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":3.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":2.0},"25":{"tf":1.7320508075688772},"26":{"tf":1.0},"5":{"tf":4.0},"6":{"tf":4.0},"7":{"tf":2.6457513110645907},"8":{"tf":2.0},"9":{"tf":1.7320508075688772}}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"u":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"20":{"tf":1.0},"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"5":{"tf":1.0},"7":{"tf":1.0}}}}}}}},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"24":{"tf":1.7320508075688772},"8":{"tf":1.7320508075688772}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"20":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"b":{"a":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"12":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":2.6457513110645907}}}}}}}}},"df":2,"docs":{"1":{"tf":1.0},"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":4.58257569495584},"14":{"tf":3.0},"18":{"tf":1.0},"20":{"tf":2.0},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"6":{"tf":4.58257569495584},"7":{"tf":3.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":2.6457513110645907}}}}}},"s":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":3,"docs":{"19":{"tf":1.4142135623730951},"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"\\"":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"11":{"tf":1.0}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"11":{"tf":1.4142135623730951},"26":{"tf":1.0}},"r":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.0}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"10":{"tf":2.0},"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"p":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{".":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"[":{"\\"":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":3.7416573867739413},"7":{"tf":3.7416573867739413}}}}},"df":5,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":3.4641016151377544},"14":{"tf":2.449489742783178},"6":{"tf":3.4641016151377544},"7":{"tf":2.449489742783178}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"14":{"tf":3.7416573867739413},"6":{"tf":2.8284271247461903},"7":{"tf":3.7416573867739413}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}},"y":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"i":{".":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"25":{"tf":1.0},"9":{"tf":1.0}}},"n":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"k":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}}}},"p":{"df":3,"docs":{"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":6,"docs":{"0":{"tf":1.0},"12":{"tf":1.0},"22":{"tf":1.0},"25":{"tf":1.0},"5":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":5,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"25":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"13":{"tf":2.6457513110645907},"6":{"tf":2.6457513110645907}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"l":{"df":5,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":7,"docs":{"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}}}}},"i":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"22":{"tf":1.0},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":6,"docs":{"13":{"tf":2.8284271247461903},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"18":{"tf":1.0},"20":{"tf":1.0},"6":{"tf":2.8284271247461903}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"x":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"z":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"breadcrumbs":{"root":{"0":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"3":{"0":{"3":{"4":{"4":{"6":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"a":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"\\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":8.06225774829855},"6":{"tf":8.06225774829855}}}}},"df":5,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"13":{"tf":11.661903789690601},"5":{"tf":3.1622776601683795},"6":{"tf":11.661903789690601}}}},"v":{"df":11,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}},"t":{"a":{"b":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"d":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"g":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":13,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":3.1622776601683795},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":1.0},"25":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":3.1622776601683795},"9":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":10,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"17":{"tf":2.449489742783178},"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"23":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"12":{"tf":1.0},"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":2,"docs":{"25":{"tf":2.0},"9":{"tf":2.0}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":1,"docs":{"22":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"h":{"a":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"w":{"df":3,"docs":{"13":{"tf":1.0},"4":{"tf":1.4142135623730951},"6":{"tf":1.0}}}}}},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"d":{"(":{"\\"":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"df":2,"docs":{"0":{"tf":1.0},"5":{"tf":2.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":8,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},".":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}}},"_":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":1,"docs":{"23":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":3.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":3.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":12,"docs":{"1":{"tf":1.0},"10":{"tf":1.4142135623730951},"13":{"tf":3.605551275463989},"14":{"tf":2.23606797749979},"15":{"tf":2.449489742783178},"16":{"tf":2.0},"17":{"tf":1.0},"19":{"tf":3.1622776601683795},"20":{"tf":1.4142135623730951},"23":{"tf":1.0},"6":{"tf":3.605551275463989},"7":{"tf":2.23606797749979}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":6.244997998398398}}}}}}}}},"i":{"df":0,"docs":{},"l":{"d":{"df":6,"docs":{"13":{"tf":1.0},"14":{"tf":3.1622776601683795},"25":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":3.1622776601683795},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}},"df":0,"docs":{}}}},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}},"c":{"6":{"d":{"0":{"df":0,"docs":{},"f":{"5":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"h":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"13":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.4142135623730951}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"d":{"df":1,"docs":{"20":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":3,"docs":{"14":{"tf":2.0},"20":{"tf":1.0},"7":{"tf":2.0}}}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":5,"docs":{"0":{"tf":1.0},"10":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"b":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":2,"docs":{"11":{"tf":1.0},"26":{"tf":1.4142135623730951}}}}},"m":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"7":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"0":{"tf":1.7320508075688772},"4":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"15":{"tf":5.196152422706632}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"x":{".":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{")":{".":{"c":{"df":0,"docs":{},"w":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{")":{"[":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{".":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"15":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"d":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}}},"df":11,"docs":{"13":{"tf":4.123105625617661},"14":{"tf":1.7320508075688772},"15":{"tf":2.6457513110645907},"16":{"tf":2.449489742783178},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.0},"6":{"tf":4.123105625617661},"7":{"tf":1.7320508075688772},"8":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"w":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"25":{"tf":1.4142135623730951},"6":{"tf":2.8284271247461903},"9":{"tf":1.4142135623730951}}}}}},"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.4142135623730951}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"\\"":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}},"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"2":{"tf":1.4142135623730951}}}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":22,"docs":{"10":{"tf":2.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":7.937253933193772},"14":{"tf":3.4641016151377544},"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.242640687119285},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.7320508075688772},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"5":{"tf":2.449489742783178},"6":{"tf":7.937253933193772},"7":{"tf":3.4641016151377544},"8":{"tf":1.7320508075688772},"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}},"t":{"a":{"c":{"df":0,"docs":{},"h":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":5,"docs":{"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"16":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.4142135623730951}},"e":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":5,"docs":{"13":{"tf":1.0},"14":{"tf":1.7320508075688772},"20":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.7320508075688772}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.7320508075688772}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}},"v":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":4,"docs":{"14":{"tf":1.0},"24":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"10":{"tf":1.0},"15":{"tf":1.4142135623730951},"17":{"tf":2.6457513110645907},"5":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":2,"docs":{"15":{"tf":1.0},"17":{"tf":4.123105625617661}}}}}}}}}},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"19":{"tf":1.0},"3":{"tf":1.4142135623730951},"4":{"tf":2.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0}},"e":{".":{"df":0,"docs":{},"m":{"d":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"26":{"tf":1.0},"7":{"tf":1.0}}}},"t":{"_":{"c":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"f":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":9,"docs":{"1":{"tf":1.0},"13":{"tf":2.0},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":2.23606797749979},"6":{"tf":2.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":5,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"21":{"tf":4.123105625617661}}}}},"s":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}},"n":{"df":23,"docs":{"10":{"tf":2.8284271247461903},"11":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951},"13":{"tf":11.313708498984761},"14":{"tf":5.0990195135927845},"15":{"tf":4.898979485566356},"16":{"tf":4.47213595499958},"17":{"tf":3.7416573867739413},"18":{"tf":2.8284271247461903},"19":{"tf":6.0},"20":{"tf":5.477225575051661},"21":{"tf":3.7416573867739413},"22":{"tf":3.4641016151377544},"23":{"tf":3.4641016151377544},"24":{"tf":2.449489742783178},"25":{"tf":2.23606797749979},"26":{"tf":1.4142135623730951},"4":{"tf":1.7320508075688772},"5":{"tf":3.872983346207417},"6":{"tf":11.313708498984761},"7":{"tf":5.0990195135927845},"8":{"tf":2.449489742783178},"9":{"tf":2.23606797749979}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}}}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.6457513110645907},"6":{"tf":2.6457513110645907}},"s":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":9,"docs":{"10":{"tf":1.4142135623730951},"13":{"tf":3.3166247903554},"14":{"tf":1.7320508075688772},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"6":{"tf":3.3166247903554},"7":{"tf":1.7320508075688772}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"12":{"tf":1.0},"22":{"tf":1.4142135623730951}},"t":{"df":2,"docs":{"0":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":3,"docs":{"19":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951}}},"y":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"l":{"df":0,"docs":{},"o":{"b":{"a":{"df":0,"docs":{},"l":{"df":23,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":3.1622776601683795},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"df":0,"docs":{}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}}}}}},"i":{"1":{"6":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"21":{"tf":1.0}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":12,"docs":{"13":{"tf":2.6457513110645907},"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.7320508075688772},"19":{"tf":2.23606797749979},"20":{"tf":2.449489742783178},"21":{"tf":2.0},"22":{"tf":1.0},"6":{"tf":2.6457513110645907},"7":{"tf":1.0}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":5,"docs":{"13":{"tf":2.0},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"6":{"tf":2.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.7320508075688772},"15":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"_":{"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"t":{"df":15,"docs":{"13":{"tf":4.47213595499958},"14":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.4142135623730951},"19":{"tf":2.449489742783178},"20":{"tf":2.23606797749979},"21":{"tf":1.7320508075688772},"22":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"6":{"tf":4.47213595499958},"7":{"tf":1.4142135623730951},"8":{"tf":1.0}}}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"d":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":2,"docs":{"20":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":3,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"i":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"j":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":6,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"19":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"n":{"d":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{">":{"df":0,"docs":{},"w":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}},"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"19":{"tf":1.0},"6":{"tf":1.7320508075688772}}}},"v":{"df":0,"docs":{},"e":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"13":{"tf":1.0},"6":{"tf":1.0}}}}},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"23":{"tf":1.0}}}},"p":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":10,"docs":{"11":{"tf":1.0},"13":{"tf":1.4142135623730951},"14":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.4142135623730951},"7":{"tf":1.0},"9":{"tf":1.0}}},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"a":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"e":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"13":{"tf":3.0},"15":{"tf":1.0},"22":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":3.0}},"l":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"10":{"tf":2.8284271247461903}},"e":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":2.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"x":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"16":{"tf":3.1622776601683795}}}}},"df":2,"docs":{"1":{"tf":1.0},"16":{"tf":3.605551275463989}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":13,"docs":{"0":{"tf":1.4142135623730951},"11":{"tf":1.0},"13":{"tf":2.23606797749979},"15":{"tf":1.0},"17":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"5":{"tf":1.7320508075688772},"6":{"tf":2.23606797749979},"8":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":22,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":4,"docs":{"13":{"tf":2.0},"14":{"tf":1.0},"6":{"tf":2.0},"7":{"tf":1.0}}},"x":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}}}},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":1.7320508075688772},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"19":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":13,"docs":{"1":{"tf":1.0},"13":{"tf":4.242640687119285},"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":3.0},"21":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":4.242640687119285},"7":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"20":{"tf":5.744562646538029}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":2.0},"5":{"tf":2.449489742783178},"6":{"tf":2.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"w":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"n":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"p":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":7,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":4,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"2":{"tf":1.0},"3":{"tf":1.0}}}}}}}}},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":3,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":2,"docs":{"11":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"h":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"19":{"tf":1.0},"20":{"tf":1.0}}}}}},"v":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"17":{"tf":1.0},"6":{"tf":1.7320508075688772}},"s":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"5":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":1,"docs":{"19":{"tf":2.0}}}}}},"d":{"df":0,"docs":{},"u":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"24":{"tf":1.0},"26":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"f":{"df":1,"docs":{"1":{"tf":2.0}},"e":{"df":0,"docs":{},"r":{"df":5,"docs":{"0":{"tf":1.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.7320508075688772}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":7,"docs":{"0":{"tf":1.0},"1":{"tf":2.23606797749979},"5":{"tf":3.0},"6":{"tf":8.12403840463596},"7":{"tf":3.872983346207417},"8":{"tf":2.449489742783178},"9":{"tf":2.23606797749979}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}},"e":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"v":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":11,"docs":{"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.123105625617661},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.0},"8":{"tf":1.0}},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":9,"docs":{"15":{"tf":2.8284271247461903},"16":{"tf":2.6457513110645907},"17":{"tf":2.449489742783178},"19":{"tf":2.8284271247461903},"20":{"tf":2.449489742783178},"21":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"8":{"tf":1.4142135623730951}}}}}}}}},"v":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"b":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"18":{"tf":1.0},"21":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":4,"docs":{"18":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"d":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"26":{"tf":2.23606797749979}},"e":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"o":{"_":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}},"df":0,"docs":{}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.7320508075688772},"9":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"df":2,"docs":{"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":4.0},"6":{"tf":4.0}}}},"df":0,"docs":{}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}},"df":0,"docs":{}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":4,"docs":{"17":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}},"df":0,"docs":{}}},"df":8,"docs":{"1":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":1.4142135623730951},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":3.3166247903554}}}}},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"10":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"\\"":{"<":{"c":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"11":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"5":{"tf":1.0},"8":{"tf":1.0}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"4":{"tf":1.0}}}}},"i":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"7":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":6,"docs":{"13":{"tf":3.4641016151377544},"14":{"tf":1.0},"25":{"tf":1.0},"6":{"tf":3.4641016151377544},"7":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"v":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":7,"docs":{"13":{"tf":1.0},"14":{"tf":2.0},"20":{"tf":1.7320508075688772},"4":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":2.0}}}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"19":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":18,"docs":{"13":{"tf":4.0},"14":{"tf":2.6457513110645907},"15":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":3.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":2.0},"25":{"tf":1.7320508075688772},"26":{"tf":1.0},"5":{"tf":4.0},"6":{"tf":4.0},"7":{"tf":2.6457513110645907},"8":{"tf":2.0},"9":{"tf":1.7320508075688772}}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"u":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"20":{"tf":1.0},"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"5":{"tf":1.0},"7":{"tf":1.0}}}}}}}},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"24":{"tf":1.7320508075688772},"8":{"tf":1.7320508075688772}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"24":{"tf":2.449489742783178},"8":{"tf":2.449489742783178}}}}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"20":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"b":{"a":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"12":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":3.872983346207417}}}}}}}}},"df":2,"docs":{"1":{"tf":1.0},"12":{"tf":2.0}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":4.58257569495584},"14":{"tf":3.0},"18":{"tf":1.0},"20":{"tf":2.0},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"6":{"tf":4.58257569495584},"7":{"tf":3.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":3.872983346207417}}}}}},"s":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":3,"docs":{"19":{"tf":1.4142135623730951},"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"\\"":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"11":{"tf":1.0}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"11":{"tf":2.23606797749979},"26":{"tf":2.0}},"r":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.0}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"10":{"tf":2.0},"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"p":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{".":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"[":{"\\"":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":3.7416573867739413},"7":{"tf":3.7416573867739413}}}}},"df":5,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":3.4641016151377544},"14":{"tf":4.47213595499958},"6":{"tf":3.4641016151377544},"7":{"tf":4.47213595499958}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"14":{"tf":3.7416573867739413},"6":{"tf":2.8284271247461903},"7":{"tf":3.7416573867739413}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}},"y":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"i":{".":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}},"n":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"k":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}}}},"p":{"df":3,"docs":{"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":6,"docs":{"0":{"tf":1.0},"12":{"tf":1.0},"22":{"tf":1.0},"25":{"tf":1.0},"5":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":5,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"25":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"13":{"tf":2.6457513110645907},"6":{"tf":2.6457513110645907}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"l":{"df":5,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":7,"docs":{"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}}}}},"i":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"22":{"tf":1.0},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":6,"docs":{"13":{"tf":2.8284271247461903},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"18":{"tf":1.0},"20":{"tf":1.0},"6":{"tf":2.8284271247461903}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"x":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"z":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"title":{"root":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}}},"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}}}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":1,"docs":{"0":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"2":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"17":{"tf":1.0}}}}}}}}}},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{}}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"21":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"b":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":5,"docs":{"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}}}}}},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"26":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}}}}},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"t":{"a":{"b":{"b":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}}},"df":1,"docs":{"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":2,"docs":{"11":{"tf":1.0},"26":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"i":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}}')); \ No newline at end of file diff --git a/docs/config-api-book/searchindex-6f9ff0e9.js b/docs/config-api-book/searchindex-6f9ff0e9.js new file mode 100644 index 00000000..04edb94b --- /dev/null +++ b/docs/config-api-book/searchindex-6f9ff0e9.js @@ -0,0 +1 @@ +window.search = Object.assign(window.search, JSON.parse('{"doc_urls":["index.html#embers-config-api","index.html#pages","index.html#definitions","index.html#example","example.html#example","registration-globals.html#registration-globals","registration-action.html#action-registration","registration-tree.html#tree-registration","registration-system.html#system-registration","registration-ui.html#ui-registration","mouse.html#mouse","theme.html#theme","tabbar.html#tabbar","action.html#action","tree.html#tree","context.html#context","mux.html#mux","event-info.html#eventinfo","session-ref.html#sessionref","buffer-ref.html#bufferref","node-ref.html#noderef","floating-ref.html#floatingref","tab-bar-context.html#tabbarcontext","tab-info.html#tabinfo","system-runtime.html#system","ui.html#ui","runtime-theme.html#runtime-theme"],"index":{"documentStore":{"docInfo":{"0":{"body":41,"breadcrumbs":4,"title":3},"1":{"body":37,"breadcrumbs":2,"title":1},"10":{"body":55,"breadcrumbs":6,"title":1},"11":{"body":15,"breadcrumbs":3,"title":1},"12":{"body":16,"breadcrumbs":3,"title":1},"13":{"body":1040,"breadcrumbs":74,"title":1},"14":{"body":202,"breadcrumbs":14,"title":1},"15":{"body":165,"breadcrumbs":14,"title":1},"16":{"body":136,"breadcrumbs":12,"title":1},"17":{"body":91,"breadcrumbs":9,"title":1},"18":{"body":48,"breadcrumbs":6,"title":1},"19":{"body":230,"breadcrumbs":20,"title":1},"2":{"body":2,"breadcrumbs":2,"title":1},"20":{"body":178,"breadcrumbs":17,"title":1},"21":{"body":78,"breadcrumbs":9,"title":1},"22":{"body":75,"breadcrumbs":8,"title":1},"23":{"body":70,"breadcrumbs":8,"title":1},"24":{"body":41,"breadcrumbs":5,"title":1},"25":{"body":61,"breadcrumbs":4,"title":1},"26":{"body":19,"breadcrumbs":6,"title":2},"3":{"body":1,"breadcrumbs":2,"title":1},"4":{"body":50,"breadcrumbs":2,"title":1},"5":{"body":136,"breadcrumbs":16,"title":2},"6":{"body":1040,"breadcrumbs":148,"title":2},"7":{"body":202,"breadcrumbs":28,"title":2},"8":{"body":41,"breadcrumbs":10,"title":2},"9":{"body":61,"breadcrumbs":8,"title":2}},"docs":{"0":{"body":"This reference is generated from the Rust-backed Rhai exports used by Embers. There are two execution phases: registration time: the top-level config file where you declare modes, bindings, named actions, and visual settings runtime: named actions, event handlers, and tab bar formatters that run against live client state Definition files live in defs/.","breadcrumbs":"Overview » Embers Config API","id":"0","title":"Embers Config API"},"1":{"body":"action buffer-ref context event-info floating-ref mouse mux node-ref registration-action registration-globals registration-system registration-tree registration-ui runtime-theme session-ref system-runtime tab-bar-context tab-info tabbar theme tree ui","breadcrumbs":"Overview » Pages","id":"1","title":"Pages"},"10":{"body":"Namespace: global fn set_click_focus fn set_click_focus(mouse: MouseApi, value: bool) Description Toggle focus-on-click behavior. fn set_click_forward fn set_click_forward(mouse: MouseApi, value: bool) Description Toggle forwarding mouse clicks into the focused buffer. fn set_wheel_forward fn set_wheel_forward(mouse: MouseApi, value: bool) Description Toggle wheel event forwarding into the focused buffer. fn set_wheel_scroll fn set_wheel_scroll(mouse: MouseApi, value: bool) Description Toggle client-side wheel scrolling.","breadcrumbs":"Mouse » Mouse » Mouse » Mouse » Mouse » Mouse","id":"10","title":"Mouse"},"11":{"body":"Namespace: global fn set_palette fn set_palette(theme: ThemeApi, palette: Map) Description Add named colors to the theme palette.","breadcrumbs":"Theme » Theme » Theme","id":"11","title":"Theme"},"12":{"body":"Namespace: global fn set_formatter fn set_formatter(tabbar: TabbarApi, callback: FnPtr) Description Register the function used to format the tab bar.","breadcrumbs":"Tabbar » Tabbar » Tabbar","id":"12","title":"Tabbar"},"13":{"body":"Namespace: global fn break_current_node fn break_current_node(_: ActionApi, destination: String) -> Action Description Break the current node into a new tab or floating window. fn cancel_search fn cancel_search(_: ActionApi) -> Action Description Cancel the active search. fn cancel_selection fn cancel_selection(_: ActionApi) -> Action Description Cancel the current selection. fn chain fn chain(_: ActionApi, actions: Array) -> Action Description Chain multiple actions into one composite action. fn clear_pending_keys fn clear_pending_keys(_: ActionApi) -> Action Description Clear any partially-entered key sequence. fn close_floating fn close_floating(_: ActionApi) -> Action Description Close the currently focused floating window. fn close_floating_id fn close_floating_id(_: ActionApi, floating_id: int) -> Action Description Close a floating window by id. fn close_node fn close_node(_: ActionApi, node_id: int) -> Action Description Close a view by node id. fn close_view fn close_view(_: ActionApi) -> Action Description Close the currently focused view. fn copy_selection fn copy_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard. fn detach_buffer fn detach_buffer(_: ActionApi) -> Action Description Detach the currently focused buffer. fn detach_buffer_id fn detach_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Detach a buffer by id. fn enter_mode fn enter_mode(_: ActionApi, mode: String) -> Action Description Enter a specific input mode by name. fn enter_search_mode fn enter_search_mode(_: ActionApi) -> Action Description Enter incremental search mode. fn enter_select_block fn enter_select_block(_: ActionApi) -> Action Description Enter block selection mode. fn enter_select_char fn enter_select_char(_: ActionApi) -> Action Description Enter character selection mode. fn enter_select_line fn enter_select_line(_: ActionApi) -> Action Description Enter line selection mode. fn focus_buffer fn focus_buffer(_: ActionApi, buffer_id: int) -> Action Description Focus a specific buffer by id. fn focus_down fn focus_down(_: ActionApi) -> Action Description Focus the view below the current node. fn focus_left fn focus_left(_: ActionApi) -> Action Description Example Focus the view to the left of the current node. action.focus_left() fn focus_right fn focus_right(_: ActionApi) -> Action Description Focus the view to the right of the current node. fn focus_up fn focus_up(_: ActionApi) -> Action Description Focus the view above the current node. fn follow_output fn follow_output(_: ActionApi) -> Action Description Re-enable following live output. fn insert_tab_after fn insert_tab_after(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab after a specific tabs node. fn insert_tab_after_current fn insert_tab_after_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab after the current tab in the focused tabs node. fn insert_tab_before fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab before a specific tabs node. fn insert_tab_before_current fn insert_tab_before_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab before the current tab. fn join_buffer_here fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action Description Join a buffer at the current node. fn kill_buffer fn kill_buffer(_: ActionApi) -> Action Description Kill the currently focused buffer. fn kill_buffer_id fn kill_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Kill a buffer by id. fn leave_mode fn leave_mode(_: ActionApi) -> Action Description Leave the active input mode. fn move_buffer_to_floating fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: Map) -> Action Description Options Move a buffer into a new floating window. x (i16): horizontal offset from the anchor (default: 0) y (i16): vertical offset from the anchor (default: 0) width (FloatingSize): window width, as a percentage (e.g., 50%) or pixel value (default: 50%) height (FloatingSize): window height, as a percentage or pixel value (default: 50%) anchor (FloatingAnchor): anchor point for positioning, e.g., “top_left”, “center” (default: center) title (Option): window title (default: none) focus (bool): whether to focus the window after creation (default: true) close_on_empty (bool): whether to close the window when its buffer empties (default: true) fn move_buffer_to_node fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action Description Move a buffer into a specific node. fn move_current_node_before fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action Description Move the current node before a sibling. fn move_node_after fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action Description Move a node after a sibling. fn next_current_tabs fn next_current_tabs(_: ActionApi) -> Action Description Select the next tab in the currently focused tabs node. fn next_tab fn next_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the next tab in a specific tabs node. fn noop fn noop(_: ActionApi) -> Action Description Build a no-op action. fn notify fn notify(_: ActionApi, level: String, message: String) -> Action Description Emit a client notification. fn open_buffer_history fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action Description Open the history of a buffer in a new view. fn open_floating fn open_floating(_: ActionApi, tree: TreeSpec, options: Map) -> Action Description Open a floating view around the provided tree. fn prev_current_tabs fn prev_current_tabs(_: ActionApi) -> Action Description Select the previous tab in the currently focused tabs node. fn prev_tab fn prev_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the previous tab in a specific tabs node. fn replace_current_with fn replace_current_with(_: ActionApi, tree: TreeSpec) -> Action Description Replace the focused node with a new tree. fn replace_node fn replace_node(_: ActionApi, node_id: int, tree: TreeSpec) -> Action Description Replace a specific node by id with a new tree. fn reveal_buffer fn reveal_buffer(_: ActionApi, buffer_id: int) -> Action Description Reveal a specific buffer by id. fn run_named_action fn run_named_action(_: ActionApi, name: String) -> Action Description Run another named action by name. fn scroll_line_down fn scroll_line_down(_: ActionApi) -> Action Description Scroll one line downward in local scrollback. fn scroll_line_up fn scroll_line_up(_: ActionApi) -> Action Description Scroll one line upward in local scrollback. fn scroll_page_down fn scroll_page_down(_: ActionApi) -> Action Description Scroll one page downward in local scrollback. fn scroll_page_up fn scroll_page_up(_: ActionApi) -> Action Description Scroll one page upward in local scrollback. fn scroll_to_bottom fn scroll_to_bottom(_: ActionApi) -> Action Description Scroll to the bottom of local scrollback. fn scroll_to_top fn scroll_to_top(_: ActionApi) -> Action Description Scroll to the top of local scrollback. fn search_next fn search_next(_: ActionApi) -> Action Description Jump to the next search match. fn search_prev fn search_prev(_: ActionApi) -> Action Description Jump to the previous search match. fn select_current_tabs fn select_current_tabs(_: ActionApi, index: int) -> Action Description Select a tab by index in the currently focused tabs node. fn select_move_down fn select_move_down(_: ActionApi) -> Action Description Move the active selection down. fn select_move_left fn select_move_left(_: ActionApi) -> Action Description Move the active selection left. fn select_move_right fn select_move_right(_: ActionApi) -> Action Description Move the active selection right. fn select_move_up fn select_move_up(_: ActionApi) -> Action Description Move the active selection up. fn select_tab fn select_tab(_: ActionApi, tabs_node_id: int, index: int) -> Action Description Select a tab by index in a specific tabs node. fn send_bytes fn send_bytes(_: ActionApi, buffer_id: int, bytes: String) -> Action\\nfn send_bytes(_: ActionApi, buffer_id: int, bytes: Array) -> Action Description Send a string of bytes to a specific buffer. fn send_bytes_current fn send_bytes_current(_: ActionApi, bytes: String) -> Action\\nfn send_bytes_current(_: ActionApi, bytes: Array) -> Action Description Send a string of bytes to the focused buffer. fn send_keys fn send_keys(_: ActionApi, buffer_id: int, notation: String) -> Action Description Send a key notation sequence to a specific buffer. fn send_keys_current fn send_keys_current(_: ActionApi, notation: String) -> Action Description Send a key notation sequence to the focused buffer. fn split_with fn split_with(_: ActionApi, direction: String, tree: TreeSpec) -> Action Description Split the current node and attach the provided tree as the new sibling. fn swap_current_node fn swap_current_node(_: ActionApi, second_node_id: int) -> Action Description Swap the current node with a sibling. fn toggle_mode fn toggle_mode(_: ActionApi, mode: String) -> Action Description Toggle a named input mode. fn toggle_zoom_node fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action Description Toggle zoom on a node. fn unzoom_current_session fn unzoom_current_session(_: ActionApi) -> Action Description Unzoom the current session. fn yank_selection fn yank_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard. fn zoom_current_node fn zoom_current_node(_: ActionApi) -> Action Description Zoom the current node.","breadcrumbs":"Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action » Action","id":"13","title":"Action"},"14":{"body":"Namespace: global fn buffer_attach fn buffer_attach(_: TreeApi, buffer_id: int) -> TreeSpec Description Attach an existing buffer by id. fn buffer_current fn buffer_current(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn buffer_empty fn buffer_empty(_: TreeApi) -> TreeSpec Description Build an empty buffer tree node. fn buffer_spawn fn buffer_spawn(_: TreeApi, command: Array) -> TreeSpec\\nfn buffer_spawn(_: TreeApi, command: Array, options: Map) -> TreeSpec Description Example Spawn a new buffer from a command array. Supported options keys are title ( string), cwd ( string), and env\\n( map). Unknown keys are rejected. tree.buffer_spawn([\\"/bin/zsh\\"], #{ title: \\"shell\\" }) fn current_buffer fn current_buffer(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn current_node fn current_node(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused node. fn split fn split(_: TreeApi, direction: String, children: Array) -> TreeSpec\\nfn split(_: TreeApi, direction: String, children: Array, sizes: Array) -> TreeSpec Description Build a split with an explicit direction string. fn split_h fn split_h(_: TreeApi, children: Array) -> TreeSpec Description Build a horizontal split. fn split_v fn split_v(_: TreeApi, children: Array) -> TreeSpec Description Build a vertical split. fn tab fn tab(_: TreeApi, title: String, tree: TreeSpec) -> TabSpec Description Build a single tab specification. fn tabs fn tabs(_: TreeApi, tabs: Array) -> TreeSpec Description Build a tabs container with the first tab active. fn tabs_with_active fn tabs_with_active(_: TreeApi, tabs: Array, active: int) -> TreeSpec Description Build a tabs container with an explicit active tab.","breadcrumbs":"Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree » Tree","id":"14","title":"Tree"},"15":{"body":"Namespace: global fn current_buffer fn current_buffer(context: Context) -> ? Description Example Return the currently focused buffer, if any. ReturnType: BufferRef | () let buffer = ctx.current_buffer();\\nif buffer != () { print(buffer.title());\\n} fn current_floating fn current_floating(context: Context) -> ? Description Return the currently focused floating window, if any. ReturnType: FloatingRef | () fn current_mode fn current_mode(context: Context) -> String Description Return the active input mode name. fn current_node fn current_node(context: Context) -> ? Description Return the currently focused node, if any. ReturnType: NodeRef | () fn current_session fn current_session(context: Context) -> ? Description Return the current session reference, if any. ReturnType: SessionRef | () fn detached_buffers fn detached_buffers(context: Context) -> Array Description Return detached buffers in the current model snapshot. fn event fn event(context: Context) -> ? Description Return the current event payload, if any. ReturnType: EventInfo | () fn find_buffer fn find_buffer(context: Context, buffer_id: int) -> ? Description Find a buffer by numeric id. Returns `()` when it does not exist. ReturnType: BufferRef | () fn find_floating fn find_floating(context: Context, floating_id: int) -> ? Description Find a floating window by numeric id. Returns `()` when it does not exist. ReturnType: FloatingRef | () fn find_node fn find_node(context: Context, node_id: int) -> ? Description Find a node by numeric id. Returns `()` when it does not exist. ReturnType: NodeRef | () fn sessions fn sessions(context: Context) -> Array Description Return every visible session. fn visible_buffers fn visible_buffers(context: Context) -> Array Description Return visible buffers in the current model snapshot.","breadcrumbs":"Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context » Context","id":"15","title":"Context"},"16":{"body":"Namespace: global fn current_buffer fn current_buffer(mux: MuxApi) -> ? Description Return the currently focused buffer, if any. ReturnType: BufferRef | () fn current_floating fn current_floating(mux: MuxApi) -> ? Description Return the currently focused floating window, if any. ReturnType: FloatingRef | () fn current_node fn current_node(mux: MuxApi) -> ? Description Return the currently focused node, if any. ReturnType: NodeRef | () fn current_session fn current_session(mux: MuxApi) -> ? Description Return the current session reference, if any. ReturnType: SessionRef | () fn detached_buffers fn detached_buffers(mux: MuxApi) -> Array Description Return detached buffers in the current model snapshot. fn find_buffer fn find_buffer(mux: MuxApi, buffer_id: int) -> ? Description Find a buffer by numeric id. Returns `()` when it does not exist. ReturnType: BufferRef | () fn find_floating fn find_floating(mux: MuxApi, floating_id: int) -> ? Description Find a floating window by numeric id. Returns `()` when it does not exist. ReturnType: FloatingRef | () fn find_node fn find_node(mux: MuxApi, node_id: int) -> ? Description Find a node by numeric id. Returns `()` when it does not exist. ReturnType: NodeRef | () fn sessions fn sessions(mux: MuxApi) -> Array Description Return every visible session. fn visible_buffers fn visible_buffers(mux: MuxApi) -> Array Description Return visible buffers in the current model snapshot.","breadcrumbs":"Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux » Mux","id":"16","title":"Mux"},"17":{"body":"Namespace: global fn buffer_id fn buffer_id(event: EventInfo) -> ? Description Return the buffer id attached to an event, or `()`. ReturnType: int | () fn client_id fn client_id(event: EventInfo) -> ? Description Return the client id attached to an event, or `()`. ReturnType: int | () fn floating_id fn floating_id(event: EventInfo) -> ? Description Return the floating id attached to an event, or `()`. ReturnType: int | () fn name fn name(event: EventInfo) -> String Description Return the event name. fn node_id fn node_id(event: EventInfo) -> ? Description Return the node id attached to an event, or `()`. ReturnType: int | () fn previous_session_id fn previous_session_id(event: EventInfo) -> ? Description Return the previous session id attached to an event, or `()`. ReturnType: int | () fn session_id fn session_id(event: EventInfo) -> ? Description Return the session id attached to an event, or `()`. ReturnType: int | ()","breadcrumbs":"EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo » EventInfo","id":"17","title":"EventInfo"},"18":{"body":"Namespace: global fn floating fn floating(session: SessionRef) -> Array Description Return floating window ids attached to the session. fn id fn id(session: SessionRef) -> int Description Return the numeric session id. fn name fn name(session: SessionRef) -> String Description Return the session name. fn root_node fn root_node(session: SessionRef) -> int Description Return the root tabs node for the session.","breadcrumbs":"SessionRef » SessionRef » SessionRef » SessionRef » SessionRef » SessionRef","id":"18","title":"SessionRef"},"19":{"body":"Namespace: global fn activity fn activity(buffer: BufferRef) -> String Description Return the current activity state name. fn command fn command(buffer: BufferRef) -> Array Description Return the original command vector. fn cwd fn cwd(buffer: BufferRef) -> ? Description Return the working directory, if any. ReturnType: string | () fn env_hint fn env_hint(buffer: BufferRef, key: String) -> ? Description Look up a single environment hint captured on the buffer. ReturnType: string | () fn exit_code fn exit_code(buffer: BufferRef) -> ? Description Return the process exit code, if any. ReturnType: int | () fn history_text fn history_text(buffer: BufferRef) -> String Description Example Return the full captured history text for the buffer. let buffer = ctx.current_buffer();\\nif buffer != () { let history = buffer.history_text();\\n} fn id fn id(buffer: BufferRef) -> int Description Return the numeric buffer id. fn is_attached fn is_attached(buffer: BufferRef) -> bool Description Return whether the buffer is currently attached to a node. fn is_detached fn is_detached(buffer: BufferRef) -> bool Description Return whether the buffer has been detached. fn is_running fn is_running(buffer: BufferRef) -> bool Description Return whether the buffer process is still running. fn is_visible fn is_visible(buffer: BufferRef) -> bool Description Return whether the buffer is visible in the current presentation. fn node_id fn node_id(buffer: BufferRef) -> ? Description Return the attached node id, if any. ReturnType: int | () fn pid fn pid(buffer: BufferRef) -> ? Description Return the process id, if any. ReturnType: int | () fn process_name fn process_name(buffer: BufferRef) -> ? Description Return the detected process name, if any. ReturnType: string | () fn session_id fn session_id(buffer: BufferRef) -> ? Description Return the attached session id, if any. ReturnType: int | () fn snapshot_text fn snapshot_text(buffer: BufferRef, limit: int) -> String Description Return a text snapshot limited to the requested line count. fn title fn title(buffer: BufferRef) -> String Description Return the buffer title. fn tty_path fn tty_path(buffer: BufferRef) -> ? Description Return the controlling TTY path, if any. ReturnType: string | ()","breadcrumbs":"BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef » BufferRef","id":"19","title":"BufferRef"},"2":{"body":"registration.rhai runtime.rhai","breadcrumbs":"Overview » Definitions","id":"2","title":"Definitions"},"20":{"body":"Namespace: global fn active_tab_index fn active_tab_index(node: NodeRef) -> ? Description Return the active tab index, if any. ReturnType: int | () fn buffer fn buffer(node: NodeRef) -> ? Description Return the attached buffer id, if any. ReturnType: int | () fn children fn children(node: NodeRef) -> Array Description Return child node ids. fn geometry fn geometry(node: NodeRef) -> ? Description Return the geometry map, if any. ReturnType: Map | () fn id fn id(node: NodeRef) -> int Description Return the node id. fn is_floating_root fn is_floating_root(node: NodeRef) -> bool Description Return whether the node is the root of a floating window. fn is_focused fn is_focused(node: NodeRef) -> bool Description Return whether the node is focused. fn is_root fn is_root(node: NodeRef) -> bool Description Return whether the node is the session root. fn is_visible fn is_visible(node: NodeRef) -> bool Description Return whether the node is visible in the current presentation. fn kind fn kind(node: NodeRef) -> String Description Return the node kind such as `buffer_view`, `split`, or `tabs`. fn parent fn parent(node: NodeRef) -> ? Description Return the parent node id, if any. ReturnType: int | () fn session_id fn session_id(node: NodeRef) -> int Description Return the owning session id. fn split_direction fn split_direction(node: NodeRef) -> ? Description Return the split direction, if any. ReturnType: string | () fn split_weights fn split_weights(node: NodeRef) -> ? Description Return split weights, if any. ReturnType: Array | () fn tab_titles fn tab_titles(node: NodeRef) -> Array Description Return tab titles on a tabs node.","breadcrumbs":"NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef » NodeRef","id":"20","title":"NodeRef"},"21":{"body":"Namespace: global fn geometry fn geometry(floating: FloatingRef) -> Map Description Return the floating geometry map. fn id fn id(floating: FloatingRef) -> int Description Return the floating id. fn is_focused fn is_focused(floating: FloatingRef) -> bool Description Return whether the floating is focused. fn is_visible fn is_visible(floating: FloatingRef) -> bool Description Return whether the floating is visible. fn root_node fn root_node(floating: FloatingRef) -> int Description Return the root node id. fn session_id fn session_id(floating: FloatingRef) -> int Description Return the owning session id. fn title fn title(floating: FloatingRef) -> ? Description Return the floating title, if any. ReturnType: string | ()","breadcrumbs":"FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef » FloatingRef","id":"21","title":"FloatingRef"},"22":{"body":"Namespace: global fn active_index fn active_index(bar: TabBarContext) -> int Description Return the active tab index. fn is_root fn is_root(bar: TabBarContext) -> bool Description Return whether the formatted tabs are the root tabs. fn mode fn mode(bar: TabBarContext) -> String Description Return the formatter mode name. fn node_id fn node_id(bar: TabBarContext) -> int Description Return the tabs node id currently being formatted. fn tabs fn tabs(bar: TabBarContext) -> Array Description Return tab metadata used by the formatter. fn viewport_width fn viewport_width(bar: TabBarContext) -> int Description Return the formatter viewport width in cells.","breadcrumbs":"TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext » TabBarContext","id":"22","title":"TabBarContext"},"23":{"body":"Namespace: global fn buffer_count fn buffer_count(tab: TabInfo) -> int Description Return how many buffers are attached to the tab. fn has_activity fn has_activity(tab: TabInfo) -> bool Description Return whether the tab has activity. fn has_bell fn has_bell(tab: TabInfo) -> bool Description Return whether the tab has a bell marker. fn index fn index(tab: TabInfo) -> int Description Return the zero-based tab index. fn is_active fn is_active(tab: TabInfo) -> bool Description Return whether the tab is active. fn title fn title(tab: TabInfo) -> String Description Return the tab title.","breadcrumbs":"TabInfo » TabInfo » TabInfo » TabInfo » TabInfo » TabInfo » TabInfo » TabInfo","id":"23","title":"TabInfo"},"24":{"body":"Namespace: global fn env fn env(_: SystemApi, name: String) -> ? Description Read an environment variable, if it is set. ReturnType: string | () fn now fn now(_: SystemApi) -> int Description Return the current Unix timestamp in seconds. fn which fn which(_: SystemApi, name: String) -> ? Description Resolve an executable from `PATH`, if it is found. ReturnType: string | ()","breadcrumbs":"System » System » System » System » System","id":"24","title":"System"},"25":{"body":"Namespace: global fn bar fn bar(_: UiApi, left: Array, center: Array, right: Array) -> BarSpec Description Build a full bar specification from left, center, and right segments. fn segment fn segment(_: UiApi, text: String) -> BarSegment\\nfn segment(_: UiApi, text: String, options: Map) -> BarSegment Description Create a [`BarSegment`] from a [`UiApi`] receiver and text using default styling. segment(_: UiApi, text: String) -> BarSegment produces plain text with default\\n[ StyleSpec] values and no click target.","breadcrumbs":"UI » UI » UI » UI","id":"25","title":"UI"},"26":{"body":"Namespace: global fn color fn color(theme: ThemeRuntimeApi, name: String) -> ? Description Read a named color from the active runtime palette, if it exists. ReturnType: RgbColor | ()","breadcrumbs":"Runtime Theme » Runtime Theme » Runtime Theme","id":"26","title":"Runtime Theme"},"3":{"body":"example.md","breadcrumbs":"Overview » Example","id":"3","title":"Example"},"4":{"body":"This is a trimmed example based on the repository fixture config. It shows the two main phases together. set_leader(\\"\\"); fn shell_tree(ctx) { tree.buffer_spawn( [\\"/bin/zsh\\"], #{ title: \\"shell\\", cwd: if ctx.current_buffer() == () { () } else { ctx.current_buffer().cwd() } } )\\n} fn split_below(ctx) { action.split_with(\\"horizontal\\", shell_tree(ctx))\\n} fn format_tabs(ctx) { let active = ctx.tabs()[ctx.active_index()]; ui.bar([ ui.segment(\\" \\" + active.title() + \\" \\", #{ fg: theme.color(\\"active_fg\\"), bg: theme.color(\\"active_bg\\") }) ], [], [])\\n} define_action(\\"split-below\\", split_below);\\nbind(\\"normal\\", \\"\\\\\\"\\", \\"split-below\\");\\ntheme.set_palette(#{ active_fg: \\"#303446\\", active_bg: \\"#c6d0f5\\"\\n});\\ntabbar.set_formatter(format_tabs);\\nmouse.set_click_focus(true);","breadcrumbs":"Example » Example","id":"4","title":"Example"},"5":{"body":"Namespace: global fn bind fn bind(mode: String, notation: String, action: Action)\\nfn bind(mode: String, notation: String, action_name: String)\\nfn bind(mode: String, notation: String, actions: Array) Description Example Bind a key notation to an [`Action`], a string action name, or an array of actions. Use the Action overload for inline builders such as action.focus_left(), the string\\noverload for a named action registered with define_action, or an array to chain multiple\\nactions in sequence. bind(\\"normal\\", \\"ws\\", \\"workspace-split\\"); fn define_action fn define_action(name: String, callback: FnPtr) Description Register a function pointer as a named action callable from bindings. fn define_mode fn define_mode(mode_name: String)\\nfn define_mode(mode_name: String, options: Map) Description Define a custom input mode with hooks and fallback options. Supported options are fallback, on_enter, and on_leave. fn on fn on(event_name: String, callback: FnPtr) Description Attach a callback to an emitted event such as `buffer_bell`. fn set_leader fn set_leader(notation: String) Description Example Set the leader sequence used in binding notations. set_leader(\\"\\"); fn unbind fn unbind(mode: String, notation: String) Description Remove a previously bound key sequence.","breadcrumbs":"Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals » Registration Globals","id":"5","title":"Registration Globals"},"6":{"body":"Namespace: global fn break_current_node fn break_current_node(_: ActionApi, destination: String) -> Action Description Break the current node into a new tab or floating window. fn cancel_search fn cancel_search(_: ActionApi) -> Action Description Cancel the active search. fn cancel_selection fn cancel_selection(_: ActionApi) -> Action Description Cancel the current selection. fn chain fn chain(_: ActionApi, actions: Array) -> Action Description Chain multiple actions into one composite action. fn clear_pending_keys fn clear_pending_keys(_: ActionApi) -> Action Description Clear any partially-entered key sequence. fn close_floating fn close_floating(_: ActionApi) -> Action Description Close the currently focused floating window. fn close_floating_id fn close_floating_id(_: ActionApi, floating_id: int) -> Action Description Close a floating window by id. fn close_node fn close_node(_: ActionApi, node_id: int) -> Action Description Close a view by node id. fn close_view fn close_view(_: ActionApi) -> Action Description Close the currently focused view. fn copy_selection fn copy_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard. fn detach_buffer fn detach_buffer(_: ActionApi) -> Action Description Detach the currently focused buffer. fn detach_buffer_id fn detach_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Detach a buffer by id. fn enter_mode fn enter_mode(_: ActionApi, mode: String) -> Action Description Enter a specific input mode by name. fn enter_search_mode fn enter_search_mode(_: ActionApi) -> Action Description Enter incremental search mode. fn enter_select_block fn enter_select_block(_: ActionApi) -> Action Description Enter block selection mode. fn enter_select_char fn enter_select_char(_: ActionApi) -> Action Description Enter character selection mode. fn enter_select_line fn enter_select_line(_: ActionApi) -> Action Description Enter line selection mode. fn focus_buffer fn focus_buffer(_: ActionApi, buffer_id: int) -> Action Description Focus a specific buffer by id. fn focus_down fn focus_down(_: ActionApi) -> Action Description Focus the view below the current node. fn focus_left fn focus_left(_: ActionApi) -> Action Description Example Focus the view to the left of the current node. action.focus_left() fn focus_right fn focus_right(_: ActionApi) -> Action Description Focus the view to the right of the current node. fn focus_up fn focus_up(_: ActionApi) -> Action Description Focus the view above the current node. fn follow_output fn follow_output(_: ActionApi) -> Action Description Re-enable following live output. fn insert_tab_after fn insert_tab_after(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab after a specific tabs node. fn insert_tab_after_current fn insert_tab_after_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab after the current tab in the focused tabs node. fn insert_tab_before fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: String, tree: TreeSpec) -> Action Description Insert a tab before a specific tabs node. fn insert_tab_before_current fn insert_tab_before_current(_: ActionApi, title: String, tree: TreeSpec) -> Action Description Insert a tab before the current tab. fn join_buffer_here fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action Description Join a buffer at the current node. fn kill_buffer fn kill_buffer(_: ActionApi) -> Action Description Kill the currently focused buffer. fn kill_buffer_id fn kill_buffer_id(_: ActionApi, buffer_id: int) -> Action Description Kill a buffer by id. fn leave_mode fn leave_mode(_: ActionApi) -> Action Description Leave the active input mode. fn move_buffer_to_floating fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: Map) -> Action Description Options Move a buffer into a new floating window. x (i16): horizontal offset from the anchor (default: 0) y (i16): vertical offset from the anchor (default: 0) width (FloatingSize): window width, as a percentage (e.g., 50%) or pixel value (default: 50%) height (FloatingSize): window height, as a percentage or pixel value (default: 50%) anchor (FloatingAnchor): anchor point for positioning, e.g., “top_left”, “center” (default: center) title (Option): window title (default: none) focus (bool): whether to focus the window after creation (default: true) close_on_empty (bool): whether to close the window when its buffer empties (default: true) fn move_buffer_to_node fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action Description Move a buffer into a specific node. fn move_current_node_before fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action Description Move the current node before a sibling. fn move_node_after fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action Description Move a node after a sibling. fn next_current_tabs fn next_current_tabs(_: ActionApi) -> Action Description Select the next tab in the currently focused tabs node. fn next_tab fn next_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the next tab in a specific tabs node. fn noop fn noop(_: ActionApi) -> Action Description Build a no-op action. fn notify fn notify(_: ActionApi, level: String, message: String) -> Action Description Emit a client notification. fn open_buffer_history fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action Description Open the history of a buffer in a new view. fn open_floating fn open_floating(_: ActionApi, tree: TreeSpec, options: Map) -> Action Description Open a floating view around the provided tree. fn prev_current_tabs fn prev_current_tabs(_: ActionApi) -> Action Description Select the previous tab in the currently focused tabs node. fn prev_tab fn prev_tab(_: ActionApi, tabs_node_id: int) -> Action Description Select the previous tab in a specific tabs node. fn replace_current_with fn replace_current_with(_: ActionApi, tree: TreeSpec) -> Action Description Replace the focused node with a new tree. fn replace_node fn replace_node(_: ActionApi, node_id: int, tree: TreeSpec) -> Action Description Replace a specific node by id with a new tree. fn reveal_buffer fn reveal_buffer(_: ActionApi, buffer_id: int) -> Action Description Reveal a specific buffer by id. fn run_named_action fn run_named_action(_: ActionApi, name: String) -> Action Description Run another named action by name. fn scroll_line_down fn scroll_line_down(_: ActionApi) -> Action Description Scroll one line downward in local scrollback. fn scroll_line_up fn scroll_line_up(_: ActionApi) -> Action Description Scroll one line upward in local scrollback. fn scroll_page_down fn scroll_page_down(_: ActionApi) -> Action Description Scroll one page downward in local scrollback. fn scroll_page_up fn scroll_page_up(_: ActionApi) -> Action Description Scroll one page upward in local scrollback. fn scroll_to_bottom fn scroll_to_bottom(_: ActionApi) -> Action Description Scroll to the bottom of local scrollback. fn scroll_to_top fn scroll_to_top(_: ActionApi) -> Action Description Scroll to the top of local scrollback. fn search_next fn search_next(_: ActionApi) -> Action Description Jump to the next search match. fn search_prev fn search_prev(_: ActionApi) -> Action Description Jump to the previous search match. fn select_current_tabs fn select_current_tabs(_: ActionApi, index: int) -> Action Description Select a tab by index in the currently focused tabs node. fn select_move_down fn select_move_down(_: ActionApi) -> Action Description Move the active selection down. fn select_move_left fn select_move_left(_: ActionApi) -> Action Description Move the active selection left. fn select_move_right fn select_move_right(_: ActionApi) -> Action Description Move the active selection right. fn select_move_up fn select_move_up(_: ActionApi) -> Action Description Move the active selection up. fn select_tab fn select_tab(_: ActionApi, tabs_node_id: int, index: int) -> Action Description Select a tab by index in a specific tabs node. fn send_bytes fn send_bytes(_: ActionApi, buffer_id: int, bytes: String) -> Action\\nfn send_bytes(_: ActionApi, buffer_id: int, bytes: Array) -> Action Description Send a string of bytes to a specific buffer. fn send_bytes_current fn send_bytes_current(_: ActionApi, bytes: String) -> Action\\nfn send_bytes_current(_: ActionApi, bytes: Array) -> Action Description Send a string of bytes to the focused buffer. fn send_keys fn send_keys(_: ActionApi, buffer_id: int, notation: String) -> Action Description Send a key notation sequence to a specific buffer. fn send_keys_current fn send_keys_current(_: ActionApi, notation: String) -> Action Description Send a key notation sequence to the focused buffer. fn split_with fn split_with(_: ActionApi, direction: String, tree: TreeSpec) -> Action Description Split the current node and attach the provided tree as the new sibling. fn swap_current_node fn swap_current_node(_: ActionApi, second_node_id: int) -> Action Description Swap the current node with a sibling. fn toggle_mode fn toggle_mode(_: ActionApi, mode: String) -> Action Description Toggle a named input mode. fn toggle_zoom_node fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action Description Toggle zoom on a node. fn unzoom_current_session fn unzoom_current_session(_: ActionApi) -> Action Description Unzoom the current session. fn yank_selection fn yank_selection(_: ActionApi) -> Action Description Copy the current selection into the clipboard. fn zoom_current_node fn zoom_current_node(_: ActionApi) -> Action Description Zoom the current node.","breadcrumbs":"Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration) » Action (Registration)","id":"6","title":"Action (Registration)"},"7":{"body":"Namespace: global fn buffer_attach fn buffer_attach(_: TreeApi, buffer_id: int) -> TreeSpec Description Attach an existing buffer by id. fn buffer_current fn buffer_current(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn buffer_empty fn buffer_empty(_: TreeApi) -> TreeSpec Description Build an empty buffer tree node. fn buffer_spawn fn buffer_spawn(_: TreeApi, command: Array) -> TreeSpec\\nfn buffer_spawn(_: TreeApi, command: Array, options: Map) -> TreeSpec Description Example Spawn a new buffer from a command array. Supported options keys are title ( string), cwd ( string), and env\\n( map). Unknown keys are rejected. tree.buffer_spawn([\\"/bin/zsh\\"], #{ title: \\"shell\\" }) fn current_buffer fn current_buffer(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused buffer. fn current_node fn current_node(_: TreeApi) -> TreeSpec Description Build a tree reference to the currently focused node. fn split fn split(_: TreeApi, direction: String, children: Array) -> TreeSpec\\nfn split(_: TreeApi, direction: String, children: Array, sizes: Array) -> TreeSpec Description Build a split with an explicit direction string. fn split_h fn split_h(_: TreeApi, children: Array) -> TreeSpec Description Build a horizontal split. fn split_v fn split_v(_: TreeApi, children: Array) -> TreeSpec Description Build a vertical split. fn tab fn tab(_: TreeApi, title: String, tree: TreeSpec) -> TabSpec Description Build a single tab specification. fn tabs fn tabs(_: TreeApi, tabs: Array) -> TreeSpec Description Build a tabs container with the first tab active. fn tabs_with_active fn tabs_with_active(_: TreeApi, tabs: Array, active: int) -> TreeSpec Description Build a tabs container with an explicit active tab.","breadcrumbs":"Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration) » Tree (Registration)","id":"7","title":"Tree (Registration)"},"8":{"body":"Namespace: global fn env fn env(_: SystemApi, name: String) -> ? Description Read an environment variable, if it is set. ReturnType: string | () fn now fn now(_: SystemApi) -> int Description Return the current Unix timestamp in seconds. fn which fn which(_: SystemApi, name: String) -> ? Description Resolve an executable from `PATH`, if it is found. ReturnType: string | ()","breadcrumbs":"System (Registration) » System (Registration) » System (Registration) » System (Registration) » System (Registration)","id":"8","title":"System (Registration)"},"9":{"body":"Namespace: global fn bar fn bar(_: UiApi, left: Array, center: Array, right: Array) -> BarSpec Description Build a full bar specification from left, center, and right segments. fn segment fn segment(_: UiApi, text: String) -> BarSegment\\nfn segment(_: UiApi, text: String, options: Map) -> BarSegment Description Create a [`BarSegment`] from a [`UiApi`] receiver and text using default styling. segment(_: UiApi, text: String) -> BarSegment produces plain text with default\\n[ StyleSpec] values and no click target.","breadcrumbs":"UI (Registration) » UI (Registration) » UI (Registration) » UI (Registration)","id":"9","title":"UI (Registration)"}},"length":27,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"3":{"0":{"3":{"4":{"4":{"6":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"a":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"\\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":8.602325267042627},"6":{"tf":8.602325267042627}}}}},"df":5,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"13":{"tf":8.94427190999916},"5":{"tf":3.1622776601683795},"6":{"tf":8.94427190999916}}}},"v":{"df":11,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}},"t":{"a":{"b":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"d":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"g":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":13,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":3.1622776601683795},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":1.0},"25":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":3.1622776601683795},"9":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":10,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"17":{"tf":2.449489742783178},"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"23":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"12":{"tf":1.0},"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":2,"docs":{"25":{"tf":2.0},"9":{"tf":2.0}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":1,"docs":{"22":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}}}},"h":{"a":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"w":{"df":3,"docs":{"13":{"tf":1.0},"4":{"tf":1.4142135623730951},"6":{"tf":1.0}}}}}},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"d":{"(":{"\\"":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"df":2,"docs":{"0":{"tf":1.0},"5":{"tf":2.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":8,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"k":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},".":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}}},"_":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":1,"docs":{"23":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":3.3166247903554},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":3.3166247903554},"7":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":12,"docs":{"1":{"tf":1.0},"10":{"tf":1.4142135623730951},"13":{"tf":3.872983346207417},"14":{"tf":2.23606797749979},"15":{"tf":2.449489742783178},"16":{"tf":2.0},"17":{"tf":1.0},"19":{"tf":3.1622776601683795},"20":{"tf":1.4142135623730951},"23":{"tf":1.0},"6":{"tf":3.872983346207417},"7":{"tf":2.23606797749979}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":4.358898943540674}}}}}}}}},"i":{"df":0,"docs":{},"l":{"d":{"df":6,"docs":{"13":{"tf":1.0},"14":{"tf":3.1622776601683795},"25":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":3.1622776601683795},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}},"df":0,"docs":{}}}},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}},"c":{"6":{"d":{"0":{"df":0,"docs":{},"f":{"5":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"h":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"13":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.4142135623730951}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"d":{"df":1,"docs":{"20":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":3,"docs":{"14":{"tf":2.0},"20":{"tf":1.0},"7":{"tf":2.0}}}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":5,"docs":{"0":{"tf":1.0},"10":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"b":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":2,"docs":{"11":{"tf":1.0},"26":{"tf":1.4142135623730951}}}}},"m":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"7":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"0":{"tf":1.4142135623730951},"4":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"15":{"tf":3.605551275463989}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"x":{".":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{")":{".":{"c":{"df":0,"docs":{},"w":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{")":{"[":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{".":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"15":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"d":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}}},"df":11,"docs":{"13":{"tf":4.795831523312719},"14":{"tf":1.7320508075688772},"15":{"tf":2.6457513110645907},"16":{"tf":2.449489742783178},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.0},"6":{"tf":4.795831523312719},"7":{"tf":1.7320508075688772},"8":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"w":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"25":{"tf":1.4142135623730951},"6":{"tf":2.8284271247461903},"9":{"tf":1.4142135623730951}}}}}},"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.4142135623730951}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"\\"":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}},"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"2":{"tf":1.0}}}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":22,"docs":{"10":{"tf":2.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":8.48528137423857},"14":{"tf":3.4641016151377544},"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.242640687119285},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.7320508075688772},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"5":{"tf":2.449489742783178},"6":{"tf":8.48528137423857},"7":{"tf":3.4641016151377544},"8":{"tf":1.7320508075688772},"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"t":{"a":{"c":{"df":0,"docs":{},"h":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":5,"docs":{"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"16":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.4142135623730951}},"e":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":5,"docs":{"13":{"tf":1.0},"14":{"tf":1.7320508075688772},"20":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.7320508075688772}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}},"v":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":4,"docs":{"14":{"tf":1.0},"24":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"10":{"tf":1.0},"15":{"tf":1.4142135623730951},"17":{"tf":2.6457513110645907},"5":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":2,"docs":{"15":{"tf":1.0},"17":{"tf":2.8284271247461903}}}}}}}}}},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"19":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.4142135623730951},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0}},"e":{".":{"df":0,"docs":{},"m":{"d":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"26":{"tf":1.0},"7":{"tf":1.0}}}},"t":{"_":{"c":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"f":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":9,"docs":{"1":{"tf":1.0},"13":{"tf":2.23606797749979},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":5,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"21":{"tf":2.8284271247461903}}}}},"s":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}},"n":{"df":23,"docs":{"10":{"tf":2.8284271247461903},"11":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951},"13":{"tf":12.083045973594572},"14":{"tf":5.0990195135927845},"15":{"tf":4.898979485566356},"16":{"tf":4.47213595499958},"17":{"tf":3.7416573867739413},"18":{"tf":2.8284271247461903},"19":{"tf":6.0},"20":{"tf":5.477225575051661},"21":{"tf":3.7416573867739413},"22":{"tf":3.4641016151377544},"23":{"tf":3.4641016151377544},"24":{"tf":2.449489742783178},"25":{"tf":2.23606797749979},"26":{"tf":1.4142135623730951},"4":{"tf":1.7320508075688772},"5":{"tf":3.872983346207417},"6":{"tf":12.083045973594572},"7":{"tf":5.0990195135927845},"8":{"tf":2.449489742783178},"9":{"tf":2.23606797749979}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}}}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.6457513110645907},"6":{"tf":2.6457513110645907}},"s":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":9,"docs":{"10":{"tf":1.4142135623730951},"13":{"tf":3.3166247903554},"14":{"tf":1.7320508075688772},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"6":{"tf":3.3166247903554},"7":{"tf":1.7320508075688772}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"12":{"tf":1.0},"22":{"tf":1.4142135623730951}},"t":{"df":2,"docs":{"0":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":3,"docs":{"19":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951}}},"y":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"l":{"df":0,"docs":{},"o":{"b":{"a":{"df":0,"docs":{},"l":{"df":23,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"df":0,"docs":{}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":3,"docs":{"13":{"tf":1.0},"19":{"tf":1.4142135623730951},"6":{"tf":1.0}}},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}}}}}},"i":{"1":{"6":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"21":{"tf":1.0}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":12,"docs":{"13":{"tf":2.6457513110645907},"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.7320508075688772},"19":{"tf":2.23606797749979},"20":{"tf":2.449489742783178},"21":{"tf":2.0},"22":{"tf":1.0},"6":{"tf":2.6457513110645907},"7":{"tf":1.0}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":5,"docs":{"13":{"tf":2.0},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"6":{"tf":2.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.7320508075688772},"15":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"_":{"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"t":{"df":15,"docs":{"13":{"tf":5.196152422706632},"14":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.4142135623730951},"19":{"tf":2.449489742783178},"20":{"tf":2.23606797749979},"21":{"tf":1.7320508075688772},"22":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"6":{"tf":5.196152422706632},"7":{"tf":1.4142135623730951},"8":{"tf":1.0}}}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"d":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":2,"docs":{"20":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":3,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"i":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"j":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":6,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"19":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"n":{"d":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{">":{"df":0,"docs":{},"w":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}},"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"19":{"tf":1.0},"6":{"tf":1.7320508075688772}}}},"v":{"df":0,"docs":{},"e":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"13":{"tf":1.0},"6":{"tf":1.0}}}}},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"23":{"tf":1.0}}}},"p":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":10,"docs":{"11":{"tf":1.0},"13":{"tf":1.4142135623730951},"14":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.4142135623730951},"7":{"tf":1.0},"9":{"tf":1.0}}},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"a":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"e":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"13":{"tf":3.0},"15":{"tf":1.0},"22":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":3.0}},"l":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"10":{"tf":1.4142135623730951}},"e":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":2.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":2.8284271247461903},"6":{"tf":2.8284271247461903}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"x":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"16":{"tf":3.1622776601683795}}}}},"df":2,"docs":{"1":{"tf":1.0},"16":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":13,"docs":{"0":{"tf":1.4142135623730951},"11":{"tf":1.0},"13":{"tf":2.23606797749979},"15":{"tf":1.0},"17":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"5":{"tf":1.7320508075688772},"6":{"tf":2.23606797749979},"8":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":22,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":4,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.0}}},"x":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}}}},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":2.23606797749979},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"19":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":2.23606797749979}}},"df":0,"docs":{}}},"df":13,"docs":{"1":{"tf":1.0},"13":{"tf":5.0},"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":3.0},"21":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":5.0},"7":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"20":{"tf":4.0}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":2.0},"5":{"tf":2.449489742783178},"6":{"tf":2.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"w":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"n":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"p":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":7,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":3,"docs":{"1":{"tf":1.0},"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":2,"docs":{"11":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"h":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"19":{"tf":1.0},"20":{"tf":1.0}}}}}},"v":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"17":{"tf":1.0},"6":{"tf":1.7320508075688772}},"s":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"5":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":1,"docs":{"19":{"tf":2.0}}}}}},"d":{"df":0,"docs":{},"u":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"24":{"tf":1.0},"26":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"f":{"df":1,"docs":{"1":{"tf":2.0}},"e":{"df":0,"docs":{},"r":{"df":5,"docs":{"0":{"tf":1.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.7320508075688772}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":7,"docs":{"0":{"tf":1.0},"1":{"tf":2.23606797749979},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}},"e":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"v":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":11,"docs":{"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.123105625617661},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.0},"8":{"tf":1.0}},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":9,"docs":{"15":{"tf":2.8284271247461903},"16":{"tf":2.6457513110645907},"17":{"tf":2.449489742783178},"19":{"tf":2.8284271247461903},"20":{"tf":2.449489742783178},"21":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"8":{"tf":1.4142135623730951}}}}}}}}},"v":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"b":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"18":{"tf":1.0},"21":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":4,"docs":{"18":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"d":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951}},"e":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"s":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"o":{"_":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}},"df":0,"docs":{}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.7320508075688772},"9":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"df":2,"docs":{"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":4.0},"6":{"tf":4.0}}}},"df":0,"docs":{}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}},"df":0,"docs":{}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":4,"docs":{"17":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}},"df":0,"docs":{}}},"df":10,"docs":{"1":{"tf":1.0},"13":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":1.4142135623730951},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"6":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":2.23606797749979}}}}},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"10":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"\\"":{"<":{"c":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"11":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"5":{"tf":1.0},"8":{"tf":1.0}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"4":{"tf":1.0}}}}},"i":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"7":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":6,"docs":{"13":{"tf":3.4641016151377544},"14":{"tf":1.0},"25":{"tf":1.0},"6":{"tf":3.4641016151377544},"7":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"v":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":7,"docs":{"13":{"tf":1.0},"14":{"tf":2.0},"20":{"tf":1.7320508075688772},"4":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":2.0}}}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"19":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":18,"docs":{"13":{"tf":4.47213595499958},"14":{"tf":2.6457513110645907},"15":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":3.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":2.0},"25":{"tf":1.7320508075688772},"26":{"tf":1.0},"5":{"tf":4.0},"6":{"tf":4.47213595499958},"7":{"tf":2.6457513110645907},"8":{"tf":2.0},"9":{"tf":1.7320508075688772}}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"u":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"20":{"tf":1.0},"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"5":{"tf":1.0},"7":{"tf":1.0}}}}}}}},"w":{"a":{"df":0,"docs":{},"p":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"24":{"tf":1.7320508075688772},"8":{"tf":1.7320508075688772}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"20":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"b":{"a":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"12":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":2.6457513110645907}}}}}}}}},"df":2,"docs":{"1":{"tf":1.0},"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":4.69041575982343},"14":{"tf":3.0},"18":{"tf":1.0},"20":{"tf":2.0},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"6":{"tf":4.69041575982343},"7":{"tf":3.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":2.6457513110645907}}}}}},"s":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":3,"docs":{"19":{"tf":1.4142135623730951},"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"\\"":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"11":{"tf":1.0}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"11":{"tf":1.4142135623730951},"26":{"tf":1.0}},"r":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.0}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"p":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{".":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"[":{"\\"":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":3.7416573867739413},"7":{"tf":3.7416573867739413}}}}},"df":5,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":3.4641016151377544},"14":{"tf":2.449489742783178},"6":{"tf":3.4641016151377544},"7":{"tf":2.449489742783178}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"14":{"tf":3.7416573867739413},"6":{"tf":2.8284271247461903},"7":{"tf":3.7416573867739413}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}},"y":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"i":{".":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"25":{"tf":1.0},"9":{"tf":1.0}}},"n":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"k":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}}},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"p":{"df":3,"docs":{"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":6,"docs":{"0":{"tf":1.0},"12":{"tf":1.0},"22":{"tf":1.0},"25":{"tf":1.0},"5":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":5,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"25":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"13":{"tf":2.8284271247461903},"6":{"tf":2.8284271247461903}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"l":{"df":5,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":7,"docs":{"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}}}}},"i":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"22":{"tf":1.0},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":6,"docs":{"13":{"tf":3.0},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"18":{"tf":1.0},"20":{"tf":1.0},"6":{"tf":3.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"x":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"z":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"breadcrumbs":{"root":{"0":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"3":{"0":{"3":{"4":{"4":{"6":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"a":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"\\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":8.602325267042627},"6":{"tf":8.602325267042627}}}}},"df":5,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"13":{"tf":12.409673645990857},"5":{"tf":3.1622776601683795},"6":{"tf":12.409673645990857}}}},"v":{"df":11,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}},"t":{"a":{"b":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"d":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"g":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":13,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":3.1622776601683795},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":1.0},"25":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":3.1622776601683795},"9":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":10,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"17":{"tf":2.449489742783178},"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"23":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"12":{"tf":1.0},"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":2,"docs":{"25":{"tf":2.0},"9":{"tf":2.0}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":1,"docs":{"22":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}}}},"h":{"a":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"w":{"df":3,"docs":{"13":{"tf":1.0},"4":{"tf":1.4142135623730951},"6":{"tf":1.0}}}}}},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"d":{"(":{"\\"":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"df":2,"docs":{"0":{"tf":1.0},"5":{"tf":2.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":8,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"k":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},".":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}}},"_":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":1,"docs":{"23":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":3.3166247903554},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":3.3166247903554},"7":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":12,"docs":{"1":{"tf":1.0},"10":{"tf":1.4142135623730951},"13":{"tf":3.872983346207417},"14":{"tf":2.23606797749979},"15":{"tf":2.449489742783178},"16":{"tf":2.0},"17":{"tf":1.0},"19":{"tf":3.1622776601683795},"20":{"tf":1.4142135623730951},"23":{"tf":1.0},"6":{"tf":3.872983346207417},"7":{"tf":2.23606797749979}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":6.244997998398398}}}}}}}}},"i":{"df":0,"docs":{},"l":{"d":{"df":6,"docs":{"13":{"tf":1.0},"14":{"tf":3.1622776601683795},"25":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":3.1622776601683795},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}},"df":0,"docs":{}}}},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}},"c":{"6":{"d":{"0":{"df":0,"docs":{},"f":{"5":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"h":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"13":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.4142135623730951}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"d":{"df":1,"docs":{"20":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":3,"docs":{"14":{"tf":2.0},"20":{"tf":1.0},"7":{"tf":2.0}}}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":5,"docs":{"0":{"tf":1.0},"10":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"b":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":2,"docs":{"11":{"tf":1.0},"26":{"tf":1.4142135623730951}}}}},"m":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"7":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"0":{"tf":1.7320508075688772},"4":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"15":{"tf":5.196152422706632}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"x":{".":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{")":{".":{"c":{"df":0,"docs":{},"w":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{")":{"[":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{".":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"15":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"d":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}}},"df":11,"docs":{"13":{"tf":4.795831523312719},"14":{"tf":1.7320508075688772},"15":{"tf":2.6457513110645907},"16":{"tf":2.449489742783178},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"22":{"tf":1.0},"24":{"tf":1.0},"6":{"tf":4.795831523312719},"7":{"tf":1.7320508075688772},"8":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"w":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"25":{"tf":1.4142135623730951},"6":{"tf":2.8284271247461903},"9":{"tf":1.4142135623730951}}}}}},"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.4142135623730951}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"\\"":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}},"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"2":{"tf":1.4142135623730951}}}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":22,"docs":{"10":{"tf":2.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":8.48528137423857},"14":{"tf":3.4641016151377544},"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.242640687119285},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.7320508075688772},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"5":{"tf":2.449489742783178},"6":{"tf":8.48528137423857},"7":{"tf":3.4641016151377544},"8":{"tf":1.7320508075688772},"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"t":{"a":{"c":{"df":0,"docs":{},"h":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":5,"docs":{"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"16":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.4142135623730951}},"e":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":5,"docs":{"13":{"tf":1.0},"14":{"tf":1.7320508075688772},"20":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.7320508075688772}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.7320508075688772}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}},"v":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":4,"docs":{"14":{"tf":1.0},"24":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"10":{"tf":1.0},"15":{"tf":1.4142135623730951},"17":{"tf":2.6457513110645907},"5":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":2,"docs":{"15":{"tf":1.0},"17":{"tf":4.123105625617661}}}}}}}}}},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"19":{"tf":1.0},"3":{"tf":1.4142135623730951},"4":{"tf":2.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0}},"e":{".":{"df":0,"docs":{},"m":{"d":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"26":{"tf":1.0},"7":{"tf":1.0}}}},"t":{"_":{"c":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"f":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.4142135623730951}}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":9,"docs":{"1":{"tf":1.0},"13":{"tf":2.23606797749979},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":5,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"a":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"21":{"tf":4.123105625617661}}}}},"s":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}},"n":{"df":23,"docs":{"10":{"tf":2.8284271247461903},"11":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951},"13":{"tf":12.083045973594572},"14":{"tf":5.0990195135927845},"15":{"tf":4.898979485566356},"16":{"tf":4.47213595499958},"17":{"tf":3.7416573867739413},"18":{"tf":2.8284271247461903},"19":{"tf":6.0},"20":{"tf":5.477225575051661},"21":{"tf":3.7416573867739413},"22":{"tf":3.4641016151377544},"23":{"tf":3.4641016151377544},"24":{"tf":2.449489742783178},"25":{"tf":2.23606797749979},"26":{"tf":1.4142135623730951},"4":{"tf":1.7320508075688772},"5":{"tf":3.872983346207417},"6":{"tf":12.083045973594572},"7":{"tf":5.0990195135927845},"8":{"tf":2.449489742783178},"9":{"tf":2.23606797749979}},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}}}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.6457513110645907},"6":{"tf":2.6457513110645907}},"s":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":9,"docs":{"10":{"tf":1.4142135623730951},"13":{"tf":3.3166247903554},"14":{"tf":1.7320508075688772},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"6":{"tf":3.3166247903554},"7":{"tf":1.7320508075688772}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"12":{"tf":1.0},"22":{"tf":1.4142135623730951}},"t":{"df":2,"docs":{"0":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":3,"docs":{"19":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951}}},"y":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"l":{"df":0,"docs":{},"o":{"b":{"a":{"df":0,"docs":{},"l":{"df":23,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":3.1622776601683795},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"df":0,"docs":{}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":3,"docs":{"13":{"tf":1.0},"19":{"tf":1.4142135623730951},"6":{"tf":1.0}}},"y":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"5":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}}}}}}}}},"i":{"1":{"6":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"21":{"tf":1.0}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":12,"docs":{"13":{"tf":2.6457513110645907},"14":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.7320508075688772},"19":{"tf":2.23606797749979},"20":{"tf":2.449489742783178},"21":{"tf":2.0},"22":{"tf":1.0},"6":{"tf":2.6457513110645907},"7":{"tf":1.0}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":5,"docs":{"13":{"tf":2.0},"20":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"6":{"tf":2.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.7320508075688772},"15":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"_":{"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}}}},"t":{"df":15,"docs":{"13":{"tf":5.196152422706632},"14":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":2.449489742783178},"18":{"tf":1.4142135623730951},"19":{"tf":2.449489742783178},"20":{"tf":2.23606797749979},"21":{"tf":1.7320508075688772},"22":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"6":{"tf":5.196152422706632},"7":{"tf":1.4142135623730951},"8":{"tf":1.0}}}},"s":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"d":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":2,"docs":{"20":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":3,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"i":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"j":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":6,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"19":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"i":{"d":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"n":{"d":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{">":{"df":0,"docs":{},"w":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}}}},"df":0,"docs":{},"v":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"19":{"tf":1.0},"6":{"tf":1.7320508075688772}}}},"v":{"df":0,"docs":{},"e":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"13":{"tf":1.0},"6":{"tf":1.0}}}}},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"23":{"tf":1.0}}}},"p":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":10,"docs":{"11":{"tf":1.0},"13":{"tf":1.4142135623730951},"14":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.4142135623730951},"7":{"tf":1.0},"9":{"tf":1.0}}},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"a":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"e":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"0":{"tf":1.0},"13":{"tf":3.0},"15":{"tf":1.0},"22":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":3.0}},"l":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"10":{"tf":2.8284271247461903}},"e":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":2.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":2.8284271247461903},"6":{"tf":2.8284271247461903}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}}}}},"x":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"16":{"tf":3.1622776601683795}}}}},"df":2,"docs":{"1":{"tf":1.0},"16":{"tf":3.605551275463989}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":13,"docs":{"0":{"tf":1.4142135623730951},"11":{"tf":1.0},"13":{"tf":2.23606797749979},"15":{"tf":1.0},"17":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"5":{"tf":1.7320508075688772},"6":{"tf":2.23606797749979},"8":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":22,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":4,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.0}}},"x":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}}}},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":7,"docs":{"13":{"tf":2.23606797749979},"15":{"tf":1.0},"16":{"tf":1.0},"17":{"tf":1.0},"19":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":2.23606797749979}}},"df":0,"docs":{}}},"df":13,"docs":{"1":{"tf":1.0},"13":{"tf":5.0},"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":3.0},"21":{"tf":1.0},"22":{"tf":1.0},"6":{"tf":5.0},"7":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"20":{"tf":5.744562646538029}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":2.0},"5":{"tf":2.449489742783178},"6":{"tf":2.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"w":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"18":{"tf":1.0},"19":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}},"n":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"_":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"p":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"<":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":7,"docs":{"13":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"25":{"tf":1.0},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":4,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"2":{"tf":1.0},"3":{"tf":1.0}}}}}}}}},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":3,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":2,"docs":{"11":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"19":{"tf":1.0},"24":{"tf":1.0},"8":{"tf":1.0}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"h":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"5":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"19":{"tf":1.0},"20":{"tf":1.0}}}}}},"v":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"17":{"tf":1.0},"6":{"tf":1.7320508075688772}},"s":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}}},"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"5":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":1,"docs":{"19":{"tf":2.0}}}}}},"d":{"df":0,"docs":{},"u":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"24":{"tf":1.0},"26":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"f":{"df":1,"docs":{"1":{"tf":2.0}},"e":{"df":0,"docs":{},"r":{"df":5,"docs":{"0":{"tf":1.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"16":{"tf":1.0},"7":{"tf":1.7320508075688772}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.4142135623730951}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":7,"docs":{"0":{"tf":1.0},"1":{"tf":2.23606797749979},"5":{"tf":3.0},"6":{"tf":8.660254037844387},"7":{"tf":3.872983346207417},"8":{"tf":2.449489742783178},"9":{"tf":2.23606797749979}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":1,"docs":{"5":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}},"e":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"v":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":11,"docs":{"15":{"tf":3.4641016151377544},"16":{"tf":3.1622776601683795},"17":{"tf":2.6457513110645907},"18":{"tf":2.0},"19":{"tf":4.123105625617661},"20":{"tf":3.872983346207417},"21":{"tf":2.6457513110645907},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"24":{"tf":1.0},"8":{"tf":1.0}},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":9,"docs":{"15":{"tf":2.8284271247461903},"16":{"tf":2.6457513110645907},"17":{"tf":2.449489742783178},"19":{"tf":2.8284271247461903},"20":{"tf":2.449489742783178},"21":{"tf":1.0},"24":{"tf":1.4142135623730951},"26":{"tf":1.0},"8":{"tf":1.4142135623730951}}}}}}}}},"v":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"l":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"b":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"18":{"tf":1.0},"21":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":4,"docs":{"18":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"d":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"26":{"tf":2.23606797749979}},"e":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"i":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"s":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"o":{"_":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"10":{"tf":1.0},"13":{"tf":2.449489742783178},"6":{"tf":2.449489742783178}}}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}}},"df":0,"docs":{}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"25":{"tf":1.7320508075688772},"9":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"df":2,"docs":{"25":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}}},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"u":{"df":0,"docs":{},"p":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":2,"docs":{"13":{"tf":4.0},"6":{"tf":4.0}}}},"df":0,"docs":{}}},"n":{"d":{"_":{"b":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"s":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}}},"df":0,"docs":{}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"5":{"tf":1.7320508075688772},"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"_":{"df":0,"docs":{},"i":{"d":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"17":{"tf":1.0}}}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":4,"docs":{"17":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}},"df":0,"docs":{}}},"df":10,"docs":{"1":{"tf":1.0},"13":{"tf":1.0},"15":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"17":{"tf":1.4142135623730951},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"6":{"tf":1.0}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":3,"docs":{"15":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":3.3166247903554}}}}},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}},"t":{"_":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"10":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"a":{"b":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"l":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"5":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"\\"":{"<":{"c":{"df":2,"docs":{"4":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"5":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"11":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"s":{"c":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.0}},"l":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"5":{"tf":1.0},"8":{"tf":1.0}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"4":{"tf":1.0},"7":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"4":{"tf":1.0}}}}},"i":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"13":{"tf":2.0},"6":{"tf":2.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"7":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":3,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":6,"docs":{"13":{"tf":3.4641016151377544},"14":{"tf":1.0},"25":{"tf":1.0},"6":{"tf":3.4641016151377544},"7":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.4142135623730951},"7":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"(":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"x":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"v":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":7,"docs":{"13":{"tf":1.0},"14":{"tf":2.0},"20":{"tf":1.7320508075688772},"4":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":2.0}}}}}},"t":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"0":{"tf":1.0},"19":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":18,"docs":{"13":{"tf":4.47213595499958},"14":{"tf":2.6457513110645907},"15":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":3.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":2.0},"25":{"tf":1.7320508075688772},"26":{"tf":1.0},"5":{"tf":4.0},"6":{"tf":4.47213595499958},"7":{"tf":2.6457513110645907},"8":{"tf":2.0},"9":{"tf":1.7320508075688772}}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"u":{"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"20":{"tf":1.0},"5":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"5":{"tf":1.0},"7":{"tf":1.0}}}}}}}},"w":{"a":{"df":0,"docs":{},"p":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"24":{"tf":1.7320508075688772},"8":{"tf":1.7320508075688772}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"24":{"tf":2.449489742783178},"8":{"tf":2.449489742783178}}}}}}}},"t":{"a":{"b":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":1,"docs":{"20":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"(":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"b":{"a":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"t":{"a":{"b":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"12":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":3.872983346207417}}}}}}}}},"df":2,"docs":{"1":{"tf":1.0},"12":{"tf":2.0}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":4.69041575982343},"14":{"tf":3.0},"18":{"tf":1.0},"20":{"tf":2.0},"22":{"tf":2.449489742783178},"23":{"tf":2.449489742783178},"6":{"tf":4.69041575982343},"7":{"tf":3.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":3.872983346207417}}}}}},"s":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"13":{"tf":2.23606797749979},"6":{"tf":2.23606797749979}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"_":{"a":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"(":{"_":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":3,"docs":{"19":{"tf":1.4142135623730951},"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"\\"":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"_":{"b":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"11":{"tf":1.0}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"11":{"tf":2.23606797749979},"26":{"tf":2.0}},"r":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"0":{"tf":1.0}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"t":{"df":0,"docs":{},"l":{"df":9,"docs":{"13":{"tf":2.449489742783178},"14":{"tf":1.7320508075688772},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"6":{"tf":2.449489742783178},"7":{"tf":1.7320508075688772}},"e":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"21":{"tf":1.0}}}}},"t":{"a":{"b":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"4":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}},"e":{"_":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}},"p":{"_":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{".":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"(":{"[":{"\\"":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"z":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"14":{"tf":3.7416573867739413},"7":{"tf":3.7416573867739413}}}}},"df":5,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":3.4641016151377544},"14":{"tf":4.47213595499958},"6":{"tf":3.4641016151377544},"7":{"tf":4.47213595499958}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":4,"docs":{"13":{"tf":2.8284271247461903},"14":{"tf":3.7416573867739413},"6":{"tf":2.8284271247461903},"7":{"tf":3.7416573867739413}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}},"y":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"i":{".":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}}}},"df":3,"docs":{"1":{"tf":1.4142135623730951},"25":{"tf":2.23606797749979},"9":{"tf":2.23606797749979}}},"n":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"k":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}}},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"p":{"df":3,"docs":{"13":{"tf":1.0},"19":{"tf":1.0},"6":{"tf":1.0}},"w":{"a":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"s":{"df":6,"docs":{"0":{"tf":1.0},"12":{"tf":1.0},"22":{"tf":1.0},"25":{"tf":1.0},"5":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":5,"docs":{"10":{"tf":2.0},"13":{"tf":1.4142135623730951},"25":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":4,"docs":{"13":{"tf":1.0},"14":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"13":{"tf":2.8284271247461903},"6":{"tf":2.8284271247461903}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"(":{"b":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"l":{"df":5,"docs":{"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}},"e":{"_":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":2,"docs":{"15":{"tf":1.0},"16":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"(":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":7,"docs":{"13":{"tf":1.4142135623730951},"19":{"tf":2.0},"20":{"tf":2.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"tf":1.7320508075688772},"6":{"tf":1.4142135623730951}}}}}}},"i":{"c":{"df":0,"docs":{},"h":{"(":{"_":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"22":{"tf":1.0},"6":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":6,"docs":{"13":{"tf":3.0},"15":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"18":{"tf":1.0},"20":{"tf":1.0},"6":{"tf":3.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"19":{"tf":1.0}},"s":{"df":0,"docs":{},"p":{"a":{"c":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"x":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"y":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"z":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"_":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"d":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}},"e":{"(":{"_":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":2,"docs":{"13":{"tf":1.4142135623730951},"6":{"tf":1.4142135623730951}}}}}}}},"title":{"root":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"13":{"tf":1.0},"6":{"tf":1.0}}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}}},"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"19":{"tf":1.0}}}}}}}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":1,"docs":{"0":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"2":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"17":{"tf":1.0}}}}}}}}}},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{}}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"21":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"b":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"16":{"tf":1.0}}}}},"n":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":5,"docs":{"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}}}}}},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"26":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}}}}},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":2,"docs":{"24":{"tf":1.0},"8":{"tf":1.0}}}}}}}},"t":{"a":{"b":{"b":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}}},"df":1,"docs":{"12":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":2,"docs":{"11":{"tf":1.0},"26":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":2,"docs":{"14":{"tf":1.0},"7":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"i":{"df":2,"docs":{"25":{"tf":1.0},"9":{"tf":1.0}}}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}}')); \ No newline at end of file diff --git a/docs/config-api-book/session-ref.html b/docs/config-api-book/session-ref.html index ff161b14..f52ff0b0 100644 --- a/docs/config-api-book/session-ref.html +++ b/docs/config-api-book/session-ref.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/system-runtime.html b/docs/config-api-book/system-runtime.html index 767e640e..841a440a 100644 --- a/docs/config-api-book/system-runtime.html +++ b/docs/config-api-book/system-runtime.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/tab-bar-context.html b/docs/config-api-book/tab-bar-context.html index 605c2a96..e0dd9fa0 100644 --- a/docs/config-api-book/tab-bar-context.html +++ b/docs/config-api-book/tab-bar-context.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/tab-info.html b/docs/config-api-book/tab-info.html index 30180ebb..675a24b1 100644 --- a/docs/config-api-book/tab-info.html +++ b/docs/config-api-book/tab-info.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/tabbar.html b/docs/config-api-book/tabbar.html index ae33ba3e..527da8a9 100644 --- a/docs/config-api-book/tabbar.html +++ b/docs/config-api-book/tabbar.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/theme.html b/docs/config-api-book/theme.html index a7a2fc0a..2edec8e7 100644 --- a/docs/config-api-book/theme.html +++ b/docs/config-api-book/theme.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/tree.html b/docs/config-api-book/tree.html index b358b529..3590520d 100644 --- a/docs/config-api-book/tree.html +++ b/docs/config-api-book/tree.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api-book/ui.html b/docs/config-api-book/ui.html index d100f0da..b7f12e76 100644 --- a/docs/config-api-book/ui.html +++ b/docs/config-api-book/ui.html @@ -35,7 +35,7 @@ const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; - window.path_to_searchindex_js = "searchindex-256e957a.js"; + window.path_to_searchindex_js = "searchindex-6f9ff0e9.js"; diff --git a/docs/config-api/action.md b/docs/config-api/action.md index 9dc1ed9a..d420f20a 100644 --- a/docs/config-api/action.md +++ b/docs/config-api/action.md @@ -2,6 +2,28 @@ ```Namespace: global``` +
+

fn break_current_node

+ +```rust,ignore +fn break_current_node(_: ActionApi, destination: String) -> Action +``` + +
+
+ +
+ +
+Break the current node into a new tab or floating window. +
+ +
+
+

fn cancel_search

@@ -581,6 +603,28 @@ Description Insert a tab before the current tab.
+ + +
+
+

fn join_buffer_here

+ +```rust,ignore +fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action +``` + +
+
+ +
+ +
+Join a buffer at the current node. +
+

@@ -706,6 +750,50 @@ Description Move a buffer into a specific node. + + +
+
+

fn move_current_node_before

+ +```rust,ignore +fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action +``` + +
+
+ +
+ +
+Move the current node before a sibling. +
+ +
+
+
+
+

fn move_node_after

+ +```rust,ignore +fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action +``` + +
+
+ +
+ +
+Move a node after a sibling. +
+

@@ -794,6 +882,28 @@ Description Emit a client notification. + + +
+
+

fn open_buffer_history

+ +```rust,ignore +fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action +``` + +
+
+ +
+ +
+Open the history of a buffer in a new view. +
+

@@ -1368,6 +1478,28 @@ Description Split the current node and attach the provided tree as the new sibling. + + +
+
+

fn swap_current_node

+ +```rust,ignore +fn swap_current_node(_: ActionApi, second_node_id: int) -> Action +``` + +
+
+ +
+ +
+Swap the current node with a sibling. +
+

@@ -1390,6 +1522,50 @@ Description Toggle a named input mode. + + +
+
+

fn toggle_zoom_node

+ +```rust,ignore +fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action +``` + +
+
+ +
+ +
+Toggle zoom on a node. +
+ +
+
+
+
+

fn unzoom_current_session

+ +```rust,ignore +fn unzoom_current_session(_: ActionApi) -> Action +``` + +
+
+ +
+ +
+Unzoom the current session. +
+

@@ -1415,3 +1591,25 @@ Copy the current selection into the clipboard.
+
+

fn zoom_current_node

+ +```rust,ignore +fn zoom_current_node(_: ActionApi) -> Action +``` + +
+
+ +
+ +
+Zoom the current node. +
+ +
+
+
diff --git a/docs/config-api/defs/registration.rhai b/docs/config-api/defs/registration.rhai index 752c140c..2e3faf94 100644 --- a/docs/config-api/defs/registration.rhai +++ b/docs/config-api/defs/registration.rhai @@ -82,6 +82,9 @@ fn tabs(_: TreeApi, tabs: array) -> TreeSpec; /// Build a tabs container with an explicit active tab. fn tabs_with_active(_: TreeApi, tabs: array, active: int) -> TreeSpec; +/// Break the current node into a new tab or floating window. +fn break_current_node(_: ActionApi, destination: string) -> Action; + /// Cancel the active search. fn cancel_search(_: ActionApi) -> Action; @@ -166,6 +169,9 @@ fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: string, tree: TreeS /// Insert a tab before the current tab. fn insert_tab_before_current(_: ActionApi, title: string, tree: TreeSpec) -> Action; +/// Join a buffer at the current node. +fn join_buffer_here(_: ActionApi, buffer_id: int, placement: string) -> Action; + /// Kill the currently focused buffer. fn kill_buffer(_: ActionApi) -> Action; @@ -192,6 +198,12 @@ fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: map) -> Action /// Move a buffer into a specific node. fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action; +/// Move the current node before a sibling. +fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action; + +/// Move a node after a sibling. +fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action; + /// Select the next tab in the currently focused tabs node. fn next_current_tabs(_: ActionApi) -> Action; @@ -204,6 +216,9 @@ fn noop(_: ActionApi) -> Action; /// Emit a client notification. fn notify(_: ActionApi, level: string, message: string) -> Action; +/// Open the history of a buffer in a new view. +fn open_buffer_history(_: ActionApi, buffer_id: int, scope: string, placement: string) -> Action; + /// Open a floating view around the provided tree. fn open_floating(_: ActionApi, tree: TreeSpec, options: map) -> Action; @@ -297,12 +312,24 @@ fn send_keys_current(_: ActionApi, notation: string) -> Action; /// Split the current node and attach the provided tree as the new sibling. fn split_with(_: ActionApi, direction: string, tree: TreeSpec) -> Action; +/// Swap the current node with a sibling. +fn swap_current_node(_: ActionApi, second_node_id: int) -> Action; + /// Toggle a named input mode. fn toggle_mode(_: ActionApi, mode: string) -> Action; +/// Toggle zoom on a node. +fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action; + +/// Unzoom the current session. +fn unzoom_current_session(_: ActionApi) -> Action; + /// Copy the current selection into the clipboard. fn yank_selection(_: ActionApi) -> Action; +/// Zoom the current node. +fn zoom_current_node(_: ActionApi) -> Action; + /// Toggle focus-on-click behavior. /// /// # rhai-autodocs:index:22 diff --git a/docs/config-api/defs/runtime.rhai b/docs/config-api/defs/runtime.rhai index ca8da201..65a0985a 100644 --- a/docs/config-api/defs/runtime.rhai +++ b/docs/config-api/defs/runtime.rhai @@ -131,6 +131,9 @@ fn tabs(_: TreeApi, tabs: array) -> TreeSpec; /// Build a tabs container with an explicit active tab. fn tabs_with_active(_: TreeApi, tabs: array, active: int) -> TreeSpec; +/// Break the current node into a new tab or floating window. +fn break_current_node(_: ActionApi, destination: string) -> Action; + /// Cancel the active search. fn cancel_search(_: ActionApi) -> Action; @@ -215,6 +218,9 @@ fn insert_tab_before(_: ActionApi, tabs_node_id: int, title: string, tree: TreeS /// Insert a tab before the current tab. fn insert_tab_before_current(_: ActionApi, title: string, tree: TreeSpec) -> Action; +/// Join a buffer at the current node. +fn join_buffer_here(_: ActionApi, buffer_id: int, placement: string) -> Action; + /// Kill the currently focused buffer. fn kill_buffer(_: ActionApi) -> Action; @@ -241,6 +247,12 @@ fn move_buffer_to_floating(_: ActionApi, buffer_id: int, options: map) -> Action /// Move a buffer into a specific node. fn move_buffer_to_node(_: ActionApi, buffer_id: int, node_id: int) -> Action; +/// Move the current node before a sibling. +fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action; + +/// Move a node after a sibling. +fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action; + /// Select the next tab in the currently focused tabs node. fn next_current_tabs(_: ActionApi) -> Action; @@ -253,6 +265,9 @@ fn noop(_: ActionApi) -> Action; /// Emit a client notification. fn notify(_: ActionApi, level: string, message: string) -> Action; +/// Open the history of a buffer in a new view. +fn open_buffer_history(_: ActionApi, buffer_id: int, scope: string, placement: string) -> Action; + /// Open a floating view around the provided tree. fn open_floating(_: ActionApi, tree: TreeSpec, options: map) -> Action; @@ -346,12 +361,24 @@ fn send_keys_current(_: ActionApi, notation: string) -> Action; /// Split the current node and attach the provided tree as the new sibling. fn split_with(_: ActionApi, direction: string, tree: TreeSpec) -> Action; +/// Swap the current node with a sibling. +fn swap_current_node(_: ActionApi, second_node_id: int) -> Action; + /// Toggle a named input mode. fn toggle_mode(_: ActionApi, mode: string) -> Action; +/// Toggle zoom on a node. +fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action; + +/// Unzoom the current session. +fn unzoom_current_session(_: ActionApi) -> Action; + /// Copy the current selection into the clipboard. fn yank_selection(_: ActionApi) -> Action; +/// Zoom the current node. +fn zoom_current_node(_: ActionApi) -> Action; + /// Return the active tab index. fn active_index(bar: TabBarContext) -> int; diff --git a/docs/config-api/registration-action.md b/docs/config-api/registration-action.md index 489a075e..736a42e2 100644 --- a/docs/config-api/registration-action.md +++ b/docs/config-api/registration-action.md @@ -2,6 +2,28 @@ ```Namespace: global``` +
+

fn break_current_node

+ +```rust,ignore +fn break_current_node(_: ActionApi, destination: String) -> Action +``` + +
+
+ +
+ +
+Break the current node into a new tab or floating window. +
+ +
+
+

fn cancel_search

@@ -581,6 +603,28 @@ Description Insert a tab before the current tab.
+ + +
+
+

fn join_buffer_here

+ +```rust,ignore +fn join_buffer_here(_: ActionApi, buffer_id: int, placement: String) -> Action +``` + +
+
+ +
+ +
+Join a buffer at the current node. +
+

@@ -706,6 +750,50 @@ Description Move a buffer into a specific node. + + +
+
+

fn move_current_node_before

+ +```rust,ignore +fn move_current_node_before(_: ActionApi, sibling_node_id: int) -> Action +``` + +
+
+ +
+ +
+Move the current node before a sibling. +
+ +
+
+
+
+

fn move_node_after

+ +```rust,ignore +fn move_node_after(_: ActionApi, node_id: int, sibling_node_id: int) -> Action +``` + +
+
+ +
+ +
+Move a node after a sibling. +
+

@@ -794,6 +882,28 @@ Description Emit a client notification. + + +
+
+

fn open_buffer_history

+ +```rust,ignore +fn open_buffer_history(_: ActionApi, buffer_id: int, scope: String, placement: String) -> Action +``` + +
+
+ +
+ +
+Open the history of a buffer in a new view. +
+

@@ -1368,6 +1478,28 @@ Description Split the current node and attach the provided tree as the new sibling. + + +
+
+

fn swap_current_node

+ +```rust,ignore +fn swap_current_node(_: ActionApi, second_node_id: int) -> Action +``` + +
+
+ +
+ +
+Swap the current node with a sibling. +
+

@@ -1390,6 +1522,50 @@ Description Toggle a named input mode. + + +
+
+

fn toggle_zoom_node

+ +```rust,ignore +fn toggle_zoom_node(_: ActionApi, node_id: int) -> Action +``` + +
+
+ +
+ +
+Toggle zoom on a node. +
+ +
+
+
+
+

fn unzoom_current_session

+ +```rust,ignore +fn unzoom_current_session(_: ActionApi) -> Action +``` + +
+
+ +
+ +
+Unzoom the current session. +
+

@@ -1415,3 +1591,25 @@ Copy the current selection into the clipboard.
+
+

fn zoom_current_node

+ +```rust,ignore +fn zoom_current_node(_: ActionApi) -> Action +``` + +
+
+ +
+ +
+Zoom the current node. +
+ +
+
+
From 2cfbb8d234bf7019d588c9c6a963894bce49b3a3 Mon Sep 17 00:00:00 2001 From: Emma <817422+Pajn@users.noreply.github.com> Date: Tue, 24 Mar 2026 00:49:54 +0100 Subject: [PATCH 4/5] Fix tests leaking processes --- Cargo.lock | 1 + crates/embers-cli/tests/interactive.rs | 128 ++++++++++++++--------- crates/embers-test-support/Cargo.toml | 1 + crates/embers-test-support/src/server.rs | 70 +++++++++++-- 4 files changed, 144 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a83c23ca..bebeb87a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,6 +638,7 @@ dependencies = [ "portable-pty", "tempfile", "tokio", + "tracing", ] [[package]] diff --git a/crates/embers-cli/tests/interactive.rs b/crates/embers-cli/tests/interactive.rs index 190873dc..59450051 100644 --- a/crates/embers-cli/tests/interactive.rs +++ b/crates/embers-cli/tests/interactive.rs @@ -1,5 +1,5 @@ use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::time::Duration; use embers_core::PtySize; @@ -18,7 +18,60 @@ const SCROLLBACK_SETTLE_DELAY: Duration = Duration::from_millis(750); const QUIET_TIMEOUT: Duration = Duration::from_millis(500); const PAGE_UP_ATTEMPTS: usize = 4; -fn spawn_embers(args: &[&str]) -> PtyHarness { +/// A guard that owns the spawned embers process and ensures cleanup +/// of orphaned __serve processes when dropped. +struct SpawnedEmbers { + socket_path: PathBuf, +} + +impl SpawnedEmbers { + fn new(socket_path: PathBuf) -> Self { + Self { socket_path } + } +} + +impl Drop for SpawnedEmbers { + fn drop(&mut self) { + // Kill any orphaned __serve process for our socket + kill_orphaned_server(&self.socket_path); + } +} + +/// Kill any orphaned embers __serve process for the given socket. +/// This is safe to call from Drop or any synchronous context. +fn kill_orphaned_server(socket_path: &Path) { + let pid_path = socket_path.with_extension("pid"); + + // Try to read and kill the PID from the pid file + if let Ok(pid_str) = fs::read_to_string(&pid_path) + && let Ok(pid) = pid_str.trim().parse::() + && pid > 0 + { + // SAFETY: pid comes from our own pid file + unsafe { libc::kill(pid, libc::SIGTERM) }; + } + + // Wait briefly for graceful shutdown + std::thread::sleep(Duration::from_millis(50)); + + // Force kill if still alive + if let Ok(pid_str) = fs::read_to_string(&pid_path) + && let Ok(pid) = pid_str.trim().parse::() + && pid > 0 + { + // SAFETY: pid comes from our own pid file + unsafe { libc::kill(pid, libc::SIGKILL) }; + } + + // Clean up pid file + let _ = fs::remove_file(&pid_path); +} + +/// Spawn an embers client process with the given arguments and return a guard +/// that ensures cleanup of any orphaned __serve process when dropped. +/// The socket_path should be the path to the socket - if a server needs to be +/// spawned for it, the guard will clean it up. +fn spawn_embers(args: &[&str], socket_path: PathBuf) -> (SpawnedEmbers, PtyHarness) { let binary = cargo_bin_path("embers"); let binary_dir = binary.parent().expect("binary dir"); let path = format!( @@ -33,34 +86,9 @@ fn spawn_embers(args: &[&str]) -> PtyHarness { ]; env_and_args.extend(args.iter().map(|arg| (*arg).to_owned())); let argv = env_and_args.iter().map(String::as_str).collect::>(); - PtyHarness::spawn("/usr/bin/env", &argv, PtySize::new(80, 24)).expect("spawn embers in pty") -} - -async fn shutdown_spawned_server(socket_path: &Path) { - let pid_path = socket_path.with_extension("pid"); - let pid = wait_for_pid(&pid_path) - .await - .trim() - .parse::() - .expect("pid parses"); - assert!(pid > 0, "invalid pid: {pid}"); - - // SAFETY: pid comes from our own pid file and SIGTERM targets that specific process. - let result = unsafe { libc::kill(pid, libc::SIGTERM) }; - assert_eq!(result, 0, "failed to signal spawned server"); - - for _ in 0..FILE_WAIT_ATTEMPTS { - if !socket_path.exists() && !pid_path.exists() { - return; - } - tokio::time::sleep(FILE_WAIT_POLL).await; - } - - panic!( - "timed out waiting for spawned server shutdown (socket: {}, pid file: {})", - socket_path.display(), - pid_path.display() - ); + let harness = PtyHarness::spawn("/usr/bin/env", &argv, PtySize::new(80, 24)) + .expect("spawn embers in pty"); + (SpawnedEmbers::new(socket_path), harness) } async fn wait_for_socket(socket_path: &Path) { @@ -74,17 +102,6 @@ async fn wait_for_socket(socket_path: &Path) { panic!("timed out waiting for socket {}", socket_path.display()); } -async fn wait_for_pid(pid_path: &Path) -> String { - for _ in 0..FILE_WAIT_ATTEMPTS { - if let Ok(pid) = fs::read_to_string(pid_path) { - return pid; - } - tokio::time::sleep(FILE_WAIT_POLL).await; - } - - panic!("timed out waiting for pid file {}", pid_path.display()); -} - async fn populate_scrollback_or_wait(harness: &mut PtyHarness, lines: usize) { harness .write_all("echo READY\r") @@ -171,7 +188,7 @@ async fn embers_without_subcommand_starts_server_and_client() { let tempdir = tempdir().expect("tempdir"); let socket_path = tempdir.path().join("embers.sock"); let socket_arg = socket_path.to_string_lossy().into_owned(); - let mut harness = spawn_embers(&["--socket", &socket_arg]); + let (_spawned, mut harness) = spawn_embers(&["--socket", &socket_arg], socket_path.clone()); harness .read_until_contains("[main]", STARTUP_TIMEOUT) @@ -202,7 +219,7 @@ async fn embers_without_subcommand_starts_server_and_client() { harness.write_all("\x11").expect("quit client"); harness.wait().expect("client exits"); - shutdown_spawned_server(&socket_path).await; + // spawned.drop() will clean up the orphaned __serve process } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -234,7 +251,8 @@ async fn attach_subcommand_connects_to_running_server() { ); let socket_arg = server.socket_path().to_string_lossy().into_owned(); - let mut harness = spawn_embers(&["attach", "--socket", &socket_arg]); + let socket_path = server.socket_path().to_path_buf(); + let (_spawned, mut harness) = spawn_embers(&["attach", "--socket", &socket_arg], socket_path); harness .read_until_contains("[main]", STARTUP_TIMEOUT) .expect("attach client renders"); @@ -283,7 +301,11 @@ async fn client_commands_can_switch_and_detach_a_live_attached_client() { ); let socket_arg = server.socket_path().to_string_lossy().into_owned(); - let mut harness = spawn_embers(&["attach", "--socket", &socket_arg, "-t", "main"]); + let socket_path = server.socket_path().to_path_buf(); + let (_spawned, mut harness) = spawn_embers( + &["attach", "--socket", &socket_arg, "-t", "main"], + socket_path, + ); harness .read_until_contains("[main]", STARTUP_TIMEOUT) .expect("attach client renders main"); @@ -355,7 +377,11 @@ async fn buffer_reveal_switches_the_attached_client_to_the_buffer_session() { .expect("ops focused buffer id exists"); let socket_arg = server.socket_path().to_string_lossy().into_owned(); - let mut harness = spawn_embers(&["attach", "--socket", &socket_arg, "-t", "main"]); + let socket_path = server.socket_path().to_path_buf(); + let (_spawned, mut harness) = spawn_embers( + &["attach", "--socket", &socket_arg, "-t", "main"], + socket_path, + ); harness .read_until_contains("[main]", STARTUP_TIMEOUT) .expect("attach client renders main"); @@ -376,7 +402,7 @@ async fn page_up_enters_local_scrollback_and_shows_indicator() { let tempdir = tempdir().expect("tempdir"); let socket_path = tempdir.path().join("embers.sock"); let socket_arg = socket_path.to_string_lossy().into_owned(); - let mut harness = spawn_embers(&["--socket", &socket_arg]); + let (_spawned, mut harness) = spawn_embers(&["--socket", &socket_arg], socket_path.clone()); harness .read_until_contains("[main]", STARTUP_TIMEOUT) @@ -387,7 +413,8 @@ async fn page_up_enters_local_scrollback_and_shows_indicator() { harness.write_all("\x11").expect("quit client"); harness.wait().expect("client exits"); - shutdown_spawned_server(&socket_path).await; + + // spawned.drop() will clean up the orphaned __serve process } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -396,7 +423,7 @@ async fn local_selection_yank_emits_osc52_clipboard_sequence() { let tempdir = tempdir().expect("tempdir"); let socket_path = tempdir.path().join("embers.sock"); let socket_arg = socket_path.to_string_lossy().into_owned(); - let mut harness = spawn_embers(&["--socket", &socket_arg]); + let (_spawned, mut harness) = spawn_embers(&["--socket", &socket_arg], socket_path.clone()); harness .read_until_contains("[main]", STARTUP_TIMEOUT) @@ -415,5 +442,6 @@ async fn local_selection_yank_emits_osc52_clipboard_sequence() { harness.write_all("\x11").expect("quit client"); harness.wait().expect("client exits"); - shutdown_spawned_server(&socket_path).await; + + // spawned.drop() will clean up the orphaned __serve process } diff --git a/crates/embers-test-support/Cargo.toml b/crates/embers-test-support/Cargo.toml index e2c11150..7ba745c5 100644 --- a/crates/embers-test-support/Cargo.toml +++ b/crates/embers-test-support/Cargo.toml @@ -18,6 +18,7 @@ libc.workspace = true portable-pty.workspace = true tempfile.workspace = true tokio.workspace = true +tracing.workspace = true [[test]] name = "integration" diff --git a/crates/embers-test-support/src/server.rs b/crates/embers-test-support/src/server.rs index 99355867..c9ae6fb5 100644 --- a/crates/embers-test-support/src/server.rs +++ b/crates/embers-test-support/src/server.rs @@ -1,13 +1,17 @@ use std::path::Path; +use std::process::Command; +use std::time::Duration; use embers_core::{Result, init_test_tracing}; use embers_server::{Server, ServerConfig, ServerHandle}; use tempfile::TempDir; +const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5); + #[derive(Debug)] pub struct TestServer { socket_path: std::path::PathBuf, - tempdir: TempDir, + _tempdir: TempDir, handle: Option, } @@ -23,7 +27,7 @@ impl TestServer { Ok(Self { socket_path, - tempdir, + _tempdir: tempdir, handle: Some(handle), }) } @@ -32,12 +36,66 @@ impl TestServer { &self.socket_path } + /// Shuts down the server and kills any orphaned __serve processes + /// that were spawned for this socket during the test. pub async fn shutdown(mut self) -> Result<()> { - let _ = self.tempdir.path(); + // First, kill any orphaned __serve processes for our socket + self.kill_orphaned_servers(); + + // Then shutdown our own server with a timeout if let Some(handle) = self.handle.take() { - handle.shutdown().await - } else { - Ok(()) + match tokio::time::timeout(SHUTDOWN_TIMEOUT, handle.shutdown()).await { + Ok(Ok(())) => {} + Ok(Err(e)) => { + tracing::warn!(error = %e, "TestServer shutdown returned error"); + } + Err(_) => { + tracing::warn!("TestServer shutdown timed out after {:?}", SHUTDOWN_TIMEOUT); + } + } + } + Ok(()) + } + + /// Kill any orphaned embers __serve processes that were spawned + /// for this server's socket but are no longer needed. + fn kill_orphaned_servers(&self) { + let socket_path_str = self.socket_path.to_string_lossy(); + let pid_path = self.socket_path.with_extension("pid"); + + // First try to kill via PID file (for __serve processes) + if let Ok(pid_str) = std::fs::read_to_string(&pid_path) + && let Ok(pid) = pid_str.trim().parse::() + { + let _ = Command::new("kill").arg(pid.to_string()).output(); } + + // Also try to find and kill any __serve processes referencing our socket + // This handles cases where the PID file wasn't cleaned up or we need + // to find the process by socket path + if let Ok(output) = Command::new("ps").args(["-eo", "pid,args"]).output() { + for line in String::from_utf8_lossy(&output.stdout).lines() { + let line = line.trim(); + // Look for __serve processes with our socket path + if line.contains("__serve") + && line.contains(&*socket_path_str) + && let Some(pid_str) = line.split_whitespace().next() + && let Ok(pid) = pid_str.parse::() + { + let _ = Command::new("kill").arg("-9").arg(pid.to_string()).output(); + tracing::debug!(pid, "killed orphaned __serve process"); + } + } + } + + // Clean up the pid file + let _ = std::fs::remove_file(&pid_path); + } +} + +impl Drop for TestServer { + fn drop(&mut self) { + // Ensure any spawned servers are killed even if shutdown wasn't called + self.kill_orphaned_servers(); } } From 36d6f03832adf13bdbf5cc67e5231bc81519c5c3 Mon Sep 17 00:00:00 2001 From: Emma <817422+Pajn@users.noreply.github.com> Date: Tue, 24 Mar 2026 17:50:15 +0100 Subject: [PATCH 5/5] Add blink styling, italic support and rebindable search keys --- crates/embers-client/src/config/loader.rs | 5 +++++ crates/embers-client/src/configured_client.rs | 12 ++++++++++-- crates/embers-client/src/grid.rs | 15 +++++++++++++++ crates/embers-client/src/renderer.rs | 2 ++ crates/embers-client/src/scripting/model.rs | 1 + crates/embers-client/src/scripting/runtime.rs | 7 +++++++ crates/embers-client/src/scripting/types.rs | 1 + 7 files changed, 41 insertions(+), 2 deletions(-) diff --git a/crates/embers-client/src/config/loader.rs b/crates/embers-client/src/config/loader.rs index 20f581fe..f6ec9adb 100644 --- a/crates/embers-client/src/config/loader.rs +++ b/crates/embers-client/src/config/loader.rs @@ -31,6 +31,11 @@ bind("select", "k", action.select_move_up()); bind("select", "l", action.select_move_right()); bind("select", "y", action.yank_selection()); bind("select", "", action.cancel_selection()); + +bind("search", "", action.commit_search()); +bind("search", "", action.cancel_search()); +bind("search", "n", action.search_next()); +bind("search", "N", action.search_prev()); "#; #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/crates/embers-client/src/configured_client.rs b/crates/embers-client/src/configured_client.rs index cdad9aa8..7e3e69a6 100644 --- a/crates/embers-client/src/configured_client.rs +++ b/crates/embers-client/src/configured_client.rs @@ -598,6 +598,7 @@ where } Action::SearchNext => self.navigate_search(presentation, true).await, Action::SearchPrev => self.navigate_search(presentation, false).await, + Action::CommitSearch => self.commit_search_prompt(session_id, viewport).await, Action::CancelSearch => self.cancel_search_prompt(session_id, viewport).await, Action::EnterSelect { kind } => { self.enter_select_mode(session_id, viewport, presentation, kind) @@ -1613,8 +1614,14 @@ where } Ok(()) } - KeyEvent::Enter => self.commit_search_prompt(session_id, viewport).await, - KeyEvent::Escape => self.cancel_search_prompt(session_id, viewport).await, + KeyEvent::Enter => { + self.execute_actions(Some(session_id), Some(viewport), vec![Action::CommitSearch]) + .await + } + KeyEvent::Escape => { + self.execute_actions(Some(session_id), Some(viewport), vec![Action::CancelSearch]) + .await + } KeyEvent::Bytes(bytes) => { if let Some(prompt) = &mut self.search_prompt { prompt.query.push_str(&String::from_utf8_lossy(&bytes)); @@ -2062,6 +2069,7 @@ fn action_is_local_terminal_action(action: &Action) -> bool { | Action::EnterSearchMode | Action::SearchNext | Action::SearchPrev + | Action::CommitSearch | Action::CancelSearch | Action::EnterSelect { .. } | Action::SelectMove { .. } diff --git a/crates/embers-client/src/grid.rs b/crates/embers-client/src/grid.rs index 312076e2..6b8f3526 100644 --- a/crates/embers-client/src/grid.rs +++ b/crates/embers-client/src/grid.rs @@ -30,6 +30,7 @@ pub struct CellStyle { pub underline: bool, pub dim: bool, pub reverse: bool, + pub blink: bool, } impl CellStyle { @@ -43,6 +44,16 @@ impl CellStyle { self } + pub const fn with_italic(mut self) -> Self { + self.italic = true; + self + } + + pub const fn with_blink(mut self) -> Self { + self.blink = true; + self + } + pub fn is_plain(self) -> bool { self == Self::default() } @@ -58,6 +69,7 @@ impl From<&crate::scripting::StyleSpec> for CellStyle { underline: value.underline, dim: value.dim, reverse: false, + blink: value.blink, } } } @@ -389,6 +401,9 @@ fn write_style_transition(output: &mut String, from: CellStyle, to: CellStyle) { if to.reverse { output.push_str("\x1b[7m"); } + if to.blink { + output.push_str("\x1b[5m"); + } if let Some(fg) = to.fg { let _ = write!(output, "\x1b[38;2;{};{};{}m", fg.red, fg.green, fg.blue); } diff --git a/crates/embers-client/src/renderer.rs b/crates/embers-client/src/renderer.rs index 42195776..d36e269e 100644 --- a/crates/embers-client/src/renderer.rs +++ b/crates/embers-client/src/renderer.rs @@ -664,6 +664,7 @@ fn scroll_indicator_style() -> CellStyle { fn search_style() -> CellStyle { CellStyle { underline: true, + italic: true, ..CellStyle::default() } } @@ -672,6 +673,7 @@ fn active_search_style() -> CellStyle { CellStyle { underline: true, reverse: true, + italic: true, ..CellStyle::default() } } diff --git a/crates/embers-client/src/scripting/model.rs b/crates/embers-client/src/scripting/model.rs index f00e4333..7ab5d201 100644 --- a/crates/embers-client/src/scripting/model.rs +++ b/crates/embers-client/src/scripting/model.rs @@ -137,6 +137,7 @@ pub enum Action { EnterSearchMode, SearchNext, SearchPrev, + CommitSearch, CancelSearch, EnterSelect { kind: SelectionKind, diff --git a/crates/embers-client/src/scripting/runtime.rs b/crates/embers-client/src/scripting/runtime.rs index 300ff96c..b4ebfc37 100644 --- a/crates/embers-client/src/scripting/runtime.rs +++ b/crates/embers-client/src/scripting/runtime.rs @@ -1653,6 +1653,12 @@ mod documented_action_api { Action::CancelSearch } + /// Commit the active search. + #[rhai_fn(name = "commit_search")] + pub fn commit_search(_: &mut ActionApi) -> Action { + Action::CommitSearch + } + /// Jump to the next search match. #[rhai_fn(name = "search_next")] pub fn search_next(_: &mut ActionApi) -> Action { @@ -2195,6 +2201,7 @@ fn parse_segment_options(mut options: Map) -> ScriptResult<(StyleSpec, Option