/** * Initializes variables, which are often reused. This should be called every time there is a * chance that project settings have been changed. */ public void init() { sourceDir = TexlipseProperties.getProjectSourceDir(project); outputDir = TexlipseProperties.getProjectOutputDir(project); tempDir = TexlipseProperties.getProjectTempDir(project); format = TexlipseProperties.getProjectProperty(project, TexlipseProperties.OUTPUT_FORMAT); sourceFile = TexlipseProperties.getProjectSourceFile(project); }
/** Creates if not exist the ProjectOutline */ private void createProjectOutline() { IProject project = getCurrentProject(); if (project == null) return; Object projectSessionOutLine = TexlipseProperties.getSessionProperty( project, TexlipseProperties.SESSION_PROJECT_FULLOUTLINE); if (projectSessionOutLine != null) projectOutline = (TexProjectOutline) projectSessionOutLine; else { projectOutline = new TexProjectOutline(getCurrentProject()); TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_PROJECT_FULLOUTLINE, projectOutline); } }
/** * Checks whether all includes exists, if they are outside of the project, add a link to the file * to the project * * @param includes */ private void processIncludes(List<OutlineNode> includes, IEditorInput input) { IProject project = getCurrentProject(); if (project == null) return; IFile referFile = (IFile) input.getAdapter(IFile.class); if (referFile == null) return; for (OutlineNode node : includes) { IFile f = null; IFile mainTexFile = TexlipseProperties.getProjectSourceFile(project); if (mainTexFile != null) { // Includes are always relative to the main file f = TexProjectParser.findIFile(node.getName(), mainTexFile, project); } if (f == null) { // Try finding it relative to refering file f = TexProjectParser.findIFile(node.getName(), referFile, project); } if (f == null) { MarkerHandler marker = MarkerHandler.getInstance(); String errorMsg = MessageFormat.format( TexlipsePlugin.getResourceString("parseErrorIncludeNotFound"), new Object[] {node.getName()}); marker.createErrorMarker(referFile, errorMsg, node.getBeginLine()); } } }
/** * Retrieves an IFile object of the currently selected output file, no matter if the file actually * exists. This method is used to respect partial builds. * * @return current output file, or null if not selected */ private IFile getSelectedOutputFile() { String fileName = TexlipseProperties.getOutputFileName(project); if (fileName != null) { if (outputDir == null) { return project.getFile(fileName); } else { return outputDir.getFile(fileName); } } else { return null; } }
/** * Updates the references and project data based on the data in the parsed document. * * @param monitor Progress monitor */ private void updateReferences(IProgressMonitor monitor) { this.updateLabels(parser.getLabels()); this.updateCommands(parser.getCommands()); IProject project = getCurrentProject(); if (project == null) return; IFile cFile = ((FileEditorInput) editor.getEditorInput()).getFile(); boolean isMainFile = cFile.equals(TexlipseProperties.getProjectSourceFile(project)); pollCancel(monitor); // After here we just store those fun properties... if (parser.isLocalBib()) { TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXLOCALBIB_PROPERTY, new Boolean(true)); } else { TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXLOCALBIB_PROPERTY, null); } // Only update Preamble, Bibstyle if main Document if (isMainFile) { boolean biblatexMode = parser.isBiblatexMode(); updateBiblatex(project, biblatexMode, parser.getBiblatexBackend(), false); String[] bibs = parser.getBibs(); this.updateBibs(bibs, biblatexMode, cFile); pollCancel(monitor); String preamble = parser.getPreamble(); if (preamble != null) { TexlipseProperties.setSessionProperty( project, TexlipseProperties.PREAMBLE_PROPERTY, preamble); } if (!biblatexMode) { String bibstyle = parser.getBibstyle(); if (bibstyle != null) { String oldStyle = (String) TexlipseProperties.getSessionProperty( project, TexlipseProperties.BIBSTYLE_PROPERTY); if (oldStyle == null || !bibstyle.equals(oldStyle)) { TexlipseProperties.setSessionProperty( project, TexlipseProperties.BIBSTYLE_PROPERTY, bibstyle); // schedule running bibtex on the next build TexlipseProperties.setSessionProperty( project, TexlipseProperties.BIBFILES_CHANGED, new Boolean(true)); } } } } }
/** * Determines, if the current output file is up to date (i.e. all source files are older). This * method is aware of partial builds. * * @return true, if the output file does not need to be rebuilt; false if it should */ public boolean isUpToDate() { long lastBuildStamp = getOutputFileDate(); IResource[] files = TexlipseProperties.getAllProjectFiles(project); for (int i = 0; i < files.length; i++) { long stamp = files[i].getLocalTimeStamp(); if (stamp > lastBuildStamp) { return false; } } return true; }
/** Creates the reference containers. */ private void createReferenceContainers() { boolean parseAll = false; IProject project = getCurrentProject(); if (project == null) { if (bibContainer == null) bibContainer = new ReferenceContainer(); if (labelContainer == null) labelContainer = new ReferenceContainer(); if (commandContainer == null) commandContainer = new TexCommandContainer(); return; } ReferenceContainer bibCon = (ReferenceContainer) TexlipseProperties.getSessionProperty( project, TexlipseProperties.BIBCONTAINER_PROPERTY); if (bibCon == null) { bibContainer = new ReferenceContainer(); TexlipseProperties.setSessionProperty( project, TexlipseProperties.BIBCONTAINER_PROPERTY, bibContainer); parseAll = true; } else { bibContainer = bibCon; } ReferenceContainer labCon = (ReferenceContainer) TexlipseProperties.getSessionProperty( project, TexlipseProperties.LABELCONTAINER_PROPERTY); if (labCon == null) { labelContainer = new ReferenceContainer(); TexlipseProperties.setSessionProperty( project, TexlipseProperties.LABELCONTAINER_PROPERTY, labelContainer); parseAll = true; } else { labelContainer = labCon; } TexCommandContainer comCon = (TexCommandContainer) TexlipseProperties.getSessionProperty( project, TexlipseProperties.COMCONTAINER_PROPERTY); if (comCon == null) { commandContainer = new TexCommandContainer(); TexlipseProperties.setSessionProperty( project, TexlipseProperties.COMCONTAINER_PROPERTY, commandContainer); parseAll = true; } else { commandContainer = comCon; } if (parseAll) { createProjectDatastructs(project); } }
/** * Moves temporary files out of the build directory, if applicable. A file is considered a * temporary file, if * * <ul> * <li>it had been in the temporary files folder before the build process * <p><b>or</b> * <li>it was created or modified during the build process, and has a temporary file extension * as specified in the preferences * </ul> * * @param excludes set of paths to exclude from moving, e.g. because they are the main output * files * @param monitor progress monitor * @throws CoreException if an error occurs */ private void moveTempFiles(final Set<IPath> excludes, IProgressMonitor monitor) throws CoreException { final IContainer aSourceContainer = getActualSourceContainer(); if (tracking.isInitial() || aSourceContainer == null || !aSourceContainer.exists()) { return; } final boolean markAsDerived = "true" .equals( TexlipseProperties.getProjectProperty( project, TexlipseProperties.MARK_TEMP_DERIVED_PROPERTY)); final String[] tempExts = TexlipsePlugin.getPreferenceArray(TexlipseProperties.TEMP_FILE_EXTS); // Check if there is anything to do if (markAsDerived || tempDir != null) { // First move temporary files, which had been placed into the source folder // just prior to the build; // then check for new temporary files, which need to be moved project .getWorkspace() .run( new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { if (movedFiles != null) { if (excludes != null) { movedFiles.removeAll(excludes); } moveFiles(sourceDir, tempDir, movedFiles, markAsDerived, true, monitor); } final Set<IPath> newTempNames = tracking.getNewTempNames(aSourceContainer, tempExts, format, monitor); if (excludes != null) { newTempNames.removeAll(excludes); } moveFiles(sourceDir, tempDir, newTempNames, markAsDerived, true, monitor); } }, monitor); } }
/** * Updates the settings for the BibLaTeX package. If this is not the initial run, checks if * settings have changed from previous parse job and, if applicable, sets a notification flag for * the builder that something has changed. * * @param project the current project * @param biblatexMode true, if biblatex package was found by parser * @param biblatexBackend database backend detected by parser, or null * @param init whether this is the initial run */ private void updateBiblatex( IProject project, boolean biblatexMode, String biblatexBackend, boolean init) { if (!init) { Boolean oldBLMode = (Boolean) TexlipseProperties.getSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXMODE_PROPERTY); String oldBackend = (String) TexlipseProperties.getSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXBACKEND_PROPERTY); boolean bibChanged; if (biblatexMode) { if (oldBLMode != null) { if (biblatexBackend != null) { bibChanged = !biblatexBackend.equals(oldBackend); } else { bibChanged = oldBLMode == null; } } else { bibChanged = true; } } else { bibChanged = oldBLMode != null; } if (bibChanged) { TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_BIBTEX_RERUN, new String("true")); } } if (biblatexMode) { TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXMODE_PROPERTY, new Boolean(true)); } else { TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXMODE_PROPERTY, null); } TexlipseProperties.setSessionProperty( project, TexlipseProperties.SESSION_BIBLATEXBACKEND_PROPERTY, biblatexBackend); }
/** * Creates all the project data structures. These include the reference completions (BibTeX and * label), command completions, the preamble, the BibTeX style. * * @param project The current project */ private void createProjectDatastructs(IProject project) { // IResource resource = ((FileEditorInput)editor.getEditorInput()).getFile(); IResource[] files = TexlipseProperties.getAllProjectFiles(project); if (files != null) { IFile mainFile = TexlipseProperties.getProjectSourceFile(project); for (int i = 0; i < files.length; i++) { // IPath path = files[i].getFullPath(); String ext = files[i].getFileExtension(); // here are the file types we want to parse if ("tex".equals(ext) || "ltx".equals(ext) || "sty".equals(ext)) { try { String input = TexlipseProperties.getFileContents(files[i]); LatexRefExtractingParser lrep = new LatexRefExtractingParser(); lrep.parse(input); if (lrep.isFatalErrors()) { MarkerHandler marker = MarkerHandler.getInstance(); marker.addFatalError( editor, "The file " + files[i].getFullPath() + " contains fatal errors, parsing aborted."); continue; } List<ReferenceEntry> labels = lrep.getLabels(); if (labels.size() > 0) { labelContainer.addRefSource(files[i].getProjectRelativePath().toString(), labels); } List<TexCommandEntry> commands = lrep.getCommands(); if (commands.size() > 0) { commandContainer.addRefSource(files[i].getProjectRelativePath().toString(), commands); } // Only update Preamble, Bibstyle if main Document if (files[i].equals(mainFile)) { String[] bibs = lrep.getBibs(); boolean biblatexMode = lrep.isBiblatexMode(); String biblatexBackend = lrep.getBiblatexBackend(); this.updateBiblatex(project, biblatexMode, biblatexBackend, true); this.updateBibs(bibs, biblatexMode, files[i]); String preamble = lrep.getPreamble(); if (preamble != null) { TexlipseProperties.setSessionProperty( project, TexlipseProperties.PREAMBLE_PROPERTY, preamble); } String bibstyle = lrep.getBibstyle(); if (bibstyle != null) TexlipseProperties.setSessionProperty( project, TexlipseProperties.BIBSTYLE_PROPERTY, bibstyle); } } catch (IOException ioe) { TexlipsePlugin.log( "Unable to open file " + files[i].getFullPath() + " for parsing", ioe); } } } // save time by doing this last labelContainer.organize(); commandContainer.organize(); } }
/** * Updates completions for the BibTeX -data * * @param bibNames Names of the BibTeX -files that the document uses * @param resource The resource of the document */ private void updateBibs(String[] bibNames, boolean biblatexMode, IResource resource) { IProject project = getCurrentProject(); if (project == null) return; if (!biblatexMode) { for (int i = 0; i < bibNames.length; i++) { if (!bibNames[i].endsWith(".bib")) { bibNames[i] += ".bib"; } } } if (bibContainer.checkFreshness(bibNames)) { return; } TexlipseProperties.setSessionProperty(project, TexlipseProperties.BIBFILE_PROPERTY, bibNames); List<String> newBibs = bibContainer.updateBibHash(bibNames); IPath path = resource.getFullPath().removeFirstSegments(1).removeLastSegments(1); if (!path.isEmpty()) path = path.addTrailingSeparator(); KpsewhichRunner filesearch = new KpsewhichRunner(); for (Iterator<String> iter = newBibs.iterator(); iter.hasNext(); ) { String name = iter.next(); try { String filepath = ""; // First try local search IResource res = project.findMember(path + name); // Try searching relative to main file if (res == null) { IContainer sourceDir = TexlipseProperties.getProjectSourceDir(project); res = sourceDir.findMember(name); } if (res != null) { filepath = res.getLocation().toOSString(); } if (res == null) { // Try Kpsewhich filepath = filesearch.getFile(resource, name, "bibtex"); if (filepath.length() > 0 && !(new File(filepath).isAbsolute())) { // filepath is a local path res = project.findMember(path + filepath); if (res != null) { filepath = res.getLocation().toOSString(); } else { filepath = ""; } } else if (filepath.length() > 0) { // Create a link to resource IPath p = new Path(filepath); if (name.indexOf('/') >= 0) { // Remove path from name name = name.substring(name.lastIndexOf('/') + 1); } IFile f = project.getFile(path + name); if (f != null && !f.exists()) { f.createLink(p, IResource.NONE, null); } } } if (filepath.length() > 0) { BibParser parser = new BibParser(filepath); try { List<ReferenceEntry> bibEntriesList = parser.getEntries(); if (bibEntriesList != null && bibEntriesList.size() > 0) { bibContainer.addRefSource(path + name, bibEntriesList); } else if (bibEntriesList == null) { MarkerHandler marker = MarkerHandler.getInstance(); marker.addFatalError( editor, "The BibTeX file " + filepath + " contains fatal errors, parsing aborted."); continue; } } catch (IOException ioe) { TexlipsePlugin.log("Can't read BibTeX file " + filepath, ioe); } } else { MarkerHandler marker = MarkerHandler.getInstance(); marker.addFatalError(editor, "The BibTeX file " + name + " not found."); } } catch (CoreException ce) { TexlipsePlugin.log("Can't run Kpathsea", ce); } } bibContainer.organize(); }
/** * Renames output files and/or moves them if necessary. A file is considered an output file, if * * <ul> * <li>it is the current output file (which can also be from a temporary build) * <p><b>or</b> * <li>it has the same file name as the current input file, apart from its file extension, and * one of the derived file extensions as specified in the preferences * </ul> * * @param monitor progress monitor * @return set of paths to the (possibly moved) files * @throws CoreException if an error occurs */ private Set<IPath> moveOutputFiles(IProgressMonitor monitor) throws CoreException { final boolean markAsDerived = "true" .equals( TexlipseProperties.getProjectProperty( project, TexlipseProperties.MARK_OUTPUT_DERIVED_PROPERTY)); final String[] derivedExts = TexlipsePlugin.getPreferenceArray(TexlipseProperties.DERIVED_FILES); final IFile aSourceFile = getActualSourceFile(); final IContainer aSourceContainer = getActualSourceContainer(); final IFile sOutputFile = getSelectedOutputFile(); final IContainer sOutputContainer = getSelectedOutputContainer(markAsDerived, monitor); if (aSourceFile == null || aSourceContainer == null || sOutputFile == null || sOutputContainer == null) { // Something is wrong with the settings return null; } // Get name without extension from main files for renaming final String dotFormat = '.' + format; final String sourceBaseName = stripFileExt(aSourceFile.getName(), null); final String outputBaseName = stripFileExt(sOutputFile.getName(), dotFormat); // Check if files are to be moved or renamed final boolean moveFiles = !sourceBaseName.equals(outputBaseName) || !sOutputContainer.equals(aSourceContainer); // Retrieve output and other derived files along with their extensions final Map<IPath, String> outputFiles = ProjectFileTracking.getOutputNames( aSourceContainer, sourceBaseName, derivedExts, format, monitor); // Check if there is anything to do if ((moveFiles || markAsDerived) && !outputFiles.isEmpty()) { final Set<IPath> movedFiles = new HashSet<IPath>(outputFiles.size()); project .getWorkspace() .run( new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { // Move files to destination folder and rename for (Entry<IPath, String> entry : outputFiles.entrySet()) { IFile currentFile = project.getFile(entry.getKey()); if (moveFiles) { // Determine new file name String destName = outputBaseName + entry.getValue(); // Move file IFile dest = moveFile(project, currentFile, sOutputContainer, destName, monitor); if (dest != null && markAsDerived) { dest.setDerived(true); } movedFiles.add(dest.getProjectRelativePath()); } else { // Possibly mark as derived if (markAsDerived) { currentFile.setDerived(true); } movedFiles.add(entry.getKey()); } } } }, monitor); return movedFiles; } else { return outputFiles.keySet(); } }
/** * Does the same as super.createDocument(Object), except this also adds latex nature to the * project containing the given document. */ public IDocument getDocument(Object element) { IDocument doc = super.getDocument(element); // add latex nature to project holding this latex file // this way we also get latex builder to any project that has latex files if (element instanceof FileEditorInput) { IFile file = (IFile) ((FileEditorInput) element).getAdapter(IFile.class); if (file != null) { IProject project = file.getProject(); try { if (!project.hasNature(TexlipseNature.NATURE_ID)) { return doc; // TexlipseProjectCreationOperation.addProjectNature(project, new // NullProgressMonitor()); } else if (TexlipseProperties.getProjectProperty( project, TexlipseProperties.OUTPUT_FORMAT) == null) { // this is needed for imported projects TexlipseNature n = new TexlipseNature(); // the nature is not added, just configured n.setProject(project); // this will cause the builder to be added, if not already there n.configure(); } } catch (CoreException e) { return doc; } // output format might not yet be set String format = TexlipseProperties.getProjectProperty(project, TexlipseProperties.OUTPUT_FORMAT); if (format == null || format.length() == 0) { TexlipseProperties.setProjectProperty( project, TexlipseProperties.OUTPUT_FORMAT, TexlipsePlugin.getPreference(TexlipseProperties.OUTPUT_FORMAT)); TexlipseProperties.setProjectProperty( project, TexlipseProperties.BUILDER_NUMBER, TexlipsePlugin.getPreference(TexlipseProperties.BUILDER_NUMBER)); TexlipseProperties.setProjectProperty( project, TexlipseProperties.MARK_TEMP_DERIVED_PROPERTY, "true"); TexlipseProperties.setProjectProperty( project, TexlipseProperties.MARK_OUTPUT_DERIVED_PROPERTY, "true"); String name = file.getName(); TexlipseProperties.setProjectProperty( project, TexlipseProperties.MAINFILE_PROPERTY, name); String output = name.substring(0, name.lastIndexOf('.') + 1) + TexlipsePlugin.getPreference(TexlipseProperties.OUTPUT_FORMAT); TexlipseProperties.setProjectProperty( project, TexlipseProperties.OUTPUTFILE_PROPERTY, output); IPath path = file.getFullPath(); String dir = path.removeFirstSegments(1).removeLastSegments(1).toString(); if (dir.length() > 0) { TexlipseProperties.setProjectProperty( project, TexlipseProperties.SOURCE_DIR_PROPERTY, dir); TexlipseProperties.setProjectProperty( project, TexlipseProperties.OUTPUT_DIR_PROPERTY, dir); TexlipseProperties.setProjectProperty( project, TexlipseProperties.TEMP_DIR_PROPERTY, dir); } } } } return doc; }