/* * $Id$ * * Copyright (c) 2006 by the TeXlipse team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package net.sourceforge.texlipse.model; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; import net.sourceforge.texlipse.TexlipsePlugin; import net.sourceforge.texlipse.builder.KpsewhichRunner; import net.sourceforge.texlipse.editor.TexDocumentParseException; import net.sourceforge.texlipse.texparser.TexParser; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; /** * A parser interface for finding and parsing files in a LaTeX-project. * * @author Oskar Ojala * @author Boris von Loesch */ public class TexProjectParser { private IProject currentProject; private IFile file; private TexParser parser; private static final String TEX_FILE_ENDING = ".tex"; /** * Creates a new project parser * * @param currentProject The project this parser should belong to * @param labels The label container for this project * @param bibs The BibTeX container for this project */ public TexProjectParser(IProject currentProject) { this.currentProject = currentProject; } /** * Finds the given file from the project and returns it or null * if such a file wasn't found. If the file was found in a path outside * the project, a link to the file is created. * * @param fileName The name of the file to look for * @param referringFile The file referring to this file (used for paths) * @return The found file or null if it wasn't found */ public IFile findIFile(String fileName, IFile referringFile) { return findIFile(fileName, referringFile, currentProject); } /** * Finds the given file from the project and returns it or null * if such a file wasn't found. If the file was found in a path outside * the project, a link to the file is created. * * @param fileName The name of the file to look for * @param referringFile The file referring to this file (used for paths) * @param currentProject * @return The found file or null if it wasn't found */ public static IFile findIFile(String fileName, IFile referringFile, IProject currentProject) { // Append default ending if (fileName.indexOf('.') == -1 || fileName.lastIndexOf('/') > fileName.lastIndexOf('.')) { fileName += TEX_FILE_ENDING; } IPath path = referringFile.getFullPath(); path = path.removeFirstSegments(1).removeLastSegments(1).append(fileName); IFile file = currentProject.getFile(path); if (!file.exists()) { //Try Kpsewhich KpsewhichRunner filesearch = new KpsewhichRunner(); try { String fName = filesearch.getFile(currentProject, fileName, "latex"); if (fName.length() > 0) { //Create a link IPath p = new Path(fName); file.createLink(p, IResource.NONE, null); } } catch (CoreException e) { TexlipsePlugin.log("Can't run Kpathsea", e); } } return file.exists() ? file : null; } /** * Parses the given file * * @param file The file to parse * @return Outline tree * @throws IOException if the file was not readable * @throws TexDocumentParseException if the parsing ended in fatal errors */ public List<OutlineNode> parseFile(IFile file) throws IOException { this.file = file; return this.parseFile(); } /** * Parses a file that has been previously found with * <code>findIFile</code>. Note that if the find was not done or * it completed unsuccessfully, then the behaviour of this method * is undefined. * * @return Outline tree or null if parsing was unsuccessful. * @throws IOException if the file was not readable * @throws TexDocumentParseException if the parsing ended in fatal errors */ private List<OutlineNode> parseFile() throws IOException { String inputContent = readFile(file); parseDocument(inputContent); if (parser.isFatalErrors()) { throw new IOException("Unable to parse document successfully"); } return parser.getOutlineTree(); } /** * Parses the document. Parses the complete project with its inputs recursively. * At the first round the complete project is parsed. Then only the changed * parts will be parsed again and the outlineTree will be generated. * * @param labels the label container. * @param bibs the bib container. */ private void parseDocument(String input) throws IOException { if (this.parser == null) { this.parser = new TexParser(null); } this.parser.parseDocument(input, false); } /** * Reads a file from the project. * * @param file the file to be read. * @return The contents of the file as a String. * @throws IOException */ private String readFile(IFile file) throws IOException { StringBuilder inputContent = new StringBuilder(""); try { BufferedReader buf = new BufferedReader( new InputStreamReader(file.getContents())); final int length = 10000; int read = length; char[] fileData = new char[length]; while (read == length) { read = buf.read(fileData, 0, length); if (read > 0) { inputContent.append(fileData, 0, read); } } buf.close(); } catch (CoreException e) { // This should be very rare... throw new IOException(e.getMessage()); } // TODO //return this.rmTrailingWhitespace(inputContent); return inputContent.toString(); } }