gnostr_asyncgit/gitui/
mod.rs

1mod bindings;
2/// pub mod cli;
3pub mod cli;
4/// mod cmd_log;
5mod cmd_log;
6/// pub mod config;
7pub mod config;
8/// mod file_watcher;
9mod file_watcher;
10/// mod git;
11mod git;
12/// mod git2_opts;
13mod git2_opts;
14/// pub mod gitu_diff;
15pub mod gitu_diff;
16/// pub mod gitui_error;
17pub mod gitui_error;
18/// mod highlight;
19mod highlight;
20/// mod items;
21mod items;
22/// mod key_parser;
23mod key_parser;
24/// mod menu;
25mod menu;
26/// mod ops;
27mod ops;
28/// mod prompt;
29mod prompt;
30/// mod screen;
31mod screen;
32/// pub mod state;
33pub mod state;
34/// mod syntax_parser;
35mod syntax_parser;
36/// pub mod term;
37pub mod term;
38#[cfg(test)]
39/// mod tests;
40mod tests;
41/// mod ui;
42mod ui;
43
44use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventState, KeyModifiers};
45use git2::Repository;
46use gitui_error::Error;
47use items::Item;
48//use ops::Action;
49use std::{
50    path::{Path, PathBuf},
51    process::Command,
52    rc::Rc,
53    time::Duration,
54};
55use term::Term;
56
57///
58pub const LOG_FILE_NAME: &str = "gnostr-asyncgit.log";
59
60//                                An overview of gnostr-asyncgit's ui and terminology:
61//
62//                Screen (src/screen/*)
63//                  │
64//                  ▼
65//                 ┌──────────────────────────────────────────────────────────────────┐
66//        Item───┬─► On branch master                                                 │
67//        Item   └─► Your branch is up to date with 'origin/master'.                  │
68//        ...      │                                                                  │
69//                 │ Untracked files                                                  │
70//                 │ src/tests/rebase.rs                                              │
71//                 │                                                                  │
72//                 │ Unstaged changes (4)                                             │
73//                 │▌modified   src/keybinds.rs…                                      │
74//                 │ modified   src/ops/mod.rs…                                       │
75//                 │ modified   src/ops/rebase.rs…                                    │
76//                 │ modified   src/tests/mod.rs…                                     │
77//                 │                                                                  │
78//                 │ Stashes                                                          │
79//                 │ stash@0 On master: scroll                                        │
80//                 │ stash@1 WIP on fix/run-cmd-error-on-bad-exit: 098d14a feat: prom…│
81//                 │                                                                  │
82//                 │ Recent commits                                                   │
83// Ops (src/ops/*) ├──────────────────────────────────────────────────────────────────┤
84//       │         │Help                        Submenu      modified   src/keybinds.r│
85//       └─────┬───►g Refresh                   h Help       ret Show                 │
86//             └───►tab Toggle section          b Branch     K Discard                │
87//                 │k p ↑ Move up               c Commit     s Stage                  │
88//                 │j n ↓ Move down             f Fetch      u Unstage                │
89// Submenu ───────►│C-k C-p C-↑ Move up line    l Log                                 │
90//                 │C-j C-n C-↓ Move down line  F Pull                                │
91//                 │C-u Half page up            P Push                                │
92//                 │C-d Half page down          r Rebase                              │
93//                 │y Show refs                 X Reset                               │
94//                 │                            z Stash                               │
95//                 └──────────────────────────────────────────────────────────────────┘
96
97///
98pub type Res<T> = Result<T, Error>;
99
100///
101pub fn run(args: &cli::Args, term: &mut Term) -> Res<()> {
102    let dir = find_git_dir()?;
103    let repo = open_repo(&dir)?;
104    let config = Rc::new(config::init_config()?);
105
106    let mut state = state::State::create(
107        Rc::new(repo),
108        term.size().map_err(Error::Term)?,
109        args,
110        config.clone(),
111        true,
112    )?;
113
114    if let Some(keys_string) = &args.keys {
115        let ("", keys) = key_parser::parse_keys(keys_string).expect("Couldn't parse keys") else {
116            panic!("Couldn't parse keys");
117        };
118
119        for event in keys_to_events(&keys) {
120            state.handle_event(term, event)?;
121        }
122    }
123
124    state.redraw_now(term)?;
125
126    if args.print {
127        return Ok(());
128    }
129
130    state.run(term, Duration::from_millis(100))?;
131
132    Ok(())
133}
134
135///
136fn open_repo(dir: &Path) -> Res<Repository> {
137    log::debug!("Opening repo");
138    let repo = open_repo_from_env()?;
139    repo.set_workdir(dir, false).map_err(Error::OpenRepo)?;
140    Ok(repo)
141}
142
143///
144fn find_git_dir() -> Res<PathBuf> {
145    log::debug!("Finding git dir");
146    let dir = PathBuf::from(
147        String::from_utf8(
148            Command::new("git")
149                .args(["rev-parse", "--show-toplevel"])
150                .output()
151                .map_err(Error::FindGitDir)?
152                .stdout,
153        )
154        .map_err(Error::GitDirUtf8)?
155        .trim_end(),
156    );
157    Ok(dir)
158}
159
160///
161fn open_repo_from_env() -> Res<Repository> {
162    match Repository::open_from_env() {
163        Ok(repo) => Ok(repo),
164        Err(err) => Err(Error::OpenRepo(err)),
165    }
166}
167
168///
169fn keys_to_events(keys: &[(KeyModifiers, KeyCode)]) -> Vec<Event> {
170    keys.iter()
171        .map(|(mods, key)| {
172            Event::Key(KeyEvent {
173                code: *key,
174                modifiers: *mods,
175                kind: event::KeyEventKind::Press,
176                state: KeyEventState::NONE,
177            })
178        })
179        .collect::<Vec<_>>()
180}