How can I create a page that Atom opens up in itself from HTML files?


#1

Hi,

I am working on my language-unix-shell package, adding features from the autocomplete-bash-builtins package, as I want it to do autocompletions for commands it syntax-highlights. Currently it hyperlinks “more” to a man page for the command in question hosted by my GitHub Pages website, The Hornery and I would rather it opened up a new tab (in Atom itself, I don’t want it to open up the default web browser) with the man page (hosted in the package’s own folder and not on The Hornery) in it. I know that HTML can be rendered in Atom as a web page (e.g., look at the core about package), but I don’t know how to implement this so that I specify the HTML file (stored in the /man subfolder of my package) to be opened when the user clicks the “more” hyperlink and it’s opened in a new tab in Atom. If the structure of my package’s repository is causing some confusion (using descriptive language has never been my strong suit) feel free to look at it yourself, you can see the man subfolder in its top-level directory.

I’ve looked at the About’s packages lib/about-view.coffee file and based on it I would think I would have to convert each man HTML page into a CoffeeScript file like it (which as you can appreciate would be rather tedious, seeing how I’ve got ~ 100 man pages to do this for). I was hoping there might be a less painful solution available…

Here’s a screenshot showing the “more” hyperlink in the autocompletions my package provides, in case my mention of it is causing some confusion.


**EDIT**: If it is likely I will have to convert all my HTML files into CoffeeScript files like the about package's `lib/about-view.coffee` file, I think I will go the simpler route of getting the user's web browser to open the man page. To do so, I would appreciate it if you could tell me how I could create a hyperlink to open the man page (in the package's `/man` subfolder, **not** in *The Hornery*) in one's browser. I want this hyperlink to work even without an Internet Connection, so I don't want it to open the man page in its GitHub repo.

Thanks for your time,
Brenton


#2

Attempted solution: I searched for “man” in the Atom package search engine, expecting to find a package that provides man pages and I found the man package. I have since updated my language-unix-shell package’s GitHub repo with changes I took from the man package. Unfortunately, I haven’t quite made it work. Here is my lib/provider.coffee file:


bvars   = require './vars'
url     = require('url');
ManView = require('./man-view');

module.exports =
class shellVarProvider
  selector: '.source.shell'
  disableForSelector: '.comment'

  inclusionPriority: 0
  suggestionPriority: 2
  filterSuggestions: true
  excludeLowerPriority: false

  getSuggestions: ({editor, bufferPosition, scopeDescriptor, prefix}) ->
    if prefix?.length > 0
        rl = for name, bvar of bvars when bvar.text.startsWith(prefix[0])
          @buildVariableValue(bvar, prefix)
      return rl
    return []

  buildVariableValue: (bvar, prefix) ->
    text: bvar.text
    type: bvar.type
    rightLabel: bvar.text
    description: bvar.description
    replacementPrefix: prefix
    descriptionMoreURL: @man_page(bvar.text)

  man_page: (command) =>
    parsed = url.parse(command);
    return if 'man:' != parsed.protocol
    path = parsed.path.substring(1);
    result = new ManView(uri: command, filePath: path);
    return result;

the problem is that the man_page function (copied from the man package’s lib/man.coffee function man_opener) is not returning a usable result for the buildVariableValue function. My knowledge of Coffee is in its infancy, so I’m kind of confused as to how to fix this problem. Please help.


#3

I have also tried editing provider.coffee to:

bvars   = require './vars'
url     = require('url');
ManView = require('./man-view');\
{exec} = require "child_process"
activeEditor = atom.workspace.getActiveTextEditor()
notifications = atom.notifications

module.exports =
class shellVarProvider
  selector: '.source.shell'
  disableForSelector: '.comment'

  inclusionPriority: 0
  suggestionPriority: 2
  filterSuggestions: true
  excludeLowerPriority: false

  getSuggestions: ({editor, bufferPosition, scopeDescriptor, prefix}) ->
    if prefix?.length > 0
        rl = for name, bvar of bvars when bvar.text.startsWith(prefix[0])
          @buildVariableValue(bvar, prefix)
      return rl
    return []

  buildVariableValue: (bvar, prefix) ->
    text: bvar.text
    type: bvar.type
    rightLabel: bvar.text
    description: bvar.description
    replacementPrefix: prefix
    descriptionMoreURL: (rightLabel) =>
          class ManInputView extends View
              detaching: false
              @content: ->
                  @div class: 'command-palette', =>
                      @subview 'selectEditor', new TextEditorView(mini: true)

              initialize: ->
                  atom.commands.add 'atom-text-editor', 'core:confirm', => @confirm()
                  atom.commands.add 'atom-text-editor', 'core:cancel', => @detach()
                  @attach()

              toggle: ->
                  if @hasParent()
                      @detach
                  else
                      @attach()

              detach: ->
                  return unless @hasParent()
                  @detaching = true
                  selectEditorFocused = @selectEditor.isFocused
                  @selectEditor.setText('')
                  @panel.destroy()
                  super
                  @detaching = false

              confirm: ->
                  page = rightLabel
                  notifications.addError "#{rightLabel}"
                  uri = "man://editor/#{page}"
                  atom.workspace.open(uri)
                  @detach()

              attach: ->
                  @panel ?= atom.workspace.addModalPanel(item: this)
                  @panel.show()
                  @selectEditor.focus()

(which sets descriptionMoreURL to the output of lib/man-input-view.coffee, or so was the hope). But this gives a “More” link that when clicked does nothing. I have tried to debug this script by adding that notifications.addError line, but it does nothing (i.e., I can’t see any changes it makes, at all).


#4

To be honest, I didn’t read everything you wrote because I’m a little pressed for time right now. Have you taken a look at the markdown-preview package? It converts the Markdown in your text editor to HTML and then displays it in a separate tab … that sounds a lot like what you’re trying to do.


#5

Thanks for the suggestion, but I’m looking at markdown-preview’s libraries and as I’m not really fluent in CoffeeScript I’m just as confused trying to add it to my package as I was with the man package.


#6

Check out the package(s) that show a web browser inside atom.


#7

I have looked at browser-plus’s source code. It was too complex for me to add it to my package, frankly it’s more complex than the code of markdown-preview. The man package’s libraries are at least closer to my reach, that’s part of the reason why I choose them. I would love to fix this problem myself, but it’s beginning to seem like a pull request will be my best shot of getting somewhere. I have moved my experimental man page additions to the man branch of this repo. If anyone reading this wants to help by creating a pull request implementing this change I will greatly appreciate it! It will probably also teach me a great deal about CoffeeScript, so I won’t need to ask quite as many questions here.


#8

I was thinking of just bringing the page up in a tab with a url.


#9

You mean passing browser-plus the URL of the man page? The problem with that strategy is that as I want this link to work offline, I need to create a man page link (on localhost) for it to open. I have tried opening browser-plus to the URL created by the man command, but it failed. See the URL used to host the page by the man command is man://editor/#{page} whenever I enter this URL (after specifying to the man command the dpkg man page) I am redirected to http://editor/dpkg.1.html, which, of course, doesn’t exist. I have tried using the alternate URL (in case I got the URL created by the man package wrong) man://editor/dpkg.html and it too failed.


#10

Oh and btw I have tried to implement what you suggested. But it too seems beyond my grasp, this is my provider.coffee file when I tried to use browser-plus to open the man page (all other files associated with it is stored in the man branch of my language-shellscript repo):

bvars   = require './vars'
url     = require('url');
ManView = require('./man-view');
{exec} = require "child_process"
activeEditor = atom.workspace.getActiveTextEditor()
notifications = atom.notifications

module.exports =
class shellVarProvider
  selector: '.source.shell'
  disableForSelector: '.comment'

  inclusionPriority: 0
  suggestionPriority: 2
  filterSuggestions: true
  excludeLowerPriority: false

  getSuggestions: ({editor, bufferPosition, scopeDescriptor, prefix}) ->
    if prefix?.length > 0
        rl = for name, bvar of bvars when bvar.text.startsWith(prefix[0])
          @buildVariableValue(bvar, prefix)
      return rl
    return []

  buildVariableValue: (bvar, prefix) ->
    text: bvar.text
    type: bvar.type
    rightLabel: bvar.text
    description: bvar.description
    replacementPrefix: prefix
    descriptionMoreURL: (rightLabel) =>
          class ManInputView extends View
              detaching: false
              @content: ->
                  @div class: 'command-palette', =>
                      @subview 'selectEditor', new TextEditorView(mini: true)

              initialize: ->
                  atom.commands.add 'atom-text-editor', 'core:confirm', => @confirm()
                  atom.commands.add 'atom-text-editor', 'core:cancel', => @detach()
                  @attach()

              toggle: ->
                  if @hasParent()
                      @detach
                  else
                      @attach()

              detach: ->
                  return unless @hasParent()
                  @detaching = true
                  selectEditorFocused = @selectEditor.isFocused
                  @selectEditor.setText('')
                  @panel.destroy()
                  super
                  @detaching = false

              confirm: ->
                  page = rightLabel
                  notifications.addError "#{rightLabel}"
                  uri = "man://editor/#{page}"
                  browlib="#{atom.packages.getLoadedPackage('browser-plus').path}/lib/browser-plus"
                  browserplus=require("#{browlib}")
                  browopen=browserplus.open(uri)
                  @detach()

              attach: ->
                  @panel ?= atom.workspace.addModalPanel(item: this)
                  @panel.show()
                  @selectEditor.focus()