Skip to content

Commit

Permalink
Implement searching notes in TUI
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-lag committed Jan 26, 2022
1 parent a15d054 commit 7ff9dda
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/brn_tui/input_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub enum InputMode {
Normal,
Edit
}
31 changes: 31 additions & 0 deletions src/brn_tui/input_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
pub struct InputString {
text: String,
}

impl Default for InputString {
fn default() -> InputString {
InputString {
text: String::from("/"),
}
}
}

impl InputString {
pub fn push(&mut self, c: char) {
self.text.push(c);
}

pub fn pop(&mut self) {
if self.text.len() > 1 {
self.text.pop();
}
}

pub fn get_displayed_text(&self) -> String {
return self.text.clone();
}

pub fn get_content_text(&self) -> String {
return self.text.chars().into_iter().skip(1).collect();
}
}
72 changes: 58 additions & 14 deletions src/brn_tui/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::note_property::NoteProperty;
use crate::notes::Notes;
use crate::settings::Settings;
use crate::brn_tui::tui_data::TuiData;
use crate::brn_tui::input_mode::InputMode;

use crossterm::{
event::{ self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode },
Expand Down Expand Up @@ -54,15 +55,46 @@ impl BrnTui {

// Detect keydown events
if let Ok(Event::Key(key)) = event::read() {
match key.code {
KeyCode::Char('q') => return Ok(()),
KeyCode::Char('j') | KeyCode::Down
=> BrnTui::increment_selected_value(tui_data, settings),
KeyCode::Char('k') | KeyCode::Up
=> BrnTui::decrement_selected_value(tui_data, settings),
KeyCode::Char('l') | KeyCode::Enter
=> BrnTui::open_selected_note(terminal, tui_data, settings),
_ => (),
match tui_data.input_mode {
InputMode::Normal => match key.code {
KeyCode::Char('q') => return Ok(()),
KeyCode::Char('j') | KeyCode::Down
=> BrnTui::increment_selected_value(tui_data, settings),
KeyCode::Char('k') | KeyCode::Up
=> BrnTui::decrement_selected_value(tui_data, settings),
KeyCode::Char('l') | KeyCode::Enter
=> BrnTui::open_selected_note(terminal, tui_data, settings),
KeyCode::Char('a')
=> BrnTui::add_note(terminal, tui_data, settings),
KeyCode::Char('/')
=> tui_data.input_mode = InputMode::Edit,
_ => (),
},
InputMode::Edit => match key.code {
KeyCode::Esc => tui_data.input_mode = InputMode::Normal,
KeyCode::Enter => {
tui_data.input_mode = InputMode::Normal;
let search_results = Notes::search(&tui_data.search_text.get_content_text())
.iter()
.map(|m| {
match Database::get_note_where_id(&m.note_id) {
Some(note) => note.note_name,
None => String::new(),
}
})
.collect();
tui_data.note_list.replace_items_with(search_results);
tui_data.note_list.select(Some(0));
BrnTui::show_note_content_preview(tui_data, settings);
}
KeyCode::Char(c) => {
tui_data.search_text.push(c);
},
KeyCode::Backspace => {
tui_data.search_text.pop();
},
_ => (),
}
}
}
}
Expand Down Expand Up @@ -102,8 +134,7 @@ impl BrnTui {
// Get notes to show
let items: Vec<ListItem> = tui_data.note_list.get_items()
.iter()
.enumerate()
.map(|(_, m)| {
.map(|m| {
ListItem::new(m.to_string())
})
.collect();
Expand Down Expand Up @@ -134,9 +165,19 @@ impl BrnTui {
}

fn render_message_block<B: Backend>(f: &mut Frame<B>, area: Rect, tui_data: &mut TuiData) {
let message_paragraph = Paragraph::new(tui_data.message.as_str())
.alignment(Alignment::Left)
.style(Style::default().fg(Color::LightRed));
let message_paragraph;
match tui_data.input_mode {
InputMode::Normal => {
message_paragraph = Paragraph::new(tui_data.message.as_str())
.alignment(Alignment::Left)
.style(Style::default().fg(Color::LightRed));
},
InputMode::Edit => {
message_paragraph = Paragraph::new(tui_data.search_text.get_displayed_text())
.alignment(Alignment::Left)
.style(Style::default().fg(Color::White));
},
}
f.render_widget(message_paragraph, area);
}

Expand Down Expand Up @@ -191,4 +232,7 @@ impl BrnTui {
}
}
}

fn add_note<B: Backend + Write>(terminal: &mut Terminal<B>, tui_data: &mut TuiData, settings: &mut Settings) {
}
}
2 changes: 2 additions & 0 deletions src/brn_tui/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod input_mode;
pub mod input_string;
pub mod main;
pub mod stateful_list;
pub mod tui_data;
13 changes: 13 additions & 0 deletions src/brn_tui/stateful_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ impl<T> StatefulList<T> {
}
}

pub fn replace_items_with(&mut self, items: Vec<T>) {
self.items = items;
self.state = ListState::default();
}

pub fn select(&mut self, index: Option<usize>) {
self.state.select(index);
}
Expand All @@ -36,6 +41,10 @@ impl<T> StatefulList<T> {
}

pub fn next(&mut self) {
if self.items.len() == 0 {
return;
}

let next_index = match self.selected() {
Some(i) => {
if i >= self.items.len() - 1 {
Expand All @@ -50,6 +59,10 @@ impl<T> StatefulList<T> {
}

pub fn previous(&mut self) {
if self.items.len() == 0 {
return;
}

let prev_index = match self.selected() {
Some(i) => {
if i == 0 {
Expand Down
6 changes: 6 additions & 0 deletions src/brn_tui/tui_data.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::notes::Notes;
use crate::brn_tui::stateful_list::StatefulList;
use crate::brn_tui::input_mode::InputMode;
use crate::brn_tui::input_string::InputString;

pub struct TuiData {
pub note_list: StatefulList<String>,
pub note_content_preview: String,
pub message: String,
pub search_text: InputString,
pub input_mode: InputMode,
}

impl Default for TuiData {
Expand All @@ -13,6 +17,8 @@ impl Default for TuiData {
note_list: StatefulList::with_items(Notes::get(100)),
note_content_preview: String::default(),
message: String::default(),
search_text: InputString::default(),
input_mode: InputMode::Normal,
};
tui_data.note_list.select(Some(0));
return tui_data;
Expand Down
15 changes: 11 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,10 @@ fn exec_open_command(matches: &ArgMatches, settings: &mut Settings) {
}
};

if let Err(error) = result {
Message::error(&error);
match result {
Ok(None) => (),
Ok(Some(message)) => Message::warning(&message),
Err(error) => Message::error(&error),
}
}

Expand All @@ -234,7 +236,8 @@ fn exec_search_command(matches: &ArgMatches, settings: &mut Settings) {
}
let search_string = matches.value_of("search-string").unwrap_or_default();

Notes::search(search_string);
let search_results = Notes::search(search_string);
Notes::display_search_results_of(search_results)
}

fn exec_random_command(_matches: &ArgMatches, settings: &mut Settings) {
Expand Down Expand Up @@ -269,7 +272,11 @@ fn exec_add_command(matches: &ArgMatches, settings: &mut Settings) {
note_type = NoteType::Topic;
}

Notes::add(note_name, note_type, settings);
match Notes::add(note_name, note_type, settings) {
Ok(None) => (),
Ok(Some(message)) => Message::warning(&message),
Err(error) => Message::error(&error),
}
}

fn exec_rm_command(matches: &ArgMatches, settings: &mut Settings) {
Expand Down
2 changes: 2 additions & 0 deletions src/note_tagging.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;

#[derive(Clone)]
pub struct NoteTagging {
pub note_id: String,
pub tag_name: Option<String>
Expand Down
56 changes: 30 additions & 26 deletions src/notes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Notes {
return note_list;
}

pub fn search(complete_search_string: &str) {
pub fn search(complete_search_string: &str) -> Vec<NoteTagging> {
let split_search_strings = complete_search_string.split(" && ");
let mut search_results: HashSet<NoteTagging> = HashSet::new();
let mut negated_search_results: HashSet<NoteTagging> = HashSet::new();
Expand All @@ -115,15 +115,19 @@ impl Notes {
}

let search_results = search_results.difference(&negated_search_results);

display_search_results_of(search_results);
return search_results.cloned().collect();

fn search_notes_and_add_to(mut search_string: &str, search_results: &mut HashSet<NoteTagging>, negated_search_results: &mut HashSet<NoteTagging>) {
let mut individual_search_results = HashSet::new();
let mut is_search_string_for_tag = false;
let mut is_negated_search_string = false;

loop {
if search_string.is_empty() {
break;
}

if &search_string[0..1] == "!" {
is_negated_search_string = true;
search_string = &search_string[1..search_string.len()];
Expand Down Expand Up @@ -174,38 +178,35 @@ impl Notes {
}
}
}
}

fn display_search_results_of(search_results: Difference<NoteTagging, RandomState>) {
for search_result in search_results {
if let Some(note) = Database::get_note_where_id(&search_result.note_id) {
let tag_name = &search_result.tag_name.as_ref();
pub fn display_search_results_of(search_results: Vec<NoteTagging>) {
for search_result in search_results {
if let Some(note) = Database::get_note_where_id(&search_result.note_id) {
let tag_name = &search_result.tag_name.as_ref();

if tag_name.is_some() {
let tag_name = tag_name.unwrap();
println!("{} {}\t\t{}{}",
note.note_id.yellow(), note.note_name,
"#".bright_yellow(), tag_name.bright_yellow());
}
else {
println!("{} {}", note.note_id.yellow(), note.note_name);
}
if tag_name.is_some() {
let tag_name = tag_name.unwrap();
println!("{} {}\t\t{}{}",
note.note_id.yellow(), note.note_name,
"#".bright_yellow(), tag_name.bright_yellow());
}
else {
println!("{} {}", note.note_id.yellow(), note.note_name);
}

}
}
}

pub fn add(note_name: &str, note_type: NoteType, settings: &mut Settings) {
pub fn add(note_name: &str, note_type: NoteType, settings: &mut Settings) -> Result<Option<String>, String> {
let template_path = Path::new(&settings.zettelkasten_dir).join("note-template.md");
if !template_path.exists() {
Message::error(&format!("add_note: the note template couldn't be found at '{}'",
return Err(format!("the note template couldn't be found at '{}'",
template_path.to_string_lossy()));
return;
}

if !NOTE_NAME_VALIDATOR.is_match(note_name) {
Message::error(&format!("add_note: the note name contains illegal characters"));
return;
return Err(format!("add_note: the note name contains illegal characters"));
}

if let Some(note) = Notes::create_note_from_template(
Expand All @@ -214,13 +215,16 @@ impl Notes {
&settings.notes_dir,
template_path.as_os_str()
) {
Message::info(&format!("created note: {} {}", note.note_id.yellow(), note.note_name));
if settings.print_to_stdout {
Message::info(&format!("created note: {} {}", note.note_id.yellow(), note.note_name));
}

Database::insert_note(&note.note_id, &note.note_name, &note.file_name, note.creation_date_time);
if let Err(error) = Notes::open(&note.note_id, settings) {
Message::error(&error);
}
let result_message = Notes::open(&note.note_id, settings);
return result_message;
}

return Ok(None);
}

fn create_note_from_template(note_name: &str, note_type: NoteType, notes_dir: &OsStr, template_path: &OsStr) -> Option<Note> {
Expand Down

0 comments on commit 7ff9dda

Please sign in to comment.