Some patches for the eclipse specfile editor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

Last weeks I have make some changes on org.eclipse.cdt.rpm.editor
eclipse plugin, these changes work like a charm here and I found them
really useful.
 
I would really like to work more on this plugin, but before that I
prefer to contact the devs to know if help is welcome and which type of
functionality should be implement in first time.

Modifications are separate into 3 patches (macro-hover,
sections-folding, completion-support)

1. macro-hover patch:
---------------------
When the cursor is placed hover a macro the content of the macro is
showed into the tooltip text.

At the moment content is searched in these two hardcoded files,
/usr/lib/rpm/macros and ~/.rpmmacros.
We can replace these hardcoded string with properties in a preference
page contain a sortable list of rpm-macro-definitions-file-to-include,
that can be useful for example to overwrite system macros definitions by
user macros definitions and vis versa.


2. folding-section patch:
-------------------------
Add folding on each section (preambule, %pre, %build, %install, %
changelog).

It use the existing .getSections() method to get the folding position,
but as a quick fix the preambule section begin always at the first line.


3. completion support:
----------------------
This patch add completion for macro, rpm package and contextual content
assist templates.

Macro completion use the same code as hover macro to retrieve the macro
proposals, the content of the macro is used as description.

There is specific content assist templates for each section, so %patch
template is usable only in the %build section.

Rpm package completion can be used only in the preambule section, there
is a preference page to build the RPM list file (this file must contain
one package per line).
Informations on the packages are retrieve using "rpm -qi", so
description of the packages is show only if the proposals list is less
than 10 items.



I hope that these patches have chance to be included in upstream, so if
some modifications are require in order to be approved, let me know.

Voilà,
Have fun ;)

-- 
Regards,
Alphonse
### Eclipse Workspace Patch 1.0
#P org.eclipse.cdt.rpm.editor_installed
Index: src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java
===================================================================
RCS file: /cvs/eclipse/rpm/org.eclipse.cdt.rpm.editor/src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java,v
retrieving revision 1.6
diff -u -r1.6 SpecfileConfiguration.java
--- src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java	19 Dec 2006 15:31:33 -0000	1.6
+++ src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java	20 Feb 2007 20:25:20 -0000
@@ -1,11 +1,14 @@
 package org.eclipse.cdt.rpm.editor;
 
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.ITextDoubleClickStrategy;
 import org.eclipse.jface.text.ITextHover;
 import org.eclipse.jface.text.TextAttribute;
 import org.eclipse.jface.text.presentation.IPresentationReconciler;
 import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
 import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
 import org.eclipse.jface.text.rules.Token;
 import org.eclipse.jface.text.source.ISourceViewer;
@@ -89,4 +92,14 @@
 		return reconciler;
 	}
 
+	/*
+	 * @see SourceViewerConfiguration#getReconciler(ISourceViewer)
+	 */
+	public IReconciler getReconciler(ISourceViewer sourceViewer) {
+		SpecfileReconcilingStrategy strategy= new SpecfileReconcilingStrategy(editor);
+		MonoReconciler reconciler= new MonoReconciler(strategy, false);
+		reconciler.setProgressMonitor(new NullProgressMonitor());
+		reconciler.setDelay(500);
+		return reconciler;
+	}
 }
\ No newline at end of file
Index: src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java
===================================================================
RCS file: /cvs/eclipse/rpm/org.eclipse.cdt.rpm.editor/src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java,v
retrieving revision 1.6
diff -u -r1.6 SpecfileEditor.java
--- src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java	4 Dec 2006 15:01:40 -0000	1.6
+++ src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java	20 Feb 2007 20:25:20 -0000
@@ -6,6 +6,11 @@
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.swt.widgets.Composite;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.editors.text.TextEditor;
@@ -17,6 +22,7 @@
 	private SpecfileContentOutlinePage outlinePage;
 	private IEditorInput input;
 	private Specfile specfile;
+	private ProjectionSupport projectionSupport;
 
 	public SpecfileEditor() {
 		super();
@@ -91,10 +97,41 @@
 			}
 			return outlinePage;
 		}
+		if (projectionSupport != null) {
+			Object adapter= projectionSupport.getAdapter(getSourceViewer(), required);
+			if (adapter != null)
+				return adapter;
+		}
 		return super.getAdapter(required);
 	}
+	
 	public Specfile getSpecfile() {
 		return specfile;
 	}
 
+	
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int)
+	 */
+	protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
+		fAnnotationAccess = createAnnotationAccess();
+		fOverviewRuler = createOverviewRuler(getSharedColors());
+		ISourceViewer viewer= new ProjectionViewer(parent, ruler, fOverviewRuler, true, styles);
+		getSourceViewerDecorationSupport(viewer);
+		return viewer;
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createPartControl(Composite parent) {
+		super.createPartControl(parent);
+		ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
+		projectionSupport = new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
+		projectionSupport.install();
+		projectionViewer.doOperation(ProjectionViewer.TOGGLE);
+	}
+	
+	
+
 }
Index: src/org/eclipse/cdt/rpm/editor/SpecfileFoldingStructureProvider.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/SpecfileFoldingStructureProvider.java
diff -N src/org/eclipse/cdt/rpm/editor/SpecfileFoldingStructureProvider.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/SpecfileFoldingStructureProvider.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,115 @@
+package org.eclipse.cdt.rpm.editor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.rpm.editor.parser.Specfile;
+import org.eclipse.cdt.rpm.editor.parser.SpecfileElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+
+public class SpecfileFoldingStructureProvider {
+
+	private static final Annotation[] EMPTY = new Annotation[] {};
+	private SpecfileEditor sEditor;
+	private IDocument sDocument;
+	private IProgressMonitor sProgressMonitor;
+
+	public SpecfileFoldingStructureProvider(SpecfileEditor editor) {
+		sEditor = editor;
+	}
+
+	public void setProgressMonitor(IProgressMonitor progressMonitor) {
+		sProgressMonitor = progressMonitor;
+	}
+
+	public void setDocument(IDocument document) {
+		sDocument = document;
+	}
+
+	public void updateFoldingRegions(Specfile specfile) {
+		try {
+
+			ProjectionAnnotationModel model = (ProjectionAnnotationModel) sEditor
+					.getAdapter(ProjectionAnnotationModel.class);
+			if (model != null)
+				updateFoldingRegions(specfile, model);
+		} catch (BadLocationException e) {
+			e.printStackTrace();
+		}
+	}
+
+	void updateFoldingRegions(Specfile specfile, ProjectionAnnotationModel model)
+			throws BadLocationException {
+		Set/* <Position> */structure = createFoldingStructure(specfile);
+		Annotation[] deletions = computeDifferences(model, structure);
+		Map/* <Annotation,Position> */additions = computeAdditions(structure);
+		if ((deletions.length != 0 || additions.size() != 0)
+				&& (sProgressMonitor == null || !sProgressMonitor.isCanceled()))
+			model.modifyAnnotations(deletions, additions, EMPTY);
+	}
+
+	private Map computeAdditions(Set currentRegions) {
+		Map additionsMap = new HashMap();
+		for (Iterator iter = currentRegions.iterator(); iter.hasNext();)
+			additionsMap.put(new ProjectionAnnotation(), iter.next());
+		return additionsMap;
+	}
+
+	private Annotation[] computeDifferences(ProjectionAnnotationModel model,
+			Set current) {
+		List deletions = new ArrayList();
+		for (Iterator iter = model.getAnnotationIterator(); iter.hasNext();) {
+			Object annotation = iter.next();
+			if (annotation instanceof ProjectionAnnotation) {
+				Position position = model.getPosition((Annotation) annotation);
+				if (current.contains(position))
+					current.remove(position);
+				else
+					deletions.add(annotation);
+			}
+		}
+		return (Annotation[]) deletions
+				.toArray(new Annotation[deletions.size()]);
+	}
+
+	private Set createFoldingStructure(Specfile specfile)
+			throws BadLocationException {
+		Set set = new HashSet();
+		System.out.println("name: " + specfile.getName() + " lenght: " + specfile.getSections().length);
+		addFoldingRegions(set, ((Object[]) specfile.getSections()));
+		return set;
+	}
+
+	private void addFoldingRegions(Set regions, Object[] elements)
+			throws BadLocationException {
+		// add preambule folding section.
+		SpecfileElement element = (SpecfileElement) elements[0];
+		Position position = new Position(0, element.getLineStartPosition() - 1);
+		regions.add(position);
+		// add sections folding.
+		for (int i = 0; i < elements.length; i++) {
+			SpecfileElement startElement = (SpecfileElement) elements[i];
+			int offsetPos = startElement.getLineStartPosition();
+			int lenghtPos;
+			if (i < elements.length -1) {
+				SpecfileElement endElement = (SpecfileElement) elements[i+1];
+				lenghtPos = endElement.getLineStartPosition() - startElement.getLineStartPosition() - 1;
+			} else {
+				lenghtPos = sDocument.getLength() - startElement.getLineStartPosition();
+			}
+			position = new Position(offsetPos, lenghtPos);
+			regions.add(position);
+		}
+	}
+}
Index: src/org/eclipse/cdt/rpm/editor/SpecfileReconcilingStrategy.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/SpecfileReconcilingStrategy.java
diff -N src/org/eclipse/cdt/rpm/editor/SpecfileReconcilingStrategy.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/SpecfileReconcilingStrategy.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,65 @@
+package org.eclipse.cdt.rpm.editor;
+
+import org.eclipse.cdt.rpm.editor.parser.Specfile;
+import org.eclipse.cdt.rpm.editor.parser.SpecfileParser;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+
+public class SpecfileReconcilingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
+
+	private IDocument sDocument;
+	private IProgressMonitor sProgressMonitor;
+	private SpecfileParser sParser;
+	private SpecfileFoldingStructureProvider sFoldingStructureProvider;
+
+	public SpecfileReconcilingStrategy(SpecfileEditor editor) {
+		sParser= new SpecfileParser();
+		sFoldingStructureProvider= new SpecfileFoldingStructureProvider(editor);
+	}
+
+	public void setDocument(IDocument document) {
+		sDocument= document;
+		sFoldingStructureProvider.setDocument(sDocument);
+	}
+
+	public void setProgressMonitor(IProgressMonitor monitor) {
+		sProgressMonitor= monitor;
+		sFoldingStructureProvider.setProgressMonitor(sProgressMonitor);
+	}
+
+	public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+		reconcile();
+	}
+
+	public void reconcile(IRegion partition) {
+		reconcile();
+	}
+
+	public void initialReconcile() {
+		reconcile();
+	}
+
+	private void reconcile() {
+		Specfile recipe= parseRecipe();
+		if (recipe != null) {
+			updateEditor(recipe);
+			updateFolding(recipe);
+		}
+	}
+
+	private Specfile parseRecipe() {
+		return sParser.parse(sDocument);
+	}
+
+	private void updateEditor(final Specfile specfile) {
+		return;
+	}
+
+	private void updateFolding(Specfile specfile) {
+		sFoldingStructureProvider.updateFoldingRegions(specfile);
+	}
+}
### Eclipse Workspace Patch 1.0
#P org.eclipse.cdt.rpm.editor_installed
Index: src/org/eclipse/cdt/rpm/editor/SpecfileHover.java
===================================================================
RCS file: /cvs/eclipse/rpm/org.eclipse.cdt.rpm.editor/src/org/eclipse/cdt/rpm/editor/SpecfileHover.java,v
retrieving revision 1.3
diff -u -r1.3 SpecfileHover.java
--- src/org/eclipse/cdt/rpm/editor/SpecfileHover.java	19 Dec 2006 15:31:33 -0000	1.3
+++ src/org/eclipse/cdt/rpm/editor/SpecfileHover.java	19 Feb 2007 19:48:06 -0000
@@ -24,10 +24,8 @@
 
 public class SpecfileHover implements ITextHover, ITextHoverExtension {
 
-
-
 	private SpecfileEditor editor;
-
+	private RpmMacroList macroList = new RpmMacroList();
 
 	public SpecfileHover(SpecfileEditor editor) {
 		this.editor = editor;
@@ -92,7 +90,12 @@
                     }
 
                 }
-               
+       // If it not correspond to a Patch or Source macro, try to find him 
+       // in the builded macro list.
+       if (! macroList.findKey(macroName)) {
+    	   value += macroList.getValue(macroName);
+           return value;
+       }                 
                 
 		return value;
 	}
Index: src/org/eclipse/cdt/rpm/editor/RpmMacroList.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/RpmMacroList.java
diff -N src/org/eclipse/cdt/rpm/editor/RpmMacroList.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/RpmMacroList.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,116 @@
+package org.eclipse.cdt.rpm.editor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class RpmMacroList {
+
+	/**
+	 * Add the folow String as properties in a preference page, so that we can 
+	 * play with the import order (e.g. system macro can overwrite user macros definition and vis versa)
+	 */
+	private String macrosFile = "/usr/lib/rpm/macros";
+	private String rpmMacrosFile = System.getProperty("user.home") + "/.rpmmacros";
+	
+	private ArrayList list = new ArrayList();
+	private String toStringStr;
+	
+	public RpmMacroList() {
+		buildMacroList();
+	}
+	
+	private void setMacrosList(String filename){
+		String line = "";
+		try {
+			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+			line = reader.readLine();
+			String key="", value="";
+			while (line != null) {
+				if (line.startsWith("%")) {
+					String[] item = line.split("\t+| ", 2);
+					try {
+						if (line.trim().endsWith("\\")) {
+							//get values for values on more than one line and try to make it look decently
+							value = "\n";
+							boolean isKeyLine  = true;
+							while (line.trim().endsWith("\\")) {
+								if (isKeyLine) {
+									isKeyLine = false;
+									key = item[0];
+									if (item.length > 1)
+										value += item[1].replace("\\", "\n\n");
+								} else {
+									value += line.substring(0, line.length() -1).trim() + "\n\t";
+								}
+								line = reader.readLine();
+							}
+						} else {
+							key = item[0]; 
+							value = item[1];							
+						}
+						item[0] = key.trim();
+						item[1] = value.trim();
+						list.add(item);
+						toStringStr += item[0] + ": " + item[1] + "\n";
+					} catch (Exception e) {
+						line = reader.readLine();
+						continue;
+					}
+					value = ""; key = "";
+				}
+				line = reader.readLine();
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public void buildMacroList() {
+		toStringStr = "";
+		/**
+		 * TODO: manage the list of rpm macros config file with a prefrence page.
+		 * 
+		 */
+		setMacrosList(rpmMacrosFile);
+		setMacrosList(macrosFile);
+	}
+	
+	public boolean findKey(String keyToFind) {
+		Iterator iterator = list.iterator();
+		String[] item;
+		while (iterator.hasNext()) {
+			item = (String[]) iterator.next();
+			if (item[0].equals(keyToFind)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	public String getValue(String key) {
+		Iterator iterator = list.iterator();
+		String[] item;
+		while (iterator.hasNext()) {
+			item = (String[]) iterator.next();
+			// to find key that begin with ? | %
+			if (item[0].endsWith(key) || item[0].endsWith(key.substring(1, key.length()))) {
+				return item[1];
+			}
+		}
+		return "";
+	}
+
+	public String toString() {
+		return toStringStr;
+	}
+	
+	public static void main(String[] args) {
+		RpmMacroList list = new RpmMacroList();
+		System.out.println(list.getValue("%_datadir"));
+	}
+	
+}
### Eclipse Workspace Patch 1.0
#P org.eclipse.cdt.rpm.editor
Index: plugin.xml
===================================================================
RCS file: /opt/src/cvs_tmp/org.eclipse.cdt.rpm.editor_installed/plugin.xml,v
retrieving revision 1.1
diff -u -r1.1 plugin.xml
--- plugin.xml	20 Feb 2007 20:48:59 -0000	1.1
+++ plugin.xml	8 Mar 2007 19:22:10 -0000
@@ -56,5 +56,46 @@
                tooltip="Organize patches numerically"/>
       </viewerContribution>
    </extension>
+   <extension
+         point="org.eclipse.ui.editors.templates">
+      <contextType
+            class="org.eclipse.jface.text.templates.TemplateContextType"
+            name="preSection"
+            id="org.eclipse.cdt.rpm.editor.preSection"/>
+      <contextType
+            class="org.eclipse.jface.text.templates.TemplateContextType"
+            name="buildSection"
+            id="org.eclipse.cdt.rpm.editor.buildSection"/>
+      <contextType
+            class="org.eclipse.jface.text.templates.TemplateContextType"
+            name="preambleSection"
+            id="org.eclipse.cdt.rpm.editor.preambleSection"/>
+      <include file="templates/templates.xml"/>
+      <contextType
+            class="org.eclipse.jface.text.templates.TemplateContextType"
+            id="org.eclipse.cdt.rpm.editor.installSection"
+            name="fileSection"/>
+      <contextType
+            class="org.eclipse.jface.text.templates.TemplateContextType"
+            id="org.eclipse.cdt.rpm.editor.changelogSection"
+            name="changelogSection"/>
+      <include file="templates/templates.xml"/>
+   </extension>
+   <extension
+         point="org.eclipse.ui.preferencePages">
+      <page
+            class="org.eclipse.cdt.rpm.editor.preferences.MainPreferencePage"
+            id="org.eclipse.cdt.rpm.editor.mainpage"
+            name="RPM Editor"/>
+      <page
+            category="org.eclipse.cdt.rpm.editor.mainpage"
+            class="org.eclipse.cdt.rpm.editor.preferences.RpmProposalsPreferencePage"
+            id="org.eclipse.cdt.rpm.editor.preferences.RpmProposalsPreferencePage"
+            name="RPM Proposal builder"/>
+   </extension>
+   <extension
+         point="org.eclipse.core.runtime.preferences">
+      <initializer class="org.eclipse.cdt.rpm.editor.preferences.PreferenceInitializer"/>
+   </extension>
 
 </plugin>
Index: src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java
===================================================================
RCS file: /opt/src/cvs_tmp/org.eclipse.cdt.rpm.editor_installed/src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java,v
retrieving revision 1.1
diff -u -r1.1 SpecfileConfiguration.java
--- src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java	20 Feb 2007 20:48:56 -0000	1.1
+++ src/org/eclipse/cdt/rpm/editor/SpecfileConfiguration.java	8 Mar 2007 19:22:10 -0000
@@ -1,10 +1,14 @@
 package org.eclipse.cdt.rpm.editor;
 
+import org.eclipse.core.internal.content.ContentType;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.ITextDoubleClickStrategy;
 import org.eclipse.jface.text.ITextHover;
 import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
 import org.eclipse.jface.text.presentation.IPresentationReconciler;
 import org.eclipse.jface.text.presentation.PresentationReconciler;
 import org.eclipse.jface.text.reconciler.IReconciler;
@@ -102,4 +106,22 @@
 		reconciler.setDelay(500);
 		return reconciler;
 	}
+	
+	/*
+	 * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getContentAssistant(org.eclipse.jface.text.source.ISourceViewer)
+	 */
+	public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+		ContentAssistant assistant= new ContentAssistant();
+		IContentAssistProcessor processor= new SpecfileCompletionProcessor(editor);
+		// add content assistance to all the supported contentType
+		assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
+		assistant.setContentAssistProcessor(processor, SpecfilePartitionScanner.SPEC_SCRIPT);
+		assistant.setContentAssistProcessor(processor,SpecfilePartitionScanner.SPEC_FILES);
+		assistant.setContentAssistProcessor(processor,SpecfilePartitionScanner.SPEC_CHANGELOG);		
+		// configure content assistance
+		assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
+		assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
+		assistant.enableAutoInsert(true);
+		return assistant;
+	}
 }
\ No newline at end of file
Index: src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java
===================================================================
RCS file: /opt/src/cvs_tmp/org.eclipse.cdt.rpm.editor_installed/src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java,v
retrieving revision 1.1
diff -u -r1.1 SpecfileEditor.java
--- src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java	20 Feb 2007 20:48:58 -0000	1.1
+++ src/org/eclipse/cdt/rpm/editor/SpecfileEditor.java	8 Mar 2007 19:22:10 -0000
@@ -1,10 +1,14 @@
 package org.eclipse.cdt.rpm.editor;
 
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
 import org.eclipse.cdt.rpm.editor.outline.SpecfileContentOutlinePage;
 import org.eclipse.cdt.rpm.editor.parser.Specfile;
 import org.eclipse.cdt.rpm.editor.parser.SpecfileParser;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.source.ISourceViewer;
 import org.eclipse.jface.text.source.IVerticalRuler;
@@ -14,6 +18,8 @@
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
 
 public class SpecfileEditor extends TextEditor {
@@ -132,6 +138,32 @@
 		projectionViewer.doOperation(ProjectionViewer.TOGGLE);
 	}
 	
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()
+	 */
+	protected void createActions() {
+		super.createActions();
+
+		IAction action= new ContentAssistAction(
+				getResourceBundle(),
+				"ContentAssistProposal.",
+				this);
+		action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+		setAction("ContentAssist", action);
+		markAsStateDependentAction("ContentAssist", true);
+	}
+	
 	
+	// ContentAssistAction take a ResourceBundle but Resource bundles are not yet implemented on  
+	// a plugin level, so we have add this method here as a quick fix.
+	public ResourceBundle getResourceBundle() {
+		ResourceBundle resourceBundle;
+		try {
+			resourceBundle= ResourceBundle.getBundle("org.eclipse.cdt.rpm.editor.SpecfileEditorMessages");
+		} catch (MissingResourceException x) {
+			resourceBundle= null;
+		}
+		return resourceBundle;
+	}
 
 }
Index: src/org/eclipse/cdt/rpm/editor/RpmMacroList.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/RpmMacroList.java
diff -N src/org/eclipse/cdt/rpm/editor/RpmMacroList.java
--- src/org/eclipse/cdt/rpm/editor/RpmMacroList.java	20 Feb 2007 20:48:58 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,116 +0,0 @@
-package org.eclipse.cdt.rpm.editor;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-public class RpmMacroList {
-
-	/**
-	 * Add the folow String as properties in a preference page, so that we can 
-	 * play with the import order (e.g. system macro can overwrite user macros definition and vis versa)
-	 */
-	private String macrosFile = "/usr/lib/rpm/macros";
-	private String rpmMacrosFile = System.getProperty("user.home") + "/.rpmmacros";
-	
-	private ArrayList list = new ArrayList();
-	private String toStringStr;
-	
-	public RpmMacroList() {
-		buildMacroList();
-	}
-	
-	private void setMacrosList(String filename){
-		String line = "";
-		try {
-			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
-			line = reader.readLine();
-			String key="", value="";
-			while (line != null) {
-				if (line.startsWith("%")) {
-					String[] item = line.split("\t+| ", 2);
-					try {
-						if (line.trim().endsWith("\\")) {
-							//get values for values on more than one line and try to make it look decently
-							value = "\n";
-							boolean isKeyLine  = true;
-							while (line.trim().endsWith("\\")) {
-								if (isKeyLine) {
-									isKeyLine = false;
-									key = item[0];
-									if (item.length > 1)
-										value += item[1].replace("\\", "\n\n");
-								} else {
-									value += line.substring(0, line.length() -1).trim() + "\n\t";
-								}
-								line = reader.readLine();
-							}
-						} else {
-							key = item[0]; 
-							value = item[1];							
-						}
-						item[0] = key.trim();
-						item[1] = value.trim();
-						list.add(item);
-						toStringStr += item[0] + ": " + item[1] + "\n";
-					} catch (Exception e) {
-						line = reader.readLine();
-						continue;
-					}
-					value = ""; key = "";
-				}
-				line = reader.readLine();
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	public void buildMacroList() {
-		toStringStr = "";
-		/**
-		 * TODO: manage the list of rpm macros config file with a prefrence page.
-		 * 
-		 */
-		setMacrosList(rpmMacrosFile);
-		setMacrosList(macrosFile);
-	}
-	
-	public boolean findKey(String keyToFind) {
-		Iterator iterator = list.iterator();
-		String[] item;
-		while (iterator.hasNext()) {
-			item = (String[]) iterator.next();
-			if (item[0].equals(keyToFind)) {
-				return true;
-			}
-		}
-		return false;
-	}
-	
-	public String getValue(String key) {
-		Iterator iterator = list.iterator();
-		String[] item;
-		while (iterator.hasNext()) {
-			item = (String[]) iterator.next();
-			// to find key that begin with ? | %
-			if (item[0].endsWith(key) || item[0].endsWith(key.substring(1, key.length()))) {
-				return item[1];
-			}
-		}
-		return "";
-	}
-
-	public String toString() {
-		return toStringStr;
-	}
-	
-	public static void main(String[] args) {
-		RpmMacroList list = new RpmMacroList();
-		System.out.println(list.getValue("%_datadir"));
-	}
-	
-}
Index: src/org/eclipse/cdt/rpm/editor/Activator.java
===================================================================
RCS file: /opt/src/cvs_tmp/org.eclipse.cdt.rpm.editor_installed/src/org/eclipse/cdt/rpm/editor/Activator.java,v
retrieving revision 1.1
diff -u -r1.1 Activator.java
--- src/org/eclipse/cdt/rpm/editor/Activator.java	20 Feb 2007 20:48:58 -0000	1.1
+++ src/org/eclipse/cdt/rpm/editor/Activator.java	8 Mar 2007 19:22:10 -0000
@@ -1,6 +1,12 @@
 package org.eclipse.cdt.rpm.editor;
 
+import java.io.IOException;
+
 import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.BundleContext;
 
@@ -15,6 +21,15 @@
 	// The shared instance
 	private static Activator plugin;
 	
+	private ContributionTemplateStore fTemplateStore;
+	private ContributionContextTypeRegistry fContextTypeRegistry;
+	
+	// RPM macros list
+	private RpmMacroProposalsList macrosList ;
+	
+	// RPM package list
+	private RpmPackageProposalsList packagesList ;
+	
 	/**
 	 * The constructor
 	 */
@@ -58,4 +73,45 @@
 	public static ImageDescriptor getImageDescriptor(String path) {
 		return imageDescriptorFromPlugin(PLUGIN_ID, path);
 	}
+	
+	public TemplateStore getTemplateStore() {
+		if (fTemplateStore == null) {
+			fTemplateStore= new ContributionTemplateStore(getContextTypeRegistry(), getPreferenceStore(), "templates");
+			try {
+				fTemplateStore.load();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+
+		return fTemplateStore;
+	}
+
+	public RpmMacroProposalsList getRpmMacroList() {
+		if (macrosList == null) {
+			macrosList = new RpmMacroProposalsList();
+		}
+		return macrosList;
+	}
+	
+	public RpmPackageProposalsList getRpmPackageList() {
+		if (packagesList == null) {
+			packagesList = new RpmPackageProposalsList();
+		}
+		return packagesList;
+	}
+	
+
+	public ContextTypeRegistry getContextTypeRegistry() {
+		if (fContextTypeRegistry == null) {
+			fContextTypeRegistry= new ContributionContextTypeRegistry();
+			fContextTypeRegistry.addContextType("org.eclipse.cdt.rpm.editor.preambleSection");
+			fContextTypeRegistry.addContextType("org.eclipse.cdt.rpm.editor.preSection");
+			fContextTypeRegistry.addContextType("org.eclipse.cdt.rpm.editor.buildSection");
+			fContextTypeRegistry.addContextType("org.eclipse.cdt.rpm.editor.installSection");
+			fContextTypeRegistry.addContextType("org.eclipse.cdt.rpm.editor.changelogSection");			
+		}
+		return fContextTypeRegistry;
+	}
+	
 }
Index: src/org/eclipse/cdt/rpm/editor/RpmMacroProposalsList.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/RpmMacroProposalsList.java
diff -N src/org/eclipse/cdt/rpm/editor/RpmMacroProposalsList.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/RpmMacroProposalsList.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,133 @@
+package org.eclipse.cdt.rpm.editor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class RpmMacroProposalsList {
+
+	/*
+	 * Add the folow String as properties in a preference page, so that we can 
+	 * play with the import order (e.g. system macro can overwrite user macros definition and vis versa)
+	 */
+	private String macrosFile = "/usr/lib/rpm/macros";
+	private String rpmMacrosFile = System.getProperty("user.home") + "/.rpmmacros";
+	
+	private ArrayList list = new ArrayList();
+	private String toStringStr;
+	
+	public RpmMacroProposalsList() {
+		buildMacroList();
+	}
+	
+	private void setMacrosList(String filename){
+		String line = "";
+		try {
+			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+			line = reader.readLine();
+			String key="", value="";
+			while (line != null) {
+				if (line.startsWith("%")) {
+					String[] item = line.split("\t+| ", 2);
+					try {
+						/*
+						 * Get values on more than one line
+						 */
+						if (line.trim().endsWith("\\")) {
+							value = "\n";
+							boolean isKeyLine  = true;
+							while (line.trim().endsWith("\\")) {
+								if (isKeyLine) {
+									isKeyLine = false;
+									key = item[0];
+									if (item.length > 1)
+										value += item[1].replace("\\", "\n\n");
+								} else {
+									value += line.substring(0, line.length() -1).trim() + "\n\t";
+								}
+								line = reader.readLine();
+							}
+						} else {
+							key = item[0]; 
+							value = item[1];							
+						}
+						item[0] = key.trim();
+						item[1] = value.trim();
+						list.add(item);
+						toStringStr += item[0] + ": " + item[1] + "\n";
+					} catch (Exception e) {
+						line = reader.readLine();
+						continue;
+					}
+					value = ""; key = "";
+				}
+				line = reader.readLine();
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public List getMacroList() {
+		return list;
+	}
+	
+	public void buildMacroList() {
+		toStringStr = "";
+		/**
+		 * TODO: manage the list of RPM macros config file with a prefrence page.
+		 * 
+		 */
+		setMacrosList(rpmMacrosFile);
+		setMacrosList(macrosFile);
+	}
+	
+	public boolean findKey(String keyToFind) {
+		Iterator iterator = list.iterator();
+		String[] item;
+		while (iterator.hasNext()) {
+			item = (String[]) iterator.next();
+			if (item[0].equals(keyToFind)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	public List getProposals(String prefix) {
+		Iterator iterator = list.iterator();
+		List retList = new ArrayList(list.size());
+		String[] item;
+		int i = 0;
+		while (iterator.hasNext()) {
+			item = (String[]) iterator.next();
+			if (item[0].startsWith(prefix)) {
+				retList.add(item);
+			}
+			i++;
+		}
+		return retList;
+	}
+	
+	public String getValue(String key) {
+		Iterator iterator = list.iterator();
+		String[] item;
+		while (iterator.hasNext()) {
+			item = (String[]) iterator.next();
+			// to find key that begin with ? | % too
+			if (item[0].endsWith(key) || item[0].endsWith(key.substring(1, key.length()))) {
+				return item[1];
+			}
+		}
+		return "";
+	}
+
+	public String toString() {
+		return toStringStr;
+	}
+
+}
Index: src/org/eclipse/cdt/rpm/editor/RpmPackageProposalsList.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/RpmPackageProposalsList.java
diff -N src/org/eclipse/cdt/rpm/editor/RpmPackageProposalsList.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/RpmPackageProposalsList.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,88 @@
+package org.eclipse.cdt.rpm.editor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.cdt.rpm.editor.preferences.PreferenceConstants;
+
+
+public class RpmPackageProposalsList {
+	private String rpmpkgsFile = Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.P_RPM_LIST_FILEPATH);
+
+	private ArrayList list = new ArrayList();
+
+	public RpmPackageProposalsList() {
+		setPackagesList();
+	}
+
+	private void setPackagesList(){
+		try {
+			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(rpmpkgsFile)));
+			String line = reader.readLine();
+			while (line != null) {
+				list.add(line.trim());
+				line = reader.readLine();
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public List getProposals(String prefix) {
+		Iterator iterator = list.iterator();
+		List proposalsList = new ArrayList(list.size());
+		int i = 0;
+		while (iterator.hasNext()) {
+			String item[] = new String[2];
+			item[0] = (String) iterator.next();
+			item[1] = "Rpm information are only avalable \nif the proposal list is less than 10 item";
+			if (item[0].startsWith(prefix)) {
+				proposalsList.add(item);
+			}
+			i++;
+		}
+		/*
+		 * Show RPM informations only if the proposal list is less than 10
+		 * TODO: We can add a preference page to give on the user the possibility to modify
+		 *       these limit.
+		 */
+		if (proposalsList.size() < 20) {
+			iterator = proposalsList.iterator();
+			List proposalsListWithInfo = new ArrayList(proposalsList.size());
+			while (iterator.hasNext()) {
+				String item[] = new String[2];
+				item = (String[]) iterator.next();
+				item[1] = getRpmInfo(item[0]);
+				proposalsListWithInfo.add(item);
+			}
+			return proposalsListWithInfo;
+		} else {
+			return proposalsList;
+		}
+	}
+
+	public String getRpmInfo(String pkgName) {
+		String ret = "";
+		String[] cmd = new String[] {"rpm","-qi", pkgName};
+		try {
+			Process child = Runtime.getRuntime().exec(cmd);
+			InputStream in = child.getInputStream();
+	        int c;
+	        while ((c = in.read()) != -1) {
+	            ret += ((char)c);
+	        }
+	        in.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return ret;
+	}
+	
+
+}
Index: src/org/eclipse/cdt/rpm/editor/preferences/RpmProposalsPreferencePage.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/preferences/RpmProposalsPreferencePage.java
diff -N src/org/eclipse/cdt/rpm/editor/preferences/RpmProposalsPreferencePage.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/preferences/RpmProposalsPreferencePage.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,103 @@
+package org.eclipse.cdt.rpm.editor.preferences;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.cdt.rpm.editor.Activator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By 
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to 
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class RpmProposalsPreferencePage
+	extends FieldEditorPreferencePage
+	implements IWorkbenchPreferencePage {
+
+	public RpmProposalsPreferencePage() {
+		super(GRID);
+		setPreferenceStore(Activator.getDefault().getPreferenceStore());
+	}
+	
+	/**
+	 * Creates the field editors. Field editors are abstractions of
+	 * the common GUI blocks needed to manipulate various types
+	 * of preferences. Each field editor knows how to save and
+	 * restore itself.
+	 */
+	public void createFieldEditors() {
+		addField(
+			new StringFieldEditor(PreferenceConstants.P_RPM_LIST_CMD, "RPM proposals list command:", getFieldEditorParent()));
+		addField(new StringFieldEditor(PreferenceConstants.P_RPM_LIST_FILEPATH, "RPM proposals list full path:", getFieldEditorParent()));
+
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+	 */
+	public void init(IWorkbench workbench) {
+		
+	}
+	
+    public boolean performOk() {
+        boolean b = super.performOk();
+        
+        IRunnableWithProgress runnable = new IRunnableWithProgress() {
+        	public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+				String rpmListCmd = getPreferenceStore().getString(PreferenceConstants.P_RPM_LIST_CMD);
+				String rpmListFilepath =  getPreferenceStore().getString(PreferenceConstants.P_RPM_LIST_FILEPATH);
+				try {
+					String[] cmd = new String[] {"/bin/sh","-c", rpmListCmd};
+					monitor.beginTask("Get RPM proposals list...", 100);
+					monitor.worked(10);
+					Process child = Runtime.getRuntime().exec(cmd);
+					InputStream in = child.getInputStream();
+					OutputStream out = new FileOutputStream(rpmListFilepath);
+					monitor.setTaskName("Write RPM proposals list into " + rpmListFilepath + " file...");
+					monitor.worked(15);
+					byte[] buf = new byte[1024];
+					int len;
+					int nbrOfByte = 1;
+					while ((len = in.read(buf)) > 0) {
+						out.write(buf, 0, len);
+						monitor.worked(nbrOfByte);
+						nbrOfByte++;
+					}
+					in.close();
+					out.close();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+        };
+        
+        try {
+	 		ProgressMonitorDialog progressMonitor = new ProgressMonitorDialog(getShell());
+	 		progressMonitor.run(true, false, runnable);
+        } catch(Exception e) {
+	 		e.printStackTrace();
+        }
+        return b;
+    }
+    
+
+}
Index: src/org/eclipse/cdt/rpm/editor/SpecfileCompletionProcessor.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/SpecfileCompletionProcessor.java
diff -N src/org/eclipse/cdt/rpm/editor/SpecfileCompletionProcessor.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/SpecfileCompletionProcessor.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,296 @@
+package org.eclipse.cdt.rpm.editor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.cdt.rpm.editor.parser.Specfile;
+import org.eclipse.cdt.rpm.editor.parser.SpecfileElement;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+public class SpecfileCompletionProcessor implements IContentAssistProcessor {
+
+	private static final String TEMPLATE_ICON = "icons/template.gif";
+
+	private static final String MACRO_ICON = "icons/rpmmacro.gif";
+	
+	private static final String PACKAGE_ICON = "icons/rpm.gif";
+
+	private static final String PREAMBLE_SECTION_TEMPLATE = "org.eclipse.cdt.rpm.editor.preambleSection";
+
+	private static final String PRE_SECTION_TEMPLATE = "org.eclipse.cdt.rpm.editor.preSection";
+
+	private static final String BUILD_SECTION_TEMPLATE = "org.eclipse.cdt.rpm.editor.buildSection";
+
+	private static final String INSTALL_SECTION_TEMPLATE = "org.eclipse.cdt.rpm.editor.installSection";
+
+	private static final String CHANGELOG_SECTION_TEMPLATE = "org.eclipse.cdt.rpm.editor.changelogSection";
+
+	private static final class ProposalComparator implements Comparator {
+		public int compare(Object o1, Object o2) {
+			return ((TemplateProposal) o2).getRelevance()
+					- ((TemplateProposal) o1).getRelevance();
+		}
+	}
+
+	private static final Comparator proposalComparator = new ProposalComparator();
+	private final SpecfileEditor sEditor;
+
+	/**
+	 * Default constructor
+	 */
+	public SpecfileCompletionProcessor(SpecfileEditor editor) {
+		sEditor = editor;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer,
+	 *      int)
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
+			int offset) {
+		List result = new ArrayList();
+		Specfile specfile = sEditor.getSpecfile();
+		if (specfile == null)
+			return null;
+		ITextSelection selection = (ITextSelection) viewer
+				.getSelectionProvider().getSelection();
+		// adjust offset to start of normalized selection:
+		if (selection.getOffset() != offset)
+			offset = selection.getOffset();
+		String prefix = getPrefix(viewer, offset);
+		Region region = new Region(offset - prefix.length(), prefix.length()
+				+ selection.getLength());
+		ICompletionProposal[] templateProposals = computeTemplateProposals(
+				viewer, region, specfile, prefix);
+		ICompletionProposal[] rpmMacroProposals = computeRpmMacroProposals(
+				viewer, region, prefix);
+		ICompletionProposal[] rpmPackageProposals = computeRpmPackageProposals(
+				viewer, region, specfile, prefix);		
+		result.addAll(Arrays.asList(templateProposals));
+		result.addAll(Arrays.asList(rpmMacroProposals));
+		result.addAll(Arrays.asList(rpmPackageProposals));
+		return (ICompletionProposal[]) result
+				.toArray(new ICompletionProposal[result.size()]);
+	}
+	
+	private ICompletionProposal[] computeTemplateProposals(ITextViewer viewer,
+			IRegion region, Specfile specfile, String prefix) {
+		TemplateContext context = createContext(viewer, region, specfile);
+		if (context == null) {
+			return new ICompletionProposal[0];
+		}
+		ITextSelection selection = (ITextSelection) viewer
+				.getSelectionProvider().getSelection();
+		context.setVariable("selection", selection.getText());
+		String id = context.getContextType().getId();
+		Template[] templates = Activator.getDefault().getTemplateStore()
+				.getTemplates(id);
+		List matches = new ArrayList();
+		for (int i = 0; i < templates.length; i++) {
+			Template template = templates[i];
+			try {
+				context.getContextType().validate(template.getPattern());
+			} catch (TemplateException e) {
+				continue;
+			}
+			int relevance = getRelevance(template, prefix);
+			if (relevance > 0) {
+				matches.add(new TemplateProposal(template, context, region,
+						getImage(TEMPLATE_ICON), relevance));
+			}
+		}
+		Collections.sort(matches, proposalComparator);
+		return (ICompletionProposal[]) matches
+				.toArray(new ICompletionProposal[matches.size()]);
+	}
+
+	/**
+	 * Compute RPM macro proposals, these proposals are usable in the whole document.
+	 * Return an array of RPM macro proposals for the given viewer, region, prefix.
+	 * 
+	 * @param viewer
+	 *            the viewer for which the context is created
+	 * @param region
+	 *            the region into <code>document</code> for which the context
+	 *            is created
+	 * @param prefix
+	 * 			  the prefix string to find
+	 * @return 
+	 *            a ICompletionProposal[]
+	 */
+	private ICompletionProposal[] computeRpmMacroProposals(ITextViewer viewer,
+			IRegion region, String prefix) {
+		List rpmMacroProposalsList = Activator.getDefault().getRpmMacroList().getProposals(prefix);
+		if (rpmMacroProposalsList == null)
+			return new ICompletionProposal[0];
+		ArrayList proposals = new ArrayList();
+		String[] item;
+		Iterator iterator = rpmMacroProposalsList.iterator();
+		while (iterator.hasNext()) {
+			item = (String[]) iterator.next();
+			proposals.add(new CompletionProposal("%{" + item[0].substring(1) + "}", 
+							region.getOffset(), region.getLength(),
+							item[0].length() + 2, getImage(MACRO_ICON),
+							item[0], null, item[1]));
+		}
+		return (ICompletionProposal[]) proposals
+				.toArray(new ICompletionProposal[proposals.size()]);
+	}
+
+	/**
+	 * Compute RPM package proposals, these proposals are usable only in the preambule section.
+	 * Return an array of RPM macro proposals for the given viewer, region, specfile, prefix.
+	 * 
+	 * @param viewer
+	 *            the viewer for which the context is created
+	 * @param region
+	 *            the region into <code>document</code> for which the context
+	 *            is created
+	 * @param specfile
+	 * 			  the specfile element
+	 * @param prefix
+	 * 			  the prefix string
+	 * @return 
+	 *            a ICompletionProposal[]
+	 */
+	private ICompletionProposal[] computeRpmPackageProposals(ITextViewer viewer,
+			IRegion region, Specfile specfile, String prefix) {
+		List rpmPkgProposalsList = Activator.getDefault().getRpmPackageList().getProposals(prefix);
+		SpecfileElement[] elements = specfile.getSectionsElements();
+		// Show rpm packages proposals only in the preambule section 
+		if (region.getOffset() < elements[0].getLineEndPosition()) {
+			if (rpmPkgProposalsList == null)
+				return new ICompletionProposal[0];
+			ArrayList proposals = new ArrayList();
+			String[] item;
+			Iterator iterator = rpmPkgProposalsList.iterator();
+			while (iterator.hasNext()) {
+				item = (String[]) iterator.next();
+				proposals.add(new CompletionProposal(item[0], 
+								region.getOffset(), region.getLength(),
+								item[0].length(), getImage(PACKAGE_ICON),
+								item[0], null, item[1]));
+			}
+			return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+		} else {
+			return new ICompletionProposal[0];	
+		}
+	}
+
+	private TemplateContextType getContextType(Specfile specfile, int offset) {
+		SpecfileElement[] elements = specfile.getSectionsElements();
+		if (offset < elements[0].getLineEndPosition()) {
+			return Activator.getDefault().getContextTypeRegistry()
+					.getContextType(PREAMBLE_SECTION_TEMPLATE);
+		} else if (offset < elements[1].getLineEndPosition()) {
+			return Activator.getDefault().getContextTypeRegistry()
+					.getContextType(PRE_SECTION_TEMPLATE);
+		} else if (offset < elements[2].getLineEndPosition()) {
+			return Activator.getDefault().getContextTypeRegistry()
+					.getContextType(BUILD_SECTION_TEMPLATE);
+		} else if (offset < elements[3].getLineEndPosition()) {
+			return Activator.getDefault().getContextTypeRegistry()
+					.getContextType(INSTALL_SECTION_TEMPLATE);
+		} else {
+			return Activator.getDefault().getContextTypeRegistry()
+					.getContextType(CHANGELOG_SECTION_TEMPLATE);
+		}
+
+	}
+
+	private TemplateContext createContext(ITextViewer viewer, IRegion region,
+			Specfile specfile) {
+		TemplateContextType contextType = getContextType(specfile, region
+				.getOffset());
+		if (contextType != null) {
+			IDocument document = viewer.getDocument();
+			return new DocumentTemplateContext(contextType, document, region
+					.getOffset(), region.getLength());
+		}
+		return null;
+	}
+	
+	private int getRelevance(Template template, String prefix) {
+		if (template.getName().startsWith(prefix))
+			return 90;
+		return 0;
+	}
+
+	private String getPrefix(ITextViewer viewer, int offset) {
+		int i = offset;
+		IDocument document = viewer.getDocument();
+		if (i > document.getLength())
+			return "";
+
+		try {
+			while (i > 0) {
+				char ch = document.getChar(i - 1);
+				if (!Character.isLetterOrDigit(ch) && (ch != '%') && (ch != '_')&& (ch != '-'))
+					break;
+				i--;
+			}
+			return document.get(i, offset - i);
+		} catch (BadLocationException e) {
+			return "";
+		}
+	}
+
+	private Image getImage(String imageRelativePath) {
+		ImageRegistry registry = Activator.getDefault().getImageRegistry();
+		Image image = registry.get(imageRelativePath);
+		if (image == null) {
+			ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin(
+					"org.eclipse.cdt.rpm.editor", imageRelativePath);
+			registry.put(imageRelativePath, desc);
+			image = registry.get(imageRelativePath);
+		}
+		return image;
+	}
+
+	public IContextInformation[] computeContextInformation(ITextViewer viewer,
+			int offset) {
+		return null;
+	}
+
+	public char[] getCompletionProposalAutoActivationCharacters() {
+		return null;
+	}
+
+	public char[] getContextInformationAutoActivationCharacters() {
+		return null;
+	}
+
+	public String getErrorMessage() {
+		return null;
+	}
+
+	public IContextInformationValidator getContextInformationValidator() {
+		return null;
+	}
+}
Index: src/org/eclipse/cdt/rpm/editor/preferences/MainPreferencePage.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/preferences/MainPreferencePage.java
diff -N src/org/eclipse/cdt/rpm/editor/preferences/MainPreferencePage.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/preferences/MainPreferencePage.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,52 @@
+package org.eclipse.cdt.rpm.editor.preferences;
+
+import org.eclipse.cdt.rpm.editor.Activator;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By 
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to 
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class MainPreferencePage
+	extends FieldEditorPreferencePage
+	implements IWorkbenchPreferencePage {
+
+	public MainPreferencePage() {
+		super(GRID);
+		setPreferenceStore(Activator.getDefault().getPreferenceStore());
+		setDescription("Main preference page for RPM editor plugin");
+	}
+	
+	/**
+	 * Creates the field editors. Field editors are abstractions of
+	 * the common GUI blocks needed to manipulate various types
+	 * of preferences. Each field editor knows how to save and
+	 * restore itself.
+	 */
+	public void createFieldEditors() {
+
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+	 */
+	public void init(IWorkbench workbench) {
+		
+	}
+	
+	
+
+	
+}
Index: src/org/eclipse/cdt/rpm/editor/preferences/PreferenceConstants.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/preferences/PreferenceConstants.java
diff -N src/org/eclipse/cdt/rpm/editor/preferences/PreferenceConstants.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/preferences/PreferenceConstants.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,10 @@
+package org.eclipse.cdt.rpm.editor.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class PreferenceConstants {
+
+	public static final String P_RPM_LIST_CMD = "rpmListCmd";
+	public static final String P_RPM_LIST_FILEPATH = "rpmListFilePath";	
+}
Index: src/org/eclipse/cdt/rpm/editor/preferences/PreferenceInitializer.java
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/preferences/PreferenceInitializer.java
diff -N src/org/eclipse/cdt/rpm/editor/preferences/PreferenceInitializer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/preferences/PreferenceInitializer.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+package org.eclipse.cdt.rpm.editor.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import org.eclipse.cdt.rpm.editor.Activator;
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+		IPreferenceStore store = Activator.getDefault()
+				.getPreferenceStore();
+		store.setDefault(PreferenceConstants.P_RPM_LIST_CMD,
+				"yum list all | grep - | cut -d \".\" -f 1");
+		store.setDefault(PreferenceConstants.P_RPM_LIST_FILEPATH,
+		System.getProperty("user.dir") +  "/.pkglist");
+	}
+
+}
Index: src/org/eclipse/cdt/rpm/editor/SpecfileEditorMessages.properties
===================================================================
RCS file: src/org/eclipse/cdt/rpm/editor/SpecfileEditorMessages.properties
diff -N src/org/eclipse/cdt/rpm/editor/SpecfileEditorMessages.properties
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/rpm/editor/SpecfileEditorMessages.properties	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,3 @@
+ContentAssistProposal.label=Content Assist
+ContentAssistProposal.tooltip=Content Assist
+ContentAssistProposal.description=Content Assist

Attachment: signature.asc
Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=

--
fedora-devel-java-list mailing list
fedora-devel-java-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/fedora-devel-java-list

[Index of Archives]     [Red Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]

  Powered by Linux