Skip to content
This repository has been archived by the owner on Aug 14, 2022. It is now read-only.

Add Opener Registry #265

Merged
merged 19 commits into from
Oct 23, 2016
Merged

Add Opener Registry #265

merged 19 commits into from
Oct 23, 2016

Conversation

yitzchak
Copy link
Collaborator

@yitzchak yitzchak commented Oct 16, 2016

This is PR implements a simple opener registry which tries to pick an opener based on availability and features. The user can override the automatic selection via the latex.opener setting.

Algorithm

  1. If a specific opener has been set with latex.opener and that one can open the file then use it.
  2. Filter out the openers that cannot open the requested file.
  3. Abort and show a warning message if there no openers left after the filter.
  4. Sort the openers in decreasing priority with SyncTeX capability ranked higher then "open in background" capability.
  5. If latex.enableSynctex is enabled then use the viewer with the highest priority that supports SyncTeX if one is present. If there are openers that support both SyncTeX and "open in background" then these will be at the front of the list because of the priority sort.
  6. If latex.openResultInBackground is enabled then use the viewer with the highest priority that supports opening in background if one is present.
  7. If all else fails, just use the highest priority opener.

Issues

  • Migrate latex.alwaysOpenResultInAtom setting to latex.opener = 'pdf-view' setting.
  • Simplify settings? Checking the existance of openers could be done with calls like okular --version if we replaced the latex.texPath with latex.paths. Would make all the opener path settings unneeded and make it possible to find 64bit SumatraPDF without user configuration. Maybe later
  • Refactor EvinceOpener to move methods into class.
  • Specs

Resolves #235 and resolves #85 and resolves #252.

Copy link
Owner

@thomasjo thomasjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is looking great! 💖

Not loving the latex.opener config stuff, since it essentially invalidates the "dependency injection" system based around loading openers from the openers directory... but I cannot think of a better alternative right now that still results in giving the user a list of options in the settings view. So let's leave that as is for the time being, unless you have some ideas.

Would also be great if the getName functions could be replaced with a convention based scheme, like simply grabbing the name from the file name sans opener suffix. The functions feel unnecessary since the name is already available elsewhere.

this.createOpeners()
}

async createOpeners () {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename this to initializeOpeners or some such.

return new OpenerImpl()
})
// Sort the openers into decreasing priority
this.openers = _.orderBy(this.openers, [opener => opener.hasSynctex(), opener => opener.canOpenInBackground()], ['desc', 'desc'])
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract this "capability list" into a separate variable for readability? Call it capabilityPrioritization or something along those lines. Maybe simply capabilities?

const openResultInBackground = atom.config.get('latex.openResultInBackground')
const enableSynctex = atom.config.get('latex.enableSynctex')

let openers = _.filter(this.openers, opener => opener.canOpen(filePath))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const openers = this.openers.filter(opener => opener.canOpen(filePath))

Also, I'd probably name it candidates instead of openers to indicate this is the list of candidates from which we will select an opener.

let opener

if (name !== 'automatic') {
opener = _.find(openers, opener => opener.getName() === name)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opener = openers.find(opener => opener.getName() === name)

@yitzchak
Copy link
Collaborator Author

yitzchak commented Oct 18, 2016

One solution to the latex.opener settings and getName function issue would be to rename the openers to be consistent with the names in latex.opener. This means atompdf-opener.js ➡️ pdf-view.js and xdg-opener.js ➡️ xdg-open.js. We then load using:

const schema = atom.config.getSchema('latex.opener')
const dir = path.join(__dirname, 'openers')
const ext = '.js'
this.openers = new Map()
for (const name of schema.enum) {
  const OpenerImpl = require(path.format({ dir, name, ext }))
  this.openers.set(name, new OpenerImpl())
}

The selection logic would then be:

  1. If a specific opener has been set with latex.opener and that one can open the file then use it.
  2. Filter out the openers that cannot open the requested file.
  3. Abort and show a warning message if there no openers left after the filter.
  4. Sort the openers in decreasing priority with SyncTeX capability ranked higher then "open in background" capability.
  5. If latex.enableSynctex is enabled then use the viewer with the highest priority that supports SyncTeX if one is present. If there are openers that support both SyncTeX and "open in background" then these will be at the front of the list because of the priority sort.
  6. If latex.openResultInBackground is enabled then use the viewer with the highest priority that supports opening in background if one is present.
  7. If all else fails, just use the highest priority opener.

@thomasjo
Copy link
Owner

I like that idea!

@yitzchak
Copy link
Collaborator Author

@thomasjo Can you give it one last review? I have added specs for OpenerRegistry and avoided needing to do package activation by initializing the openers only in package activation. Maybe not the best solution, but it works.

export default class OpenerRegistry {
openers = new Map()

async initializeOpeners () {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this async?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left over from when I had filtering code there.

@@ -60,6 +60,7 @@ export default {
const Composer = require('./composer')

global.latex = new Latex()
latex.opener.initializeOpeners()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to the Latex constructor if/when we make initializeOpeners synchronous? Feels like some responsibility has leaked out here — this needs to be done either in Latex or OpenerRegistry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was done in OpenerRegistry but that caused problems in the spec since the schema was not available.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I propose we fix the spec instead. This just doesn't feel right 💭

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I'll have to dig into the package activation issue to make it happen. OpenerRegistry is getting created in a whole bunch of places in the specs. Moving it back won't cause spec failure, just console messages, BTW.

@yitzchak
Copy link
Collaborator Author

yitzchak commented Oct 22, 2016

@thomasjo I've tried migrated the specs to use package activation by making the most minimal changes to specs unrelated to this PR. Looks like everything is working aside from latexmk 4.48 being broken on MiKTeX. I think we should do further tweaks to the unrelated specs if needed in #224 to avoid too many merge conflicts. In other words, I think this is basically ready to 🚢!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants