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/aerm.h>
28 #include <aecomplete/command/generic.h>
29 #include <aecomplete/command/private.h>
30 #include <aecomplete/complete/change/number.h>
31 #include <aecomplete/complete/project/file.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 complete_ty *result;
51 int incomplete_change_number;
52 string_ty *project_name;
53 long change_number;
54 project *pp;
55 user_ty::pointer up;
56 change::pointer cp;
57 int baserel;
58
59 arglex2_retable(0);
60 arglex();
61 incomplete_change_number = 0;
62 project_name = 0;
63 change_number = 0;
64 while (arglex_token != arglex_token_eoln)
65 {
66 switch (arglex_token)
67 {
68 default:
69 result = generic_argument_complete();
70 if (result)
71 return result;
72 continue;
73
74 case arglex_token_directory:
75 case arglex_token_file:
76 // noise word, ignore
77 break;
78
79 case arglex_token_string:
80 // whole file name, ignore
81 break;
82
83 case arglex_token_string_incomplete:
84 // incomplete filename
85 break;
86
87 case arglex_token_change:
88 switch (arglex())
89 {
90 default:
91 continue;
92
93 case arglex_token_number:
94 if (arglex_value.alv_number == 0)
95 change_number = MAGIC_ZERO;
96 else if (arglex_value.alv_number > 0)
97 change_number = arglex_value.alv_number;
98 break;
99
100 case arglex_token_number_incomplete:
101 case arglex_token_string_incomplete:
102 incomplete_change_number = 1;
103 break;
104 }
105 break;
106
107 case arglex_token_number:
108 if (arglex_value.alv_number == 0)
109 change_number = MAGIC_ZERO;
110 else if (arglex_value.alv_number > 0)
111 change_number = arglex_value.alv_number;
112 break;
113
114 case arglex_token_number_incomplete:
115 incomplete_change_number = 1;
116 break;
117
118 case arglex_token_project:
119 switch (arglex())
120 {
121 default:
122 continue;
123
124 case arglex_token_string:
125 project_name = str_from_c(arglex_value.alv_string);
126 break;
127
128 case arglex_token_string_incomplete:
129 case arglex_token_number_incomplete:
130 return complete_project_name();
131 }
132 break;
133
134 case arglex_token_base_relative:
135 case arglex_token_current_relative:
136 user_ty::relative_filename_preference_argument(do_nothing);
137 break;
138 }
139 arglex();
140 }
141
142 //
143 // Work out which project to use.
144 //
145 if (!project_name)
146 {
147 nstring n = user_ty::create()->default_project();
148 project_name = str_copy(n.get_ref());
149 }
150 pp = project_alloc(project_name);
151 pp->bind_existing();
152
153 //
154 // If we need to complete a change number, we have the project now.
155 //
156 if (incomplete_change_number)
157 return complete_change_number(pp, 1 << cstate_state_being_developed);
158
159 //
160 // locate user data
161 //
162 up = user_ty::create();
163
164 //
165 // locate change data
166 //
167 if (!change_number)
168 change_number = up->default_change(pp);
169 cp = change_alloc(pp, change_number);
170 change_bind_existing(cp);
171
172 //
173 // Figure out whether we are using base relative file names, or
174 // current directory relative file names.
175 //
176 baserel =
177 (
178 up->relative_filename_preference
179 (
180 uconf_relative_filename_preference_current
181 )
182 ==
183 uconf_relative_filename_preference_base
184 );
185
186 //
187 // We are going to complete a project file name.
188 //
189 return complete_project_file(cp, baserel, 0);
190 }
191
192
193 static command_vtbl_ty vtbl =
194 {
195 destructor,
196 completion_get,
197 sizeof(command_ty),
198 "aerm",
199 };
200
201
202 command_ty *
command_aerm()203 command_aerm()
204 {
205 return command_new(&vtbl);
206 }
207
208
209 // vim: set ts=8 sw=4 et :
210