sway_workspace_manager/
command.rs1pub enum Position {
2 Prev { cycle: bool },
3 Next { cycle: bool },
4 Start,
5 End,
6 Num { num: usize, extra: bool },
7}
8
9impl Position {
10 pub fn num_existing(
11 &self,
12 current_index: usize,
13 num_workspaces: usize,
14 ) -> Result<usize, swayipc::Error> {
15 let (index, len) = (current_index, num_workspaces);
16
17 match *self {
18 Position::Prev { cycle } => {
19 if index == 1 {
20 if cycle {
21 Ok(len)
22 } else {
23 Err(swayipc::Error::CommandFailed(
24 "No previous workspace in the first workspace".to_string(),
25 ))
26 }
27 } else {
28 Ok(index - 1)
29 }
30 }
31
32 Position::Next { cycle } => {
33 if index == len {
34 if cycle {
35 Ok(1)
36 } else {
37 Err(swayipc::Error::CommandFailed(
38 "No next workspace in the last workspace".to_string(),
39 ))
40 }
41 } else {
42 Ok(index + 1)
43 }
44 }
45
46 Position::Start => Ok(1),
47
48 Position::End => Ok(len),
49
50 Position::Num { num, extra } => {
51 if 1 <= num && (!extra && num <= len || extra && num <= len + 1) {
52 Ok(num)
53 } else {
54 Err(swayipc::Error::CommandFailed(
55 "Workspace number out of range".to_string(),
56 ))
57 }
58 }
59 }
60 }
61
62 pub fn num_new(
63 &self,
64 current_index: usize,
65 num_workspaces: usize,
66 ) -> Result<usize, swayipc::Error> {
67 let (index, len) = (current_index, num_workspaces);
68
69 match *self {
70 Position::Prev { cycle: _ } => Ok(index),
71
72 Position::Next { cycle: _ } => Ok(index + 1),
73
74 Position::Start => Ok(1),
75
76 Position::End => Ok(len + 1),
77
78 Position::Num { num, .. } => {
79 if 1 <= num && num <= len + 1 {
80 Ok(num)
81 } else {
82 Err(swayipc::Error::CommandFailed(
83 "Workspace number out of range".to_string(),
84 ))
85 }
86 }
87 }
88 }
89}
90
91pub enum Command {
92 Reorder { daemon: bool },
93 Switch { target: Position, carry: bool },
94 Create { target: Position, carry: bool },
95 Swap { target: Position },
96 Rename { new_name: String },
97}
98
99impl Command {
100 pub fn new(mut args: impl Iterator<Item = String>) -> Result<Self, &'static str> {
101 args.next();
102
103 let verb = args.next().ok_or("not enough arguments")?;
104
105 if verb.as_str() == "reorder" {
106 let daemon = args.any(|flag| flag.as_str() == "--daemon");
107 return Ok(Self::Reorder { daemon });
108 }
109
110 if verb.as_str() == "rename" {
111 let new_name = args.next().ok_or("not enough argumets")?;
112 return Ok(Self::Rename { new_name });
113 }
114
115 let position = args.next().ok_or("not enough arguments")?;
116
117 let mut cycle = false;
118 let mut extra = false;
119 while let Some(flag) = args.next() {
120 match flag.as_str() {
121 "--cycle" => cycle = true,
122 "--extra" => extra = true,
123 _ => (),
124 };
125 }
126
127 let target = match position.as_str() {
128 "prev" => Ok(Position::Prev { cycle }),
129 "next" => Ok(Position::Next { cycle }),
130 "start" => Ok(Position::Start),
131 "end" => Ok(Position::End),
132 other => other
133 .parse::<usize>()
134 .map(|num| Position::Num { num, extra })
135 .or(Err("invalid target")),
136 }?;
137
138 match verb.as_str() {
139 "switch" => Ok(Self::Switch {
140 target,
141 carry: false,
142 }),
143 "move" => Ok(Self::Switch {
144 target,
145 carry: true,
146 }),
147 "create" => Ok(Self::Create {
148 target,
149 carry: false,
150 }),
151 "move-to-new" => Ok(Self::Create {
152 target,
153 carry: true,
154 }),
155 "swap" => Ok(Self::Swap { target }),
156
157 _ => Err("invalid commnd"),
158 }
159 }
160}