Jump to content

Any way to open a URL with a particular browser?


Recommended Posts

I've gotten kind of spoiled with the extended actions for some searches (e.g. App name > Tab > Open in Finder), so every time I paste a URL I kind of expect to be able to hit tab and choose which browser to use to open it. But I can't. Is there any built-in way to do this? I do use the clipboard integration as well so it'd be great if I can do it directly from the history view as well but that's not required.

 

I looked into creating a workflow with the open URL action, but that doesn't seem to work with providing a full URL and it requires me to set to browser in the workflow which kind of defeats the purpose.

Link to post

I actually used to use Choosy when I used to do this a lot more, but it's infrequent enough these days that the extra annoyance of using a separate tool outweighs the benefit. What I'd really love would be a way to register a URL as a "filetype" so that I can get the usual extra menu. i.e. if I type <space>filename.txt<tab> (assuming the file exists obviously), one of the options is "Open with...". What I really want is a way to have that same sort of menu for a URL.

Link to post
On 8/21/2018 at 9:45 PM, Alex M said:

I looked into creating a workflow with the open URL action, but that doesn't seem to work with providing a full URL and it requires me to set to browser in the workflow which kind of defeats the purpose.

 

There are a few things you can do in Alfred's workflows which help with this.

 

Firstly, you could have two separate Open URL actions configured as appropriate, then use modifiers on the connections... e.g. return on the result will open the first Open URL object in the default browser, alt+return will open in the second Open URL object with a specified browser. A simple workflow could be:

 

Keyword to take a URL as argument -> two Open URL actions, one with a modifier.

 

Another option is to dynamically configure the Open URL object. This is a more advanced workflow technique, but allows for significant flexibility using the JSON utility:

https://www.alfredapp.com/help/workflows/utilities/json/

 

It's probably best to take the simple approach first.

Link to post

If you're pasting URLs into Alfred, here's a workflow that shows you a bunch of browsers when you paste a URL into Alfred.

 

It uses the keyword "http", so when you paste a URL into Alfred, it shows you "Open in Safari", "Open in Chrome" ... options. The browsers are configured in the browsers.py file in the workflow:

"""Open a URL in different browsers."""

from __future__ import print_function, absolute_import

from collections import namedtuple
import json
import sys

Browser = namedtuple('Browser', 'name path')

BROWSERS = [
    Browser(u'Safari', u'/Applications/Safari.app'),
    Browser(u'Chrome', u'/Applications/Google Chrome.app'),
    Browser(u'Firefox', u'/Applications/FirefoxDeveloperEdition.app'),
]


def log(s, *args):
    """Simple STDERR logger."""
    if args:
        s = s % args
    print(s, file=sys.stderr)


def main():
    """Run Script Filter."""
    url = sys.argv[1].decode('utf-8')
    log('url=%r', url)

    items = []
    for b in BROWSERS:
        items.append(dict(
            title='Open in ' + b.name,
            subtitle=b.path,
            arg=url,
            icon=dict(
                path=b.path,
                type='fileicon',
            ),
            valid=True,
            variables=dict(
                browser=b.path,
                url=url,
            ),
        ))

    json.dump(dict(items=items), sys.stdout)


if __name__ == '__main__':
    main()

 

Edited by deanishe
Link to post

I ended up doing a lot more work than I planned on this, but I'm pretty happy with what I came up with. I started with @deanishe's workflow and then edited the python script to get a list of URL handlers from the OS instead of requiring them to be hard-coded. This does slow down the workflow by about 500 ms which isn't ideal, but it gets the job done. I've also discovered Alfred-Workflow and the built in support for caching so I'm going to try that later in order to speed things up a bit.

 

It'd be great if there was a way to pull URL handlers directly from Alfred/Spotlight, but all I've been able to find so far is calling 'lsregister -dump' which is where most of the speed hit comes from. If anyone has any suggestions on how to speed that bit up I'd greatly appreciate it. In the meantime, here's the updated code I used for the workflow:

 

"""Open a URL in different browsers"""

from __future__ import print_function, absolute_import

from collections import namedtuple
import json
import sys
import os
import re

rexps = [
    re.compile('^\s*(bundle)\s*id:\s*(\d*)'),
    re.compile('^\s*(path):\s*(.*)'),
    re.compile('^\s*(name):\s*(.*)'),
    re.compile('^\s*(bindings):\s*(.*)')
]


def log(s, *args):
    """Simple STDERR logger."""
    if args:
        s = s % args
    print(s, file=sys.stderr)

def gethandlers():
    handlers = {}
    bundle = ""

    dump = os.popen("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump")

    for line in dump.readlines():
        for rexp in rexps:
            m = rexp.match(line)
            if not m:
                continue

            key = m.group(1)
            value = m.group(2)

            if key == "bundle":
                if bundle != value:
                    bundle = value
                    name = ""
                    path = ""

            if key == "name" and not name:
                name = value

            if key == "path" and not path:
                path = value

            if key == "bindings" and 'http:' in value.split(","):
                handlers[name] = path

    dump.close()
    handlers.pop('nwjs', None)
    handlers.pop('VLC media player', None)
    return handlers

def main():
    """Run Script Filter."""
    url = ("http" + sys.argv[1]).decode('utf-8')
    log('url=%r', url)

    items = []
    browsers = gethandlers()
    for b in sorted(browsers):
        items.append(dict(
            title='Open in ' + b,
            subtitle=browsers[b],
            arg=url,
            icon=dict(
                path=browsers[b],
                type='fileicon',
            ),
            valid=True,
            variables=dict(
                browser=browsers[b],
                url=url,
            ),
        ))

    json.dump(dict(items=items), sys.stdout)


if __name__ == '__main__':
    main()

 

Link to post

From one of my workflows, here's a script that retrieves all apps that can open a URL (scheme). You mostly need to change the URLs in lines 35 and 58 from mailto: to http: URLs.

 

I wouldn't bother with it personally. So many apps can open http URLs that you'll probably end up adding a whitelist to keep the results clean anyway.

 

Edited by deanishe
Link to post

I've updated my script to check if the input is a real URL, as it was annoying me a bit when looking up HTTP stuff in Dash.

 

"""Open a URL in different browsers."""

from __future__ import print_function, absolute_import

from collections import namedtuple
import json
import re
import sys

Browser = namedtuple('Browser', 'name path')

BROWSERS = [
    Browser(u'Safari', u'/Applications/Safari.app'),
    Browser(u'Chrome', u'/Applications/Google Chrome.app'),
    Browser(u'Firefox', u'/Applications/FirefoxDeveloperEdition.app'),
]


def log(s, *args):
    """Simple STDERR logger."""
    if args:
        s = s % args
    print(s, file=sys.stderr)


def is_url(s):
    """Return ``True``if ``s`` is an http(s) URL."""
    return re.match(r'https?://\S+', s, re.IGNORECASE)


def main():
    """Run Script Filter."""
    query = sys.argv[1].decode('utf-8')

    log('query=%r', query)

    if not is_url(query):
        log('not a URL; exiting')
        return

    items = []
    for b in BROWSERS:
        items.append(dict(
            title=u'Open in ' + b.name,
            subtitle=u'Open “%s” in %s' % (query, b.name),
            arg=query,
            icon=dict(
                path=b.path,
                type='fileicon',
            ),
            valid=True,
            variables=dict(
                browser=b.path,
                url=query,
            ),
        ))

    json.dump(dict(items=items), sys.stdout)


if __name__ == '__main__':
    sys.exit(main())

 

Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...