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