feat: implement state transitions

This commit is contained in:
xeruf 2024-07-18 20:48:51 +03:00
parent 491eb81cb2
commit 06d6595bd8
1 changed files with 53 additions and 24 deletions

View File

@ -92,8 +92,11 @@ async fn main() {
} }
} }
fn make_event(text: &str, tags: &[Tag]) -> Event { fn make_task(text: &str, tags: &[Tag]) -> Event {
EventBuilder::new(Kind::from(1621), text, tags.to_vec()) make_event(Kind::from(1621), text, tags)
}
fn make_event(kind: Kind, text: &str, tags: &[Tag]) -> Event {
EventBuilder::new(kind, text, tags.to_vec())
.to_event(&MY_KEYS) .to_event(&MY_KEYS)
.unwrap() .unwrap()
} }
@ -108,7 +111,7 @@ async fn repl() {
for argument in args().skip(1) { for argument in args().skip(1) {
add_task( add_task(
&mut tasks, &mut tasks,
make_event(&argument, &[Tag::Hashtag("arg".to_string())]), make_task(&argument, &[Tag::Hashtag("arg".to_string())]),
); );
} }
@ -139,7 +142,8 @@ async fn repl() {
match stdin().lines().next() { match stdin().lines().next() {
Some(Ok(input)) => { Some(Ok(input)) => {
let mut iter = input.chars(); let mut iter = input.chars();
match iter.next() { let op = iter.next();
match op {
None => {} None => {}
Some(':') => match input[1..2].parse::<usize>() { Some(':') => match input[1..2].parse::<usize>() {
@ -160,6 +164,16 @@ async fn repl() {
} }
}, },
Some('>') | Some('<') => {
position.inspect(|e| {
let pos = tasks.get(e)
.map(|t| t.state().state)
.and_then(|state| STATES.iter().position(|s| s == &state))
.unwrap_or(1);
tasks.get_mut(e).map(|t| t.props.push(make_event(STATES[if op.unwrap() == '<' { pos - 1 } else { pos + 1 }].kind(), &input[1..], &[Tag::event(e.clone())])));
});
}
Some('.') => { Some('.') => {
let mut dots = 1; let mut dots = 1;
for _ in iter.take_while(|c| c == &'.') { for _ in iter.take_while(|c| c == &'.') {
@ -175,13 +189,13 @@ async fn repl() {
let mut tags: Vec<Tag> = Vec::new(); let mut tags: Vec<Tag> = Vec::new();
position.inspect(|p| tags.push(Tag::event(*p))); position.inspect(|p| tags.push(Tag::event(*p)));
let event = match input.split_once(": ") { let event = match input.split_once(": ") {
None => make_event(&input, &tags), None => make_task(&input, &tags),
Some(s) => { Some(s) => {
tags.append( tags.append(
&mut s.1.split(" ") &mut s.1.split(" ")
.map(|t| Tag::Hashtag(t.to_string())) .map(|t| Tag::Hashtag(t.to_string()))
.collect()); .collect());
make_event(s.0, &tags) make_task(s.0, &tags)
} }
}; };
for tag in event.tags.iter() { for tag in event.tags.iter() {
@ -252,11 +266,10 @@ impl Task {
1632 => Some(Closed), 1632 => Some(Closed),
1633 => Some(Active), 1633 => Some(Active),
_ => None, _ => None,
} }.map(|s| TaskState {
.map(|s| TaskState { name: event.content.clone(),
name: self.event.content.clone(),
state: s, state: s,
time: self.event.created_at.clone(), time: event.created_at.clone(),
}) })
}) })
} }
@ -271,15 +284,19 @@ impl Task {
}) })
} }
fn state(&self) -> Option<TaskState> { fn state(&self) -> TaskState {
self.states().max_by_key(|t| t.time) self.states().max_by_key(|t| t.time).unwrap_or(TaskState {
name: String::new(),
state: Open,
time: self.event.created_at,
})
} }
fn get(&self, property: &str) -> Option<String> { fn get(&self, property: &str) -> Option<String> {
match property { match property {
"id" => Some(self.event.id.to_string()), "id" => Some(self.event.id.to_string()),
"parentid" => self.parent_id().map(|i| i.to_string()), "parentid" => self.parent_id().map(|i| i.to_string()),
"state" => self.state().map(|s| s.state.to_string()), "state" => Some(self.state().state.to_string()),
"name" => Some(self.event.content.clone()), "name" => Some(self.event.content.clone()),
"desc" | "description" => self.descriptions().fold(None, |total, s| { "desc" | "description" => self.descriptions().fold(None, |total, s| {
Some(match total { Some(match total {
@ -300,13 +317,25 @@ struct TaskState {
state: State, state: State,
time: Timestamp, time: Timestamp,
} }
#[derive(Debug)]
#[derive(Debug, Copy, Clone, PartialEq)]
enum State { enum State {
Closed,
Open, Open,
Active, Active,
Done, Done,
Closed,
} }
impl State {
fn kind(&self) -> Kind {
match self {
Closed => Kind::from(1632),
Open => Kind::from(1630),
Active => Kind::from(1633),
Done => Kind::from(1631),
}
}
}
static STATES: [State; 4] = [Closed, Open, Active, Done];
impl fmt::Display for State { impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f) fmt::Debug::fmt(self, f)