1    	package acl2s.plugin.wizards;
2    	
3    	import org.eclipse.core.resources.IContainer;
4    	import org.eclipse.core.resources.IResource;
5    	import org.eclipse.core.resources.ResourcesPlugin;
6    	import org.eclipse.core.runtime.Path;
7    	import org.eclipse.jface.viewers.ISelection;
8    	import org.eclipse.jface.viewers.IStructuredSelection;
9    	import org.eclipse.jface.wizard.WizardPage;
10   	import org.eclipse.swt.SWT;
11   	import org.eclipse.swt.events.ModifyEvent;
12   	import org.eclipse.swt.events.ModifyListener;
13   	import org.eclipse.swt.events.SelectionAdapter;
14   	import org.eclipse.swt.events.SelectionEvent;
15   	import org.eclipse.swt.layout.GridData;
16   	import org.eclipse.swt.layout.GridLayout;
17   	import org.eclipse.swt.layout.RowLayout;
18   	import org.eclipse.swt.widgets.Button;
19   	import org.eclipse.swt.widgets.Composite;
20   	import org.eclipse.swt.widgets.Group;
21   	import org.eclipse.swt.widgets.Label;
22   	import org.eclipse.swt.widgets.Text;
23   	import org.eclipse.ui.dialogs.ContainerSelectionDialog;
24   	import org.peterd.util.Misc;
25   	
26   	import acl2s.lib.parse.obj.Str;
27   	import acl2s.lib.session.SessionMode;
28   	import acl2s.plugin.Acl2sPlugin;
29   	import acl2s.plugin.editors.lisp.LispDocument;
30   	
31   	public class NewLispPage extends WizardPage implements ModifyListener {
32   		private Text containerText;
33   		private Text fileText;
34   		private Button[] modeButtons;
35   		private Button bookButton;
36   		private Button a2sButton;
37   		private Text pkgText;
38   		
39   		private IContainer containerResource;
40   		private NewLispCreator creator;
41   		private String fileName;
42   		
43   		private ISelection selection;
44   	
45   		private final SessionMode[] modes;
46   		
47   		protected NewLispPage(ISelection selection) {
48   			super("wizardPage", "New ACL2/Lisp File", null);
49   			this.selection = selection;
50   			modes = Acl2sPlugin.getBaseConfig().getModes();
51   			/*for (int i = 1; i < modes.length; i++) {
52   				if (modes[i].equals(MyConfig.getDefaultMode())) {
53   					modes[i] = modes[0];
54   					modes[0] = MyConfig.getDefaultMode();
55   					break;
56   				}
57   			}*/
58   		}
59   	
60   		public void createControl(Composite parent) {
61   			Composite container = new Composite(parent, SWT.NULL);
62   			GridLayout layout = new GridLayout();
63   			container.setLayout(layout);
64   			layout.numColumns = 3;
65   			layout.verticalSpacing = 12;
66   			
67   			
68   			Label label = new Label(container, SWT.NULL);
69   			label.setText("&Directory:");
70   	
71   			containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
72   			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
73   			containerText.setLayoutData(gd);
74   			containerText.addModifyListener(this);
75   	
76   			Button button = new Button(container, SWT.PUSH);
77   			button.setText("Browse...");
78   			button.addSelectionListener(new SelectionHandler() {
79   				public void widgetSelected(SelectionEvent e) {
80   					handleBrowse();
81   				}
82   			});
83   			
84   			
85   			
86   			label = new Label(container, SWT.NULL);
87   			label.setText("&File name:");
88   	
89   			fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
90   			gd = new GridData(GridData.FILL_HORIZONTAL);
91   			gd.horizontalSpan = 2;
92   			fileText.setLayoutData(gd);
93   			fileText.addModifyListener(this);
94   			
95   			
96   			Group grp = new Group(container, 0);
97   			grp.setText("Which ACL2 mode (can change later)?");
98   			gd = new GridData(GridData.FILL_HORIZONTAL);
99   			gd.horizontalSpan = 3;
100  			grp.setLayoutData(gd);
101  			grp.setLayout(new RowLayout(SWT.VERTICAL));
102  			modeButtons = new Button[modes.length];
103  			for (int i = 0; i < modes.length; i++) {
104  				modeButtons[i] = new Button(grp, SWT.RADIO);
105  				modeButtons[i].setText(modes[i].getName() + " - " + modes[i].getShortDesc());
106  				modeButtons[i].setSelection(i == 0);
107  				modeButtons[i].addSelectionListener(new SelectionHandler());
108  			}
109  			
110  			a2sButton = new Button(container, SWT.CHECK);
111  			a2sButton.setText("Create an associated ACL2 session file (recommended)");
112  			a2sButton.addSelectionListener(new SelectionHandler());
113  			a2sButton.setSelection(true);
114  			gd = new GridData(GridData.FILL_HORIZONTAL);
115  			gd.horizontalSpan = 3;
116  			a2sButton.setLayoutData(gd);
117  			
118  			
119  			grp = new Group(container, 0);
120  			grp.setText("Options for auto-generating text/code in the new file");
121  			gd = new GridData(GridData.FILL_HORIZONTAL);
122  			gd.horizontalSpan = 3;
123  			grp.setLayoutData(gd);
124  			layout = new GridLayout();
125  			grp.setLayout(layout);
126  			layout.numColumns = 2;
127  			layout.verticalSpacing = 9;
128  	
129  			
130  			bookButton = new Button(grp, SWT.CHECK);
131  			bookButton.setText("Create with book code");
132  			bookButton.addSelectionListener(new SelectionHandler());
133  			gd = new GridData(GridData.FILL_HORIZONTAL);
134  			gd.horizontalSpan = 2;
135  			bookButton.setLayoutData(gd);
136  			
137  	
138  			
139  			label = new Label(grp, SWT.NULL);
140  			label.setText("ACL2 &Package (optional):");
141  	
142  			pkgText = new Text(grp, SWT.BORDER | SWT.SINGLE);
143  			gd = new GridData(GridData.FILL_HORIZONTAL);
144  			pkgText.setLayoutData(gd);
145  			pkgText.addModifyListener(this);
146  			
147  			
148  			initialize();
149  			dialogChanged();
150  			setControl(container);
151  		}
152  	
153  		private void initialize() {
154  			if (selection != null && selection.isEmpty() == false
155  					&& selection instanceof IStructuredSelection) {
156  				IStructuredSelection ssel = (IStructuredSelection) selection;
157  				if (ssel.size() > 1)
158  					return;
159  				Object obj = ssel.getFirstElement();
160  				if (obj instanceof IResource) {
161  					IContainer container;
162  					if (obj instanceof IContainer)
163  						container = (IContainer) obj;
164  					else
165  						container = ((IResource) obj).getParent();
166  					containerText.setText(container.getFullPath().toString());
167  				}
168  			}
169  			fileText.setText("mybook.lisp");
170  		}
171  	
172  		private void handleBrowse() {
173  			ContainerSelectionDialog dialog = new ContainerSelectionDialog(
174  					getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
175  					"Select enclosing project and directory");
176  			if (dialog.open() == ContainerSelectionDialog.OK) {
177  				Object[] result = dialog.getResult();
178  				if (result.length == 1) {
179  					containerText.setText(((Path) result[0]).toString());
180  				}
181  			}
182  		}
183  	
184  		private void dialogChanged() {
185  			// UPDATING
186  			creator = new NewLispCreator();
187  	
188  			for (int i = 0; i < modeButtons.length; i++) {
189  				if (modeButtons[i].getSelection()) {
190  					creator.mode = modes[i];
191  					if (modes[i].getBookDevAllowed()) {
192  						bookButton.setEnabled(true);
193  					} else {
194  						bookButton.setEnabled(false);
195  						bookButton.setSelection(false);
196  					}
197  				}
198  			}
199  			
200  			if (bookButton.getSelection()) {
201  				creator.book = creator.new BookInfo();
202  			} else {
203  				creator.book = null;
204  			}
205  			
206  			creator.pkg = pkgText.getText();
207  	
208  			// CHECKING
209  			if (containerText.getText().length() == 0) {
210  				updateStatus("File container must be specified");
211  				return;
212  			}
213  			Path cp = new Path(containerText.getText());
214  			IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(cp);
215  			if (res == null
216  					|| (res.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
217  				updateStatus("File container must exist");
218  				return;
219  			}
220  			if (!(res instanceof IContainer)) {
221  				updateStatus("File container must exist");
222  				return;
223  			}
224  			if (!res.isAccessible()) {
225  				updateStatus("Project must be writable");
226  				return;
227  			}
228  			containerResource = (IContainer) res;
229  			
230  			fileName = fileText.getText();
231  			if (fileName.length() == 0) {
232  				updateStatus("File name must be specified");
233  				return;
234  			}
235  			if (fileName.replace('\\', '/').indexOf('/', 1) > 0) {
236  				updateStatus("File name cannot contain '/'");
237  				return;
238  			}
239  			int dotLoc = fileName.lastIndexOf('.');
240  			if (dotLoc == -1) {
241  				fileName += ".lisp";
242  			} else {
243  				String ext = fileName.substring(dotLoc + 1);
244  				if (ext.equals("lisp") == false) {
245  					updateStatus("File extension must be \"lisp\" (if present)");
246  					return;
247  				}
248  			}
249  			if (containerResource.findMember(new Path(fileName)) != null) {
250  				updateStatus("File already exists");
251  				return;
252  			}
253  			
Event do_not_call: "java.lang.String.toUpperCase()" implicitly uses the environment's default character set, which might lead to unexpected behavior. Consider using toUpperCase(Locale locale).
254  			if (!creator.pkg.equals(creator.pkg.toUpperCase())) {
255  				updateStatus("ACL2 package names cannot contain lowercase letters");
256  				return;
257  			}
258  			
259  			updateStatus(null);
260  		}
261  	
262  		private void updateStatus(String message) {
263  			setErrorMessage(message);
264  			setPageComplete(message == null);
265  		}
266  	
267  		public String getFileName() {
268  			return fileName;
269  		}
270  		
271  		public IContainer getContainerResource() {
272  			return containerResource;
273  		}
274  		
275  		public String getInitDump() {
276  			return creator.dump();
277  		}
278  	
279  		public boolean createA2s() {
280  			return a2sButton.getSelection();
281  		}
282  		
283  		public void modifyText(ModifyEvent e) {
284  			dialogChanged();
285  		}
286  		
287  		private class SelectionHandler extends SelectionAdapter {
288  			public void widgetSelected(SelectionEvent e) {
289  				dialogChanged();
290  			}
291  		}
292  	}
293  	
294  	
295  	
296  	class NewLispCreator {
297  		BookInfo book = null;
298  		String pkg = null;
299  		SessionMode mode = Acl2sPlugin.getBaseConfig().getDefaultMode();
300  		
301  		String dump() {
302  			StringBuilder b = new StringBuilder();
303  			
304  			if (book != null) {
305  				b.append(LispDocument.PREAMBLE_START);
306  			}		
307  			
308  			dumpMode(b);
309  			
310  			dumpDef(b);
311  			
312  			if (book != null) {
313  				book.dump(b);
314  				b.append(LispDocument.PREAMBLE_END);
315  			}
316  	
317  			dumpIn(b);
318  			
319  			return b.toString();
320  		}
321  		
322  		class BookInfo {
323  			void dump(StringBuilder b) {
324  				b.append('(');
325  				if (!Misc.equal("ACL2", pkg)) {
326  					b.append("acl2::");
327  				}
328  				b.append("begin-book");
329  				if (mode.getTtagsRequired()) {
330  					b.append(" t :ttags :all");
331  				}
332  				b.append(")\n\n");
333  			}
334  		}
335  	
336  		
337  		boolean isStdPkg() {
338  			if (pkg == null || pkg.equals("")) return true;  // assume we're good
339  			
340  			boolean newPkg = true;
341  			for (String p : existingPkgs) {
342  				if (p.equals(pkg)) {
343  					newPkg = false;
344  				}
345  			}
346  			return !newPkg;
347  		}
348  		
349  		void dumpMode(StringBuilder dump) {
350  			if (mode != SessionMode.compatible) {
351  				String[] modeInit = mode.getInitStrings();
352  				if (modeInit != null) {
353  					for (int i = 0; i < modeInit.length; i++) {
354  						dump.append(modeInit[i]);
355  					}
356  				}
357  				dump.append(LispDocument.SMODE_PREFIX);
358  				dump.append(mode.getName());
359  				dump.append('\n');
360  			}
361  		}
362  		
363  		void dumpDef(StringBuilder b) {
364  			if (pkg == null || pkg.equals("")) return;
365  			String unparsed = unparsePkgName();
366  			boolean newPkg = !isStdPkg();
367  			if (newPkg) {
368  				b.append("(defpkg ");
369  				b.append(unparsed);
370  				b.append("\n        (union-eq ");
371  				if (mode.getExtraImportExpr().isNil()) {
372  					b.append("*acl2-exports*");
373  				} else {
374  					b.append("(append " + mode.getExtraImportString() + " *acl2-exports*)");
375  				}
376  				b.append("\n                  ");
377  				b.append("*common-lisp-symbols-from-main-lisp-package*))\n\n");
378  			}
379  		}
380  		
381  		void dumpIn(StringBuilder b) {
382  			if (pkg == null || pkg.equals("")) {
383  				if (book != null) {
384  					b.append("(in-package \"ACL2\")\n\n");
385  				}
386  			} else {
387  				b.append("(in-package ");
388  				b.append(unparsePkgName());
389  				b.append(")\n\n");
390  			}
391  		}
392  		
393  		String unparsePkgName() {
394  			return new Str(pkg).toString();
395  		}
396  		
397  		static final String[] existingPkgs = new String[] { "ACL2", "ACL2-USER" };
398  	}