1use std::path::PathBuf;
7use std::time::Duration;
8
9use crate::config::{
10 BufferConfig, EncodingConfig, LineEnding, LoggingConfig, SessionConfig, TimeoutConfig,
11};
12
13#[derive(Debug, Clone)]
15pub struct SessionBuilder {
16 config: SessionConfig,
17}
18
19impl SessionBuilder {
20 #[must_use]
22 pub fn new() -> Self {
23 Self {
24 config: SessionConfig::default(),
25 }
26 }
27
28 #[must_use]
30 pub fn command(mut self, command: impl Into<String>) -> Self {
31 self.config.command = command.into();
32 self
33 }
34
35 #[must_use]
37 pub fn args<I, S>(mut self, args: I) -> Self
38 where
39 I: IntoIterator<Item = S>,
40 S: Into<String>,
41 {
42 self.config.args = args.into_iter().map(Into::into).collect();
43 self
44 }
45
46 #[must_use]
48 pub fn arg(mut self, arg: impl Into<String>) -> Self {
49 self.config.args.push(arg.into());
50 self
51 }
52
53 #[must_use]
55 pub fn envs<I, K, V>(mut self, envs: I) -> Self
56 where
57 I: IntoIterator<Item = (K, V)>,
58 K: Into<String>,
59 V: Into<String>,
60 {
61 self.config.env = envs
62 .into_iter()
63 .map(|(k, v)| (k.into(), v.into()))
64 .collect();
65 self
66 }
67
68 #[must_use]
70 pub fn env(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
71 self.config.env.insert(key.into(), value.into());
72 self
73 }
74
75 #[must_use]
77 pub fn working_directory(mut self, path: impl Into<PathBuf>) -> Self {
78 self.config.working_dir = Some(path.into());
79 self
80 }
81
82 #[must_use]
84 pub const fn dimensions(mut self, cols: u16, rows: u16) -> Self {
85 self.config.dimensions = (cols, rows);
86 self
87 }
88
89 #[must_use]
91 pub const fn timeout(mut self, timeout: Duration) -> Self {
92 self.config.timeout.default = timeout;
93 self
94 }
95
96 #[must_use]
98 pub const fn timeout_config(mut self, config: TimeoutConfig) -> Self {
99 self.config.timeout = config;
100 self
101 }
102
103 #[must_use]
105 pub const fn buffer_max_size(mut self, max_size: usize) -> Self {
106 self.config.buffer.max_size = max_size;
107 self
108 }
109
110 #[must_use]
112 pub const fn buffer_config(mut self, config: BufferConfig) -> Self {
113 self.config.buffer = config;
114 self
115 }
116
117 #[must_use]
119 pub const fn line_ending(mut self, line_ending: LineEnding) -> Self {
120 self.config.line_ending = line_ending;
121 self
122 }
123
124 #[must_use]
126 pub const fn unix_line_endings(self) -> Self {
127 self.line_ending(LineEnding::Lf)
128 }
129
130 #[must_use]
132 pub const fn windows_line_endings(self) -> Self {
133 self.line_ending(LineEnding::CrLf)
134 }
135
136 #[must_use]
138 pub const fn encoding(mut self, config: EncodingConfig) -> Self {
139 self.config.encoding = config;
140 self
141 }
142
143 #[must_use]
145 pub fn logging(mut self, config: LoggingConfig) -> Self {
146 self.config.logging = config;
147 self
148 }
149
150 #[must_use]
152 pub fn log_to_file(mut self, path: impl Into<PathBuf>) -> Self {
153 self.config.logging.log_file = Some(path.into());
154 self
155 }
156
157 #[must_use]
159 pub fn build(self) -> SessionConfig {
160 self.config
161 }
162}
163
164impl Default for SessionBuilder {
165 fn default() -> Self {
166 Self::new()
167 }
168}
169
170impl From<SessionBuilder> for SessionConfig {
171 fn from(builder: SessionBuilder) -> Self {
172 builder.build()
173 }
174}
175
176pub struct QuickSession;
178
179impl QuickSession {
180 #[must_use]
182 pub fn shell() -> SessionConfig {
183 SessionBuilder::new().command(Self::default_shell()).build()
184 }
185
186 #[must_use]
188 pub fn bash() -> SessionConfig {
189 SessionBuilder::new()
190 .command("/bin/bash")
191 .arg("--norc")
192 .arg("--noprofile")
193 .build()
194 }
195
196 #[must_use]
198 pub fn command(cmd: impl Into<String>) -> SessionConfig {
199 SessionBuilder::new().command(cmd).build()
200 }
201
202 #[must_use]
204 pub fn ssh(host: &str) -> SessionConfig {
205 SessionBuilder::new()
206 .command("ssh")
207 .arg(host)
208 .timeout(Duration::from_secs(30))
209 .build()
210 }
211
212 #[must_use]
214 pub fn ssh_user(user: &str, host: &str) -> SessionConfig {
215 SessionBuilder::new()
216 .command("ssh")
217 .arg(format!("{user}@{host}"))
218 .timeout(Duration::from_secs(30))
219 .build()
220 }
221
222 #[must_use]
224 pub fn telnet(host: &str, port: u16) -> SessionConfig {
225 SessionBuilder::new()
226 .command("telnet")
227 .arg(host)
228 .arg(port.to_string())
229 .timeout(Duration::from_secs(30))
230 .build()
231 }
232
233 #[must_use]
235 pub fn python() -> SessionConfig {
236 SessionBuilder::new()
237 .command(if cfg!(windows) { "python" } else { "python3" })
238 .arg("-i")
239 .build()
240 }
241
242 #[must_use]
246 pub fn cmd() -> SessionConfig {
247 SessionBuilder::new()
248 .command("cmd.exe")
249 .windows_line_endings()
250 .build()
251 }
252
253 #[must_use]
259 pub fn powershell() -> SessionConfig {
260 let command = if cfg!(windows) {
261 "powershell.exe"
262 } else {
263 "pwsh"
264 };
265 SessionBuilder::new()
266 .command(command)
267 .arg("-NoLogo")
268 .arg("-NoProfile")
269 .build()
270 }
271
272 #[must_use]
274 pub fn zsh() -> SessionConfig {
275 SessionBuilder::new()
276 .command("/bin/zsh")
277 .arg("--no-rcs")
278 .build()
279 }
280
281 #[must_use]
283 pub fn fish() -> SessionConfig {
284 SessionBuilder::new()
285 .command("fish")
286 .arg("--no-config")
287 .build()
288 }
289
290 #[must_use]
292 pub fn repl(cmd: impl Into<String>) -> SessionConfig {
293 SessionBuilder::new().command(cmd).build()
294 }
295
296 #[must_use]
298 pub fn node() -> SessionConfig {
299 SessionBuilder::new().command("node").build()
300 }
301
302 #[must_use]
304 pub fn ruby() -> SessionConfig {
305 SessionBuilder::new()
306 .command("irb")
307 .arg("--simple-prompt")
308 .build()
309 }
310
311 #[must_use]
313 pub fn mysql(host: &str, user: &str, database: &str) -> SessionConfig {
314 SessionBuilder::new()
315 .command("mysql")
316 .arg("-h")
317 .arg(host)
318 .arg("-u")
319 .arg(user)
320 .arg(database)
321 .timeout(Duration::from_secs(30))
322 .build()
323 }
324
325 #[must_use]
327 pub fn mysql_password(host: &str, user: &str, database: &str) -> SessionConfig {
328 SessionBuilder::new()
329 .command("mysql")
330 .arg("-h")
331 .arg(host)
332 .arg("-u")
333 .arg(user)
334 .arg("-p")
335 .arg(database)
336 .timeout(Duration::from_secs(30))
337 .build()
338 }
339
340 #[must_use]
342 pub fn psql(host: &str, user: &str, database: &str) -> SessionConfig {
343 SessionBuilder::new()
344 .command("psql")
345 .arg("-h")
346 .arg(host)
347 .arg("-U")
348 .arg(user)
349 .arg(database)
350 .timeout(Duration::from_secs(30))
351 .build()
352 }
353
354 #[must_use]
356 pub fn docker_exec(container: &str) -> SessionConfig {
357 SessionBuilder::new()
358 .command("docker")
359 .arg("exec")
360 .arg("-it")
361 .arg(container)
362 .arg("/bin/sh")
363 .build()
364 }
365
366 #[must_use]
368 pub fn docker_exec_shell(container: &str, shell: &str) -> SessionConfig {
369 SessionBuilder::new()
370 .command("docker")
371 .arg("exec")
372 .arg("-it")
373 .arg(container)
374 .arg(shell)
375 .build()
376 }
377
378 #[must_use]
380 pub fn docker_run(image: &str) -> SessionConfig {
381 SessionBuilder::new()
382 .command("docker")
383 .arg("run")
384 .arg("-it")
385 .arg("--rm")
386 .arg(image)
387 .build()
388 }
389
390 #[must_use]
392 pub fn redis_cli(host: &str) -> SessionConfig {
393 SessionBuilder::new()
394 .command("redis-cli")
395 .arg("-h")
396 .arg(host)
397 .build()
398 }
399
400 #[must_use]
402 pub fn mongosh(uri: &str) -> SessionConfig {
403 SessionBuilder::new()
404 .command("mongosh")
405 .arg(uri)
406 .timeout(Duration::from_secs(30))
407 .build()
408 }
409
410 #[must_use]
412 pub fn sqlite(database: &str) -> SessionConfig {
413 SessionBuilder::new()
414 .command("sqlite3")
415 .arg(database)
416 .build()
417 }
418
419 #[must_use]
421 pub fn gdb(program: &str) -> SessionConfig {
422 SessionBuilder::new().command("gdb").arg(program).build()
423 }
424
425 #[must_use]
427 pub fn lldb(program: &str) -> SessionConfig {
428 SessionBuilder::new().command("lldb").arg(program).build()
429 }
430
431 #[must_use]
433 pub fn lua() -> SessionConfig {
434 SessionBuilder::new().command("lua").arg("-i").build()
435 }
436
437 #[must_use]
439 pub fn perl() -> SessionConfig {
440 SessionBuilder::new().command("perl").arg("-de0").build()
441 }
442
443 #[must_use]
445 pub fn r() -> SessionConfig {
446 SessionBuilder::new()
447 .command("R")
448 .arg("--no-save")
449 .arg("--no-restore")
450 .build()
451 }
452
453 #[must_use]
455 pub fn julia() -> SessionConfig {
456 SessionBuilder::new().command("julia").build()
457 }
458
459 #[must_use]
461 pub fn scala() -> SessionConfig {
462 SessionBuilder::new().command("scala").build()
463 }
464
465 #[must_use]
467 pub fn iex() -> SessionConfig {
468 SessionBuilder::new().command("iex").build()
469 }
470
471 #[must_use]
473 pub fn clojure() -> SessionConfig {
474 SessionBuilder::new().command("clj").build()
475 }
476
477 #[must_use]
479 pub fn ghci() -> SessionConfig {
480 SessionBuilder::new().command("ghci").build()
481 }
482
483 #[must_use]
485 pub fn ocaml() -> SessionConfig {
486 SessionBuilder::new().command("ocaml").build()
487 }
488
489 #[must_use]
491 pub fn kubectl_exec(pod: &str) -> SessionConfig {
492 SessionBuilder::new()
493 .command("kubectl")
494 .arg("exec")
495 .arg("-it")
496 .arg(pod)
497 .arg("--")
498 .arg("/bin/sh")
499 .build()
500 }
501
502 #[must_use]
504 pub fn kubectl_exec_ns(namespace: &str, pod: &str, shell: &str) -> SessionConfig {
505 SessionBuilder::new()
506 .command("kubectl")
507 .arg("exec")
508 .arg("-it")
509 .arg("-n")
510 .arg(namespace)
511 .arg(pod)
512 .arg("--")
513 .arg(shell)
514 .build()
515 }
516
517 #[must_use]
519 pub fn screen_attach(session_name: &str) -> SessionConfig {
520 SessionBuilder::new()
521 .command("screen")
522 .arg("-r")
523 .arg(session_name)
524 .build()
525 }
526
527 #[must_use]
529 pub fn tmux_attach(session_name: &str) -> SessionConfig {
530 SessionBuilder::new()
531 .command("tmux")
532 .arg("attach")
533 .arg("-t")
534 .arg(session_name)
535 .build()
536 }
537
538 #[must_use]
540 pub fn ssh_port(host: &str, port: u16) -> SessionConfig {
541 SessionBuilder::new()
542 .command("ssh")
543 .arg("-p")
544 .arg(port.to_string())
545 .arg(host)
546 .timeout(Duration::from_secs(30))
547 .build()
548 }
549
550 #[must_use]
552 pub fn ssh_full(user: &str, host: &str, port: u16) -> SessionConfig {
553 SessionBuilder::new()
554 .command("ssh")
555 .arg("-p")
556 .arg(port.to_string())
557 .arg(format!("{user}@{host}"))
558 .timeout(Duration::from_secs(30))
559 .build()
560 }
561
562 #[must_use]
564 pub fn ssh_key(user: &str, host: &str, key_file: &str) -> SessionConfig {
565 SessionBuilder::new()
566 .command("ssh")
567 .arg("-i")
568 .arg(key_file)
569 .arg(format!("{user}@{host}"))
570 .timeout(Duration::from_secs(30))
571 .build()
572 }
573
574 #[must_use]
576 pub fn vagrant_ssh() -> SessionConfig {
577 SessionBuilder::new()
578 .command("vagrant")
579 .arg("ssh")
580 .timeout(Duration::from_secs(30))
581 .build()
582 }
583
584 #[must_use]
586 pub fn vagrant_ssh_machine(machine: &str) -> SessionConfig {
587 SessionBuilder::new()
588 .command("vagrant")
589 .arg("ssh")
590 .arg(machine)
591 .timeout(Duration::from_secs(30))
592 .build()
593 }
594
595 #[must_use]
597 pub fn sftp(host: &str) -> SessionConfig {
598 SessionBuilder::new()
599 .command("sftp")
600 .arg(host)
601 .timeout(Duration::from_secs(30))
602 .build()
603 }
604
605 #[must_use]
607 pub fn sftp_user(user: &str, host: &str) -> SessionConfig {
608 SessionBuilder::new()
609 .command("sftp")
610 .arg(format!("{user}@{host}"))
611 .timeout(Duration::from_secs(30))
612 .build()
613 }
614
615 #[must_use]
617 pub fn ftp(host: &str) -> SessionConfig {
618 SessionBuilder::new()
619 .command("ftp")
620 .arg(host)
621 .timeout(Duration::from_secs(30))
622 .build()
623 }
624
625 #[must_use]
627 pub fn netcat(host: &str, port: u16) -> SessionConfig {
628 SessionBuilder::new()
629 .command("nc")
630 .arg(host)
631 .arg(port.to_string())
632 .build()
633 }
634
635 #[must_use]
637 pub fn socat(address: &str) -> SessionConfig {
638 SessionBuilder::new()
639 .command("socat")
640 .arg("-")
641 .arg(address)
642 .build()
643 }
644
645 #[must_use]
647 pub fn minicom(device: &str) -> SessionConfig {
648 SessionBuilder::new()
649 .command("minicom")
650 .arg("-D")
651 .arg(device)
652 .build()
653 }
654
655 #[must_use]
657 pub fn screen_serial(device: &str, baud_rate: u32) -> SessionConfig {
658 SessionBuilder::new()
659 .command("screen")
660 .arg(device)
661 .arg(baud_rate.to_string())
662 .build()
663 }
664
665 #[must_use]
667 pub fn picocom(device: &str, baud_rate: u32) -> SessionConfig {
668 SessionBuilder::new()
669 .command("picocom")
670 .arg("-b")
671 .arg(baud_rate.to_string())
672 .arg(device)
673 .build()
674 }
675
676 #[must_use]
678 pub fn aws_ssm(instance_id: &str) -> SessionConfig {
679 SessionBuilder::new()
680 .command("aws")
681 .arg("ssm")
682 .arg("start-session")
683 .arg("--target")
684 .arg(instance_id)
685 .timeout(Duration::from_secs(60))
686 .build()
687 }
688
689 #[must_use]
691 pub fn az_serial_console(resource_group: &str, vm_name: &str) -> SessionConfig {
692 SessionBuilder::new()
693 .command("az")
694 .arg("serial-console")
695 .arg("connect")
696 .arg("--resource-group")
697 .arg(resource_group)
698 .arg("--name")
699 .arg(vm_name)
700 .timeout(Duration::from_secs(60))
701 .build()
702 }
703
704 #[must_use]
706 pub fn gcloud_ssh(instance: &str, zone: &str) -> SessionConfig {
707 SessionBuilder::new()
708 .command("gcloud")
709 .arg("compute")
710 .arg("ssh")
711 .arg(instance)
712 .arg("--zone")
713 .arg(zone)
714 .timeout(Duration::from_secs(60))
715 .build()
716 }
717
718 #[must_use]
720 pub fn evcxr() -> SessionConfig {
721 SessionBuilder::new().command("evcxr").build()
722 }
723
724 #[must_use]
726 pub fn gore() -> SessionConfig {
727 SessionBuilder::new().command("gore").build()
728 }
729
730 #[must_use]
732 pub fn php() -> SessionConfig {
733 SessionBuilder::new().command("php").arg("-a").build()
734 }
735
736 #[must_use]
738 pub fn swift() -> SessionConfig {
739 SessionBuilder::new().command("swift").build()
740 }
741
742 #[must_use]
744 pub fn kotlin() -> SessionConfig {
745 SessionBuilder::new().command("kotlin").build()
746 }
747
748 #[must_use]
750 pub fn groovysh() -> SessionConfig {
751 SessionBuilder::new().command("groovysh").build()
752 }
753
754 #[must_use]
756 pub fn ts_node() -> SessionConfig {
757 SessionBuilder::new().command("ts-node").build()
758 }
759
760 #[must_use]
762 pub fn deno() -> SessionConfig {
763 SessionBuilder::new().command("deno").build()
764 }
765
766 #[must_use]
768 pub fn bun() -> SessionConfig {
769 SessionBuilder::new().command("bun").arg("repl").build()
770 }
771
772 #[must_use]
774 pub fn default_shell() -> String {
775 std::env::var("SHELL").unwrap_or_else(|_| {
776 if cfg!(windows) {
777 "cmd.exe".to_string()
778 } else {
779 "/bin/sh".to_string()
780 }
781 })
782 }
783}
784
785#[cfg(test)]
786mod tests {
787 use super::*;
788
789 #[test]
790 fn builder_basic() {
791 let config = SessionBuilder::new()
792 .command("/bin/bash")
793 .arg("-c")
794 .arg("echo hello")
795 .build();
796
797 assert_eq!(config.command, "/bin/bash");
798 assert_eq!(config.args, vec!["-c", "echo hello"]);
799 }
800
801 #[test]
802 fn builder_env() {
803 let config = SessionBuilder::new()
804 .command("test")
805 .env("FOO", "bar")
806 .env("BAZ", "qux")
807 .build();
808
809 assert_eq!(config.env.get("FOO"), Some(&"bar".to_string()));
810 assert_eq!(config.env.get("BAZ"), Some(&"qux".to_string()));
811 }
812
813 #[test]
814 fn builder_timeout() {
815 let config = SessionBuilder::new()
816 .command("test")
817 .timeout(Duration::from_secs(60))
818 .build();
819
820 assert_eq!(config.timeout.default, Duration::from_secs(60));
821 }
822
823 #[test]
824 fn quick_session_bash() {
825 let config = QuickSession::bash();
826 assert_eq!(config.command, "/bin/bash");
827 assert!(config.args.contains(&"--norc".to_string()));
828 }
829
830 #[test]
831 fn quick_session_ssh() {
832 let config = QuickSession::ssh_user("admin", "example.com");
833 assert_eq!(config.command, "ssh");
834 assert!(config.args.contains(&"admin@example.com".to_string()));
835 }
836
837 #[test]
838 fn quick_session_cmd() {
839 let config = QuickSession::cmd();
840 assert_eq!(config.command, "cmd.exe");
841 assert_eq!(config.line_ending, LineEnding::CrLf);
842 }
843
844 #[test]
845 fn quick_session_powershell() {
846 let config = QuickSession::powershell();
847 #[cfg(windows)]
848 assert_eq!(config.command, "powershell.exe");
849 #[cfg(not(windows))]
850 assert_eq!(config.command, "pwsh");
851 assert!(config.args.contains(&"-NoLogo".to_string()));
852 assert!(config.args.contains(&"-NoProfile".to_string()));
853 }
854
855 #[test]
856 fn quick_session_zsh() {
857 let config = QuickSession::zsh();
858 assert_eq!(config.command, "/bin/zsh");
859 assert!(config.args.contains(&"--no-rcs".to_string()));
860 }
861
862 #[test]
863 fn quick_session_fish() {
864 let config = QuickSession::fish();
865 assert_eq!(config.command, "fish");
866 assert!(config.args.contains(&"--no-config".to_string()));
867 }
868
869 #[test]
870 fn quick_session_python() {
871 let config = QuickSession::python();
872 #[cfg(windows)]
873 assert_eq!(config.command, "python");
874 #[cfg(not(windows))]
875 assert_eq!(config.command, "python3");
876 assert!(config.args.contains(&"-i".to_string()));
877 }
878
879 #[test]
880 fn quick_session_node() {
881 let config = QuickSession::node();
882 assert_eq!(config.command, "node");
883 }
884
885 #[test]
886 fn quick_session_ruby() {
887 let config = QuickSession::ruby();
888 assert_eq!(config.command, "irb");
889 assert!(config.args.contains(&"--simple-prompt".to_string()));
890 }
891
892 #[test]
893 fn quick_session_mysql() {
894 let config = QuickSession::mysql("localhost", "root", "testdb");
895 assert_eq!(config.command, "mysql");
896 assert!(config.args.contains(&"-h".to_string()));
897 assert!(config.args.contains(&"localhost".to_string()));
898 assert!(config.args.contains(&"-u".to_string()));
899 assert!(config.args.contains(&"root".to_string()));
900 assert!(config.args.contains(&"testdb".to_string()));
901 }
902
903 #[test]
904 fn quick_session_psql() {
905 let config = QuickSession::psql("localhost", "postgres", "mydb");
906 assert_eq!(config.command, "psql");
907 assert!(config.args.contains(&"-h".to_string()));
908 assert!(config.args.contains(&"-U".to_string()));
909 assert!(config.args.contains(&"postgres".to_string()));
910 }
911
912 #[test]
913 fn quick_session_docker_exec() {
914 let config = QuickSession::docker_exec("my-container");
915 assert_eq!(config.command, "docker");
916 assert!(config.args.contains(&"exec".to_string()));
917 assert!(config.args.contains(&"-it".to_string()));
918 assert!(config.args.contains(&"my-container".to_string()));
919 assert!(config.args.contains(&"/bin/sh".to_string()));
920 }
921
922 #[test]
923 fn quick_session_docker_run() {
924 let config = QuickSession::docker_run("ubuntu:latest");
925 assert_eq!(config.command, "docker");
926 assert!(config.args.contains(&"run".to_string()));
927 assert!(config.args.contains(&"-it".to_string()));
928 assert!(config.args.contains(&"--rm".to_string()));
929 assert!(config.args.contains(&"ubuntu:latest".to_string()));
930 }
931
932 #[test]
933 fn quick_session_redis() {
934 let config = QuickSession::redis_cli("redis.example.com");
935 assert_eq!(config.command, "redis-cli");
936 assert!(config.args.contains(&"-h".to_string()));
937 assert!(config.args.contains(&"redis.example.com".to_string()));
938 }
939
940 #[test]
941 fn quick_session_sqlite() {
942 let config = QuickSession::sqlite("test.db");
943 assert_eq!(config.command, "sqlite3");
944 assert!(config.args.contains(&"test.db".to_string()));
945 }
946
947 #[test]
948 fn quick_session_gdb() {
949 let config = QuickSession::gdb("./my_program");
950 assert_eq!(config.command, "gdb");
951 assert!(config.args.contains(&"./my_program".to_string()));
952 }
953
954 #[test]
955 fn quick_session_kubectl() {
956 let config = QuickSession::kubectl_exec("my-pod");
957 assert_eq!(config.command, "kubectl");
958 assert!(config.args.contains(&"exec".to_string()));
959 assert!(config.args.contains(&"-it".to_string()));
960 assert!(config.args.contains(&"my-pod".to_string()));
961 assert!(config.args.contains(&"--".to_string()));
962 assert!(config.args.contains(&"/bin/sh".to_string()));
963 }
964
965 #[test]
966 fn quick_session_kubectl_ns() {
967 let config = QuickSession::kubectl_exec_ns("production", "api-pod", "/bin/bash");
968 assert_eq!(config.command, "kubectl");
969 assert!(config.args.contains(&"-n".to_string()));
970 assert!(config.args.contains(&"production".to_string()));
971 assert!(config.args.contains(&"api-pod".to_string()));
972 assert!(config.args.contains(&"/bin/bash".to_string()));
973 }
974
975 #[test]
976 fn quick_session_repls() {
977 assert_eq!(QuickSession::lua().command, "lua");
979 assert_eq!(QuickSession::julia().command, "julia");
980 assert_eq!(QuickSession::scala().command, "scala");
981 assert_eq!(QuickSession::iex().command, "iex");
982 assert_eq!(QuickSession::clojure().command, "clj");
983 assert_eq!(QuickSession::ghci().command, "ghci");
984 assert_eq!(QuickSession::ocaml().command, "ocaml");
985 assert_eq!(QuickSession::r().command, "R");
986 }
987
988 #[test]
989 fn quick_session_tmux_screen() {
990 let config = QuickSession::tmux_attach("mysession");
991 assert_eq!(config.command, "tmux");
992 assert!(config.args.contains(&"attach".to_string()));
993 assert!(config.args.contains(&"-t".to_string()));
994 assert!(config.args.contains(&"mysession".to_string()));
995
996 let config = QuickSession::screen_attach("myscreen");
997 assert_eq!(config.command, "screen");
998 assert!(config.args.contains(&"-r".to_string()));
999 assert!(config.args.contains(&"myscreen".to_string()));
1000 }
1001
1002 #[test]
1003 fn quick_session_ssh_variants() {
1004 let config = QuickSession::ssh_port("example.com", 2222);
1006 assert_eq!(config.command, "ssh");
1007 assert!(config.args.contains(&"-p".to_string()));
1008 assert!(config.args.contains(&"2222".to_string()));
1009 assert!(config.args.contains(&"example.com".to_string()));
1010
1011 let config = QuickSession::ssh_full("admin", "server.com", 2222);
1013 assert_eq!(config.command, "ssh");
1014 assert!(config.args.contains(&"-p".to_string()));
1015 assert!(config.args.contains(&"2222".to_string()));
1016 assert!(config.args.contains(&"admin@server.com".to_string()));
1017
1018 let config = QuickSession::ssh_key("root", "host.com", "/path/to/key");
1020 assert_eq!(config.command, "ssh");
1021 assert!(config.args.contains(&"-i".to_string()));
1022 assert!(config.args.contains(&"/path/to/key".to_string()));
1023 assert!(config.args.contains(&"root@host.com".to_string()));
1024 }
1025
1026 #[test]
1027 fn quick_session_vagrant() {
1028 let config = QuickSession::vagrant_ssh();
1029 assert_eq!(config.command, "vagrant");
1030 assert!(config.args.contains(&"ssh".to_string()));
1031
1032 let config = QuickSession::vagrant_ssh_machine("web");
1033 assert_eq!(config.command, "vagrant");
1034 assert!(config.args.contains(&"ssh".to_string()));
1035 assert!(config.args.contains(&"web".to_string()));
1036 }
1037
1038 #[test]
1039 fn quick_session_file_transfer() {
1040 let config = QuickSession::sftp("server.com");
1041 assert_eq!(config.command, "sftp");
1042 assert!(config.args.contains(&"server.com".to_string()));
1043
1044 let config = QuickSession::sftp_user("admin", "server.com");
1045 assert_eq!(config.command, "sftp");
1046 assert!(config.args.contains(&"admin@server.com".to_string()));
1047
1048 let config = QuickSession::ftp("ftp.example.com");
1049 assert_eq!(config.command, "ftp");
1050 assert!(config.args.contains(&"ftp.example.com".to_string()));
1051 }
1052
1053 #[test]
1054 fn quick_session_network_tools() {
1055 let config = QuickSession::netcat("localhost", 8080);
1056 assert_eq!(config.command, "nc");
1057 assert!(config.args.contains(&"localhost".to_string()));
1058 assert!(config.args.contains(&"8080".to_string()));
1059
1060 let config = QuickSession::socat("TCP:server:1234");
1061 assert_eq!(config.command, "socat");
1062 assert!(config.args.contains(&"-".to_string()));
1063 assert!(config.args.contains(&"TCP:server:1234".to_string()));
1064 }
1065
1066 #[test]
1067 fn quick_session_serial_terminals() {
1068 let config = QuickSession::minicom("/dev/ttyUSB0");
1069 assert_eq!(config.command, "minicom");
1070 assert!(config.args.contains(&"-D".to_string()));
1071 assert!(config.args.contains(&"/dev/ttyUSB0".to_string()));
1072
1073 let config = QuickSession::screen_serial("/dev/ttyACM0", 115_200);
1074 assert_eq!(config.command, "screen");
1075 assert!(config.args.contains(&"/dev/ttyACM0".to_string()));
1076 assert!(config.args.contains(&"115200".to_string()));
1077
1078 let config = QuickSession::picocom("/dev/ttyS0", 9600);
1079 assert_eq!(config.command, "picocom");
1080 assert!(config.args.contains(&"-b".to_string()));
1081 assert!(config.args.contains(&"9600".to_string()));
1082 assert!(config.args.contains(&"/dev/ttyS0".to_string()));
1083 }
1084
1085 #[test]
1086 fn quick_session_cloud_providers() {
1087 let config = QuickSession::aws_ssm("i-1234567890abcdef0");
1088 assert_eq!(config.command, "aws");
1089 assert!(config.args.contains(&"ssm".to_string()));
1090 assert!(config.args.contains(&"start-session".to_string()));
1091 assert!(config.args.contains(&"--target".to_string()));
1092 assert!(config.args.contains(&"i-1234567890abcdef0".to_string()));
1093
1094 let config = QuickSession::az_serial_console("my-rg", "my-vm");
1095 assert_eq!(config.command, "az");
1096 assert!(config.args.contains(&"serial-console".to_string()));
1097 assert!(config.args.contains(&"connect".to_string()));
1098 assert!(config.args.contains(&"--resource-group".to_string()));
1099 assert!(config.args.contains(&"my-rg".to_string()));
1100 assert!(config.args.contains(&"--name".to_string()));
1101 assert!(config.args.contains(&"my-vm".to_string()));
1102
1103 let config = QuickSession::gcloud_ssh("instance-1", "us-central1-a");
1104 assert_eq!(config.command, "gcloud");
1105 assert!(config.args.contains(&"compute".to_string()));
1106 assert!(config.args.contains(&"ssh".to_string()));
1107 assert!(config.args.contains(&"instance-1".to_string()));
1108 assert!(config.args.contains(&"--zone".to_string()));
1109 assert!(config.args.contains(&"us-central1-a".to_string()));
1110 }
1111
1112 #[test]
1113 fn quick_session_additional_repls() {
1114 assert_eq!(QuickSession::evcxr().command, "evcxr");
1116
1117 assert_eq!(QuickSession::gore().command, "gore");
1119
1120 let config = QuickSession::php();
1122 assert_eq!(config.command, "php");
1123 assert!(config.args.contains(&"-a".to_string()));
1124
1125 assert_eq!(QuickSession::swift().command, "swift");
1127
1128 assert_eq!(QuickSession::kotlin().command, "kotlin");
1130
1131 assert_eq!(QuickSession::groovysh().command, "groovysh");
1133
1134 assert_eq!(QuickSession::ts_node().command, "ts-node");
1136
1137 assert_eq!(QuickSession::deno().command, "deno");
1139
1140 let config = QuickSession::bun();
1142 assert_eq!(config.command, "bun");
1143 assert!(config.args.contains(&"repl".to_string()));
1144 }
1145}