blob: 24275e2f95b5129ebf6e1c52ae6efb6d141c9250 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 Alphonse Van Assche.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Alphonse Van Assche - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.rpm.ui.editor;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.linuxtools.internal.rpm.ui.editor.preferences.PreferenceConstants;
import org.eclipse.linuxtools.internal.rpm.ui.editor.scanners.SpecfileScanner;
import org.eclipse.linuxtools.rpm.core.utils.Utils;
/**
* This class is used to retrieve and manage the RPM macro proposals list.
*
*/
public class RpmMacroProposalsList {
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private Map<String, String> macroMap = new HashMap<>();
private String toStringStr;
/**
* Default contructor
*/
public RpmMacroProposalsList() {
buildMacroList();
}
/**
* Build the macro list.
*/
public final void buildMacroList() {
for (String definedMacro : SpecfileScanner.DEFINED_MACROS) {
macroMap.put(definedMacro, Messages.RpmMacroProposalsList_0);
// TODO find way to provide info about buildin macros.
}
String macroProposalsPaths = Activator.getDefault().getPreferenceStore()
.getString(PreferenceConstants.P_MACRO_PROPOSALS_FILESPATH);
String[] paths = macroProposalsPaths.split(";"); //$NON-NLS-1$
// paths must be reversed because the last value added
// into a Map overwrites the first.
paths = reverseStringArray(paths);
for (String path : paths) {
if (!path.equals(EMPTY_STRING)) {
File pathFile = new File(path);
if (pathFile.exists()) {
if (pathFile.isDirectory()) {
File[] macrosFiles = pathFile.listFiles();
for (File macrosFile : macrosFiles) {
addMacroToMap(macrosFile.getAbsolutePath());
}
} else {
addMacroToMap(path);
}
}
}
}
}
/**
* Add macro definition to the map
*
* @param filename macro file definition.
*/
private void addMacroToMap(String filename) {
String line = EMPTY_STRING;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)))) {
line = reader.readLine();
String key = EMPTY_STRING, value = EMPTY_STRING;
while (line != null) {
if (line.startsWith("%")) { //$NON-NLS-1$
String[] item = line.split("\t+| ", 2); //$NON-NLS-1$
try {
// Get values on more than one line
if (line.trim().endsWith("\\")) { //$NON-NLS-1$
value = "\n"; //$NON-NLS-1$
boolean isKeyLine = true;
while (line.trim().endsWith("\\")) { //$NON-NLS-1$
if (isKeyLine) {
isKeyLine = false;
key = item[0];
if (item.length > 1) {
value += item[1].replaceAll("\\\\", "\n\n"); //$NON-NLS-1$//$NON-NLS-2$
}
} else {
value += line.substring(0, line.length() - 1).trim() + "\n\t"; //$NON-NLS-1$
}
line = reader.readLine();
}
} else {
key = item[0];
value = item[1];
}
key = key.trim();
value = value.trim();
macroMap.put(key, value);
toStringStr += key + ": " + value + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
} catch (Exception e) {
line = reader.readLine();
continue;
}
value = EMPTY_STRING;
key = EMPTY_STRING;
}
line = reader.readLine();
}
} catch (IOException e) {
SpecfileLog.logError(e);
}
}
/**
* Reverse a <code>String</code> array.
*
* @param stringArrayToReverse the string array to reverse.
* @return the reversed <code>String</code> array.
*/
private String[] reverseStringArray(String[] stringArrayToReverse) {
int left = 0;
int right = stringArrayToReverse.length - 1;
while (left < right) {
String tmp = stringArrayToReverse[left];
stringArrayToReverse[left] = stringArrayToReverse[right];
stringArrayToReverse[right] = tmp;
left++;
right--;
}
return stringArrayToReverse;
}
/**
* Get proposals for a given prefix
*
* @param prefix The prefix to search.
* @return a <code>Map</code> of proposals.
*/
public Map<String, String> getProposals(String prefix) {
Map<String, String> proposalsMap = new HashMap<>(macroMap.size());
for (Map.Entry<String, String> entry : macroMap.entrySet()) {
// Get proposals for macro begin with { char too.
if (entry.getKey().startsWith(prefix.replaceFirst("\\{", EMPTY_STRING))) { //$NON-NLS-1$
proposalsMap.put(entry.getKey(), entry.getValue());
}
}
// Sort proposals
return new TreeMap<>(proposalsMap);
}
/**
* Get the value for a given macro.
*
* @param key Key to retrieve value.
* @return a string representation of the value
*/
public String getValue(String key) {
String value = macroMap.get("%" + key); //$NON-NLS-1$
// get proposals for macro contain ? too.
if (value == null) {
value = macroMap.get(("%" + key).replaceFirst("\\?", EMPTY_STRING)); //$NON-NLS-1$ //$NON-NLS-2$
}
return value;
}
/**
* Find a key in the macroMap
*
* @param keyToFind The key to find.
* @return return the value
*/
public boolean findKey(String keyToFind) {
return macroMap.containsKey(keyToFind);
}
/**
* Return the ouput of the <code>rpm --eval</code> command for a given macro.
*
* @param macroName The macro name to eval.
* @return the resolved macro content.
*/
public static String getMacroEval(String macroName) {
String eval = EMPTY_STRING;
try {
eval = Utils.runCommandToString("rpm", "--eval", macroName); //$NON-NLS-1$//$NON-NLS-2$
} catch (IOException e) {
SpecfileLog.logError(e);
}
return eval.trim();
}
@Override
public String toString() {
return toStringStr;
}
}