├── .gitignore ├── Cargo.toml ├── README.md ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtab" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | crossterm = "0.26.1" 10 | tui = "0.19.0" 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rtab is a tool to quickly write tabs. 2 | 3 | ``` 4 | e|----------------------------------------| 5 | B|----------------------------------------| 6 | G|2------------2--------------------------| 7 | D|2------2-1---2------0-2----5-4---4-3-5-2| 8 | A|0----0-------0----0------0-----0--------| 9 | E|---0------------0-----------------------| 10 | ``` 11 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{io::Stdout, time::Duration}; 2 | 3 | use crossterm::{ 4 | cursor::{MoveDown, MoveLeft, MoveRight, MoveUp, RestorePosition, SavePosition}, 5 | event::{ 6 | self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyModifiers, 7 | }, 8 | execute, 9 | style::Print, 10 | terminal::{ 11 | disable_raw_mode, enable_raw_mode, Clear, ClearType, EnterAlternateScreen, 12 | LeaveAlternateScreen, 13 | }, 14 | }; 15 | 16 | struct App { 17 | pub stdout: Stdout, 18 | old_y: u16, 19 | pos_y: u16, 20 | pos_x: u16, 21 | tabs: [String; 6], 22 | } 23 | 24 | impl App { 25 | pub fn new() -> Self { 26 | Self { 27 | stdout: std::io::stdout(), 28 | old_y: 0, 29 | pos_y: 0, 30 | pos_x: 0, 31 | tabs: [ 32 | "e|".to_owned(), 33 | "B|".to_owned(), 34 | "G|".to_owned(), 35 | "D|".to_owned(), 36 | "A|".to_owned(), 37 | "E|".to_owned(), 38 | ], 39 | } 40 | } 41 | 42 | fn redraw(&mut self) { 43 | execute!(self.stdout, MoveUp(self.old_y + 1),).unwrap(); 44 | 45 | for line in &self.tabs { 46 | execute!( 47 | self.stdout, 48 | //EnableMouseCapture, 49 | Print("\r\n"), 50 | Print(line), 51 | Clear(ClearType::UntilNewLine), 52 | Print("\r"), 53 | ) 54 | .unwrap(); 55 | } 56 | 57 | if self.pos_y == 5 { 58 | execute!(self.stdout, MoveRight(2 + self.pos_x)).unwrap(); 59 | } else { 60 | execute!( 61 | self.stdout, 62 | MoveUp(5 - self.pos_y), 63 | MoveRight(2 + self.pos_x) 64 | ) 65 | .unwrap(); 66 | } 67 | 68 | self.old_y = self.pos_y; 69 | } 70 | } 71 | 72 | fn main() { 73 | let mut app = App::new(); 74 | enable_raw_mode().unwrap(); 75 | 76 | app.redraw(); 77 | 78 | loop { 79 | match crossterm::event::read().unwrap() { 80 | Event::Key(KeyEvent { 81 | code: KeyCode::Esc, .. 82 | }) => break, 83 | Event::Key(KeyEvent { 84 | code: KeyCode::Up, .. 85 | }) => { 86 | app.pos_y = app.pos_y.saturating_sub(1); 87 | app.redraw(); 88 | } 89 | Event::Key(KeyEvent { 90 | code: KeyCode::Down, 91 | .. 92 | }) => { 93 | if app.pos_y >= 5 { 94 | continue; 95 | } 96 | app.pos_y += 1; 97 | app.redraw(); 98 | } 99 | Event::Key(KeyEvent { 100 | code: KeyCode::Left, 101 | modifiers: KeyModifiers::SHIFT, 102 | .. 103 | }) => { 104 | for line in 0..6 { 105 | app.tabs[line].insert(app.pos_x as usize + 2, '-'); 106 | } 107 | app.redraw(); 108 | } 109 | Event::Key(KeyEvent { 110 | code: KeyCode::Right, 111 | modifiers: KeyModifiers::SHIFT, 112 | .. 113 | }) => { 114 | if app.pos_x as usize >= app.tabs[0].len() - 2 { 115 | continue; 116 | } 117 | app.pos_x += 1; 118 | for line in 0..6 { 119 | app.tabs[line].insert(app.pos_x as usize + 2, '-'); 120 | } 121 | app.redraw(); 122 | } 123 | Event::Key(KeyEvent { 124 | code: KeyCode::Left, 125 | .. 126 | }) => { 127 | app.pos_x = app.pos_x.saturating_sub(1); 128 | app.redraw(); 129 | } 130 | Event::Key(KeyEvent { 131 | code: KeyCode::Right, 132 | .. 133 | }) => { 134 | if app.pos_x as usize >= app.tabs[0].len() - 2 { 135 | continue; 136 | } 137 | app.pos_x += 1; 138 | app.redraw(); 139 | } 140 | Event::Key(KeyEvent { 141 | code: KeyCode::Backspace, 142 | .. 143 | }) => { 144 | if app.tabs[0].len() == 2 { 145 | continue; 146 | } 147 | let mut x = app.pos_x; 148 | if app.pos_x as usize >= app.tabs[0].len() - 2 { 149 | x -= 1; 150 | } 151 | for line in 0..6 { 152 | app.tabs[line].remove(x as usize + 2); 153 | } 154 | app.pos_x = x; 155 | app.redraw(); 156 | } 157 | Event::Key(KeyEvent { 158 | code: KeyCode::Char(mut c), 159 | .. 160 | }) => { 161 | if c == ' ' { 162 | c = '-'; 163 | } 164 | 165 | if app.pos_x as usize >= app.tabs[0].len() - 2 { 166 | for line in 0..6 { 167 | if line == app.pos_y as usize { 168 | app.tabs[line].insert(app.pos_x as usize + 2, c); 169 | } else { 170 | if app.pos_x as usize >= app.tabs[line].len() - 2 { 171 | app.tabs[line] 172 | .insert(app.pos_x as usize + 2, if c == '|' { c } else { '-' }); 173 | } 174 | } 175 | } 176 | } else { 177 | app.tabs[app.pos_y as usize].replace_range( 178 | app.pos_x as usize + 2..app.pos_x as usize + 3, 179 | &format!("{c}"), 180 | ); 181 | } 182 | app.pos_x += 1; 183 | app.redraw(); 184 | } 185 | //Event::Mouse(event) => println!("{:?}", event), 186 | //Event::Resize(width, height) => println!("New size {}x{}", width, height), 187 | _ => {} 188 | } 189 | } 190 | 191 | // Restore terminal 192 | disable_raw_mode().unwrap(); 193 | execute!( 194 | app.stdout, 195 | MoveDown(5 - app.pos_y), 196 | Print("\r\n"), 197 | //DisableMouseCapture 198 | ) 199 | .unwrap(); 200 | } 201 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cassowary" 19 | version = "0.3.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "crossterm" 31 | version = "0.25.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 34 | dependencies = [ 35 | "bitflags", 36 | "crossterm_winapi", 37 | "libc", 38 | "mio", 39 | "parking_lot", 40 | "signal-hook", 41 | "signal-hook-mio", 42 | "winapi", 43 | ] 44 | 45 | [[package]] 46 | name = "crossterm" 47 | version = "0.26.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 50 | dependencies = [ 51 | "bitflags", 52 | "crossterm_winapi", 53 | "libc", 54 | "mio", 55 | "parking_lot", 56 | "signal-hook", 57 | "signal-hook-mio", 58 | "winapi", 59 | ] 60 | 61 | [[package]] 62 | name = "crossterm_winapi" 63 | version = "0.9.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 66 | dependencies = [ 67 | "winapi", 68 | ] 69 | 70 | [[package]] 71 | name = "libc" 72 | version = "0.2.141" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" 75 | 76 | [[package]] 77 | name = "lock_api" 78 | version = "0.4.9" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 81 | dependencies = [ 82 | "autocfg", 83 | "scopeguard", 84 | ] 85 | 86 | [[package]] 87 | name = "log" 88 | version = "0.4.17" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 91 | dependencies = [ 92 | "cfg-if", 93 | ] 94 | 95 | [[package]] 96 | name = "mio" 97 | version = "0.8.6" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 100 | dependencies = [ 101 | "libc", 102 | "log", 103 | "wasi", 104 | "windows-sys", 105 | ] 106 | 107 | [[package]] 108 | name = "parking_lot" 109 | version = "0.12.1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 112 | dependencies = [ 113 | "lock_api", 114 | "parking_lot_core", 115 | ] 116 | 117 | [[package]] 118 | name = "parking_lot_core" 119 | version = "0.9.7" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 122 | dependencies = [ 123 | "cfg-if", 124 | "libc", 125 | "redox_syscall", 126 | "smallvec", 127 | "windows-sys", 128 | ] 129 | 130 | [[package]] 131 | name = "redox_syscall" 132 | version = "0.2.16" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 135 | dependencies = [ 136 | "bitflags", 137 | ] 138 | 139 | [[package]] 140 | name = "rtab" 141 | version = "0.1.0" 142 | dependencies = [ 143 | "crossterm 0.26.1", 144 | "tui", 145 | ] 146 | 147 | [[package]] 148 | name = "scopeguard" 149 | version = "1.1.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 152 | 153 | [[package]] 154 | name = "signal-hook" 155 | version = "0.3.15" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 158 | dependencies = [ 159 | "libc", 160 | "signal-hook-registry", 161 | ] 162 | 163 | [[package]] 164 | name = "signal-hook-mio" 165 | version = "0.2.3" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 168 | dependencies = [ 169 | "libc", 170 | "mio", 171 | "signal-hook", 172 | ] 173 | 174 | [[package]] 175 | name = "signal-hook-registry" 176 | version = "1.4.1" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 179 | dependencies = [ 180 | "libc", 181 | ] 182 | 183 | [[package]] 184 | name = "smallvec" 185 | version = "1.10.0" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 188 | 189 | [[package]] 190 | name = "tui" 191 | version = "0.19.0" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" 194 | dependencies = [ 195 | "bitflags", 196 | "cassowary", 197 | "crossterm 0.25.0", 198 | "unicode-segmentation", 199 | "unicode-width", 200 | ] 201 | 202 | [[package]] 203 | name = "unicode-segmentation" 204 | version = "1.10.1" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 207 | 208 | [[package]] 209 | name = "unicode-width" 210 | version = "0.1.10" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 213 | 214 | [[package]] 215 | name = "wasi" 216 | version = "0.11.0+wasi-snapshot-preview1" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 219 | 220 | [[package]] 221 | name = "winapi" 222 | version = "0.3.9" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 225 | dependencies = [ 226 | "winapi-i686-pc-windows-gnu", 227 | "winapi-x86_64-pc-windows-gnu", 228 | ] 229 | 230 | [[package]] 231 | name = "winapi-i686-pc-windows-gnu" 232 | version = "0.4.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 235 | 236 | [[package]] 237 | name = "winapi-x86_64-pc-windows-gnu" 238 | version = "0.4.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 241 | 242 | [[package]] 243 | name = "windows-sys" 244 | version = "0.45.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 247 | dependencies = [ 248 | "windows-targets", 249 | ] 250 | 251 | [[package]] 252 | name = "windows-targets" 253 | version = "0.42.2" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 256 | dependencies = [ 257 | "windows_aarch64_gnullvm", 258 | "windows_aarch64_msvc", 259 | "windows_i686_gnu", 260 | "windows_i686_msvc", 261 | "windows_x86_64_gnu", 262 | "windows_x86_64_gnullvm", 263 | "windows_x86_64_msvc", 264 | ] 265 | 266 | [[package]] 267 | name = "windows_aarch64_gnullvm" 268 | version = "0.42.2" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 271 | 272 | [[package]] 273 | name = "windows_aarch64_msvc" 274 | version = "0.42.2" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 277 | 278 | [[package]] 279 | name = "windows_i686_gnu" 280 | version = "0.42.2" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 283 | 284 | [[package]] 285 | name = "windows_i686_msvc" 286 | version = "0.42.2" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 289 | 290 | [[package]] 291 | name = "windows_x86_64_gnu" 292 | version = "0.42.2" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 295 | 296 | [[package]] 297 | name = "windows_x86_64_gnullvm" 298 | version = "0.42.2" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 301 | 302 | [[package]] 303 | name = "windows_x86_64_msvc" 304 | version = "0.42.2" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 307 | --------------------------------------------------------------------------------