1 //
2 // aegis - project change supervisor
3 // Copyright (C) 2002-2008, 2011, 2012 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19
20 #include <libaegis/arglex2.h>
21 #include <libaegis/change.h>
22 #include <libaegis/cstate.fmtgen.h>
23 #include <libaegis/project.h>
24 #include <libaegis/user.h>
25 #include <libaegis/zero.h>
26
27 #include <aecomplete/command/aecpu.h>
28 #include <aecomplete/command/generic.h>
29 #include <aecomplete/command/private.h>
30 #include <aecomplete/complete/change/file.h>
31 #include <aecomplete/complete/change/number.h>
32 #include <aecomplete/complete/project/name.h>
33
34
35 static void
destructor(command_ty *)36 destructor(command_ty *)
37 {
38 }
39
40
41 static void
do_nothing(void)42 do_nothing(void)
43 {
44 }
45
46
47 static complete_ty *
completion_get(command_ty *)48 completion_get(command_ty *)
49 {
50 int action_mask;
51 complete_ty *result;
52 int incomplete_change_number;
53 string_ty *project_name;
54 long change_number;
55 project *pp;
56 user_ty::pointer up;
57 change::pointer cp;
58 int baserel;
59
60 arglex2_retable(0);
61 arglex();
62 incomplete_change_number = 0;
63 project_name = 0;
64 change_number = 0;
65 while (arglex_token != arglex_token_eoln)
66 {
67 switch (arglex_token)
68 {
69 default:
70 result = generic_argument_complete();
71 if (result)
72 return result;
73 continue;
74
75 case arglex_token_directory:
76 case arglex_token_file:
77 // noise word, ignore
78 break;
79
80 case arglex_token_string:
81 // whole file name, ignore
82 break;
83
84 case arglex_token_string_incomplete:
85 // incomplete file name
86 break;
87
88 case arglex_token_change:
89 switch (arglex())
90 {
91 default:
92 continue;
93
94 case arglex_token_number:
95 if (arglex_value.alv_number == 0)
96 change_number = MAGIC_ZERO;
97 else if (arglex_value.alv_number > 0)
98 change_number = arglex_value.alv_number;
99 break;
100
101 case arglex_token_number_incomplete:
102 case arglex_token_string_incomplete:
103 incomplete_change_number = 1;
104 break;
105 }
106 break;
107
108 case arglex_token_number:
109 if (arglex_value.alv_number == 0)
110 change_number = MAGIC_ZERO;
111 else if (arglex_value.alv_number > 0)
112 change_number = arglex_value.alv_number;
113 break;
114
115 case arglex_token_number_incomplete:
116 incomplete_change_number = 1;
117 break;
118
119 case arglex_token_project:
120 switch (arglex())
121 {
122 default:
123 continue;
124
125 case arglex_token_string:
126 project_name = str_from_c(arglex_value.alv_string);
127 break;
128
129 case arglex_token_string_incomplete:
130 case arglex_token_number_incomplete:
131 return complete_project_name();
132 }
133 break;
134
135 case arglex_token_base_relative:
136 case arglex_token_current_relative:
137 user_ty::relative_filename_preference_argument(do_nothing);
138 break;
139 }
140 arglex();
141 }
142
143 //
144 // Work out which project to use.
145 //
146 if (!project_name)
147 {
148 nstring n = user_ty::create()->default_project();
149 project_name = str_copy(n.get_ref());
150 }
151 pp = project_alloc(project_name);
152 pp->bind_existing();
153
154 //
155 // If we need to complete a change number, we have the project now.
156 //
157 if (incomplete_change_number)
158 return complete_change_number(pp, 1 << cstate_state_being_developed);
159
160 //
161 // locate user data
162 //
163 up = user_ty::create();
164
165 //
166 // locate change data
167 //
168 if (!change_number)
169 change_number = up->default_change(pp);
170 cp = change_alloc(pp, change_number);
171 change_bind_existing(cp);
172
173 //
174 // Figure out whether we are using base relative file names, or
175 // current directory relative file names.
176 //
177 baserel =
178 (
179 up->relative_filename_preference
180 (
181 uconf_relative_filename_preference_current
182 )
183 ==
184 uconf_relative_filename_preference_base
185 );
186
187 //
188 // We are going to complete a change file name.
189 //
190 action_mask = (1 << file_action_modify) | (1 << file_action_insulate);
191 return complete_change_file(cp, baserel, 0, action_mask);
192 }
193
194
195 static command_vtbl_ty vtbl =
196 {
197 destructor,
198 completion_get,
199 sizeof(command_ty),
200 "aecpu",
201 };
202
203
204 command_ty *
command_aecpu()205 command_aecpu()
206 {
207 return command_new(&vtbl);
208 }
209
210
211 // vim: set ts=8 sw=4 et :
212