Submitter | Gregory Szorc |
---|---|
Date | July 16, 2016, 4:57 a.m. |
Message ID | <d9f80be1178350827224.1468645072@ubuntu-vm-main> |
Download | mbox | patch |
Permalink | /patch/15898/ |
State | Changes Requested |
Headers | show |
Comments
On Fri, Jul 15, 2016 at 09:57:52PM -0700, Gregory Szorc wrote: > # HG changeset patch > # User Gregory Szorc <gregory.szorc@gmail.com> > # Date 1468645039 25200 > # Fri Jul 15 21:57:19 2016 -0700 > # Node ID d9f80be11783508272240020c29ffd36529de53e > # Parent 1c22400db72de4bbeb992fde534c0abbe1367b03 > commands: possibly start a web browser during `hg serve` (BC) > > When D. Richard Hipp visited the Mozilla office several months ago > and was showing me all the awesomeness in his Fossil VCS, one of the > features that stood out to me was `fossil ui` starting a fully-featured > HTTP/HTML server including the web browser. It was so... elegant > to just type a command and get a web browser pointed to a local > HTTP server where you could interact with your VCS. > > From my own experience, when I run `hg serve` from an interactive > terminal I open a web browser 95% of the time. The other 5% of the > time I start the server so I can point another Mercurial client at it. > `hg serve` isn't currently optimized for my use case because I have > to run `hg serve` then copy or type a URL into my browser. What a waste > of time! Being at the opposite end of the spectrum (rarely needing a web browser when running hg serve), it strikes me that if your terminal emulator doesn't allow you to click a link and have it open in your default browser windows, you should investigate changing your terminal emulator. Mike
16.07.2016, 12:58, "Gregory Szorc" <gregory.szorc@gmail.com>: > # HG changeset patch > # User Gregory Szorc <gregory.szorc@gmail.com> > # Date 1468645039 25200 > # Fri Jul 15 21:57:19 2016 -0700 > # Node ID d9f80be11783508272240020c29ffd36529de53e > # Parent 1c22400db72de4bbeb992fde534c0abbe1367b03 > commands: possibly start a web browser during `hg serve` (BC) > > When D. Richard Hipp visited the Mozilla office several months ago > and was showing me all the awesomeness in his Fossil VCS, one of the > features that stood out to me was `fossil ui` starting a fully-featured > HTTP/HTML server including the web browser. It was so... elegant > to just type a command and get a web browser pointed to a local > HTTP server where you could interact with your VCS. > > From my own experience, when I run `hg serve` from an interactive > terminal I open a web browser 95% of the time. The other 5% of the > time I start the server so I can point another Mercurial client at it. > `hg serve` isn't currently optimized for my use case because I have > to run `hg serve` then copy or type a URL into my browser. What a waste > of time! > > This patch changes the behavior of `hg serve` to automatically start > a web browser if a) the terminal is interactive and we're not running > a background daemon or server for specialized clients b) the --browser > argument explicitly requests we start a browser. > > While this change is backwards incompatible, I think it strikes the > right balance of behavior: we only open browsers if it appears a user > is typing `hg serve`. And, the escape hatch is simple for people > wanting the previous behavior: `hg serve --browser=` or set > "web.browser" to an empty string or "none." > > If nothing else, this change will help users discover the built-in > HTML interface when running `hg serve` for the first time. I still > encounter Mercurial users who don't realize that `hg serve` starts > a browseable server (as opposed to a headless HTTP/protocol server). > Launching the browser automatically will show them that the local > server is more than a "listening at <URL>" message in their terminal. I've been running 3 different browsers with different arguments and extensions on 3 different workspaces (Xfce) for a long time and found that to be great. Now, if Xfce could pick up my custom menu items or shortcuts (it can't) and make one of them the default browser, maaybe I could pick just one for every possible case of me running `hg serve` [1]. I assume it would still open the browser on the workspace where the terminal with `hg serve` is, and not on the workspace I want to keep that browser on. All of that would be fairly annoying. Thank you for reading my rant. So I think that opening a browser on `hg serve` without arguments should be opt-in (require e.g. web.browser=default, or an argument to the command). How about alias.ui = serve --browser? I also think that for hgweb to become more discoverable, we could just fix https://bz.mercurial-scm.org/show_bug.cgi?id=3976 and then write "WebUI available at http://127.0.0.1:8000/" or something more... inviting. Luckily, many terminals actually allow double-clicking or right-clicking the link and picking "Open in browser" in the context menu. [1] My actual default browser is w3m (the text based), that opens in a 80x24 terminal, because that's what I think an application that opens a URL without a warning deserves. (To be fair, w3m is actually nice for browsing pastebins)
On Sat, 16 Jul 2016 14:04:46 +0800, Anton Shestakov wrote: > 16.07.2016, 12:58, "Gregory Szorc" <gregory.szorc@gmail.com>: > I've been running 3 different browsers with different arguments and extensions on 3 different workspaces (Xfce) for a long time and found that to be great. Now, if Xfce could pick up my custom menu items or shortcuts (it can't) and make one of them the default browser, maaybe I could pick just one for every possible case of me running `hg serve` [1]. I assume it would still open the browser on the workspace where the terminal with `hg serve` is, and not on the workspace I want to keep that browser on. All of that would be fairly annoying. Thank you for reading my rant. > > So I think that opening a browser on `hg serve` without arguments should be opt-in (require e.g. web.browser=default, or an argument to the command). How about alias.ui = serve --browser? Agree. I don't wanna open GUI unintentionally while working in console. So, -1 for default 0 for opt-in feature > I also think that for hgweb to become more discoverable, we could just fix https://bz.mercurial-scm.org/show_bug.cgi?id=3976 and then write "WebUI available at http://127.0.0.1:8000/" or something more... inviting. Luckily, many terminals actually allow double-clicking or right-clicking the link and picking "Open in browser" in the context menu. I think it's okay to show "listening at" message even if --port is specified.
On Sun, Jul 17, 2016 at 3:22 AM, Yuya Nishihara <yuya@tcha.org> wrote: > On Sat, 16 Jul 2016 14:04:46 +0800, Anton Shestakov wrote: > > 16.07.2016, 12:58, "Gregory Szorc" <gregory.szorc@gmail.com>: > > I've been running 3 different browsers with different arguments and > extensions on 3 different workspaces (Xfce) for a long time and found that > to be great. Now, if Xfce could pick up my custom menu items or shortcuts > (it can't) and make one of them the default browser, maaybe I could pick > just one for every possible case of me running `hg serve` [1]. I assume it > would still open the browser on the workspace where the terminal with `hg > serve` is, and not on the workspace I want to keep that browser on. All of > that would be fairly annoying. Thank you for reading my rant. > > > > So I think that opening a browser on `hg serve` without arguments should > be opt-in (require e.g. web.browser=default, or an argument to the > command). How about alias.ui = serve --browser? > > Agree. I don't wanna open GUI unintentionally while working in console. So, > > -1 for default > 0 for opt-in feature > Fair enough. > > > I also think that for hgweb to become more discoverable, we could just > fix https://bz.mercurial-scm.org/show_bug.cgi?id=3976 and then write > "WebUI available at http://127.0.0.1:8000/" or something more... > inviting. Luckily, many terminals actually allow double-clicking or > right-clicking the link and picking "Open in browser" in the context menu. > > I think it's okay to show "listening at" message even if --port is > specified. > It occurred to me while writing this that "auto launch a browser UI" is applicable to a number of commands, much like having command output go to a pager is. I could envision various commands accepting a "--browser" argument that would open a browser to show results instead of sending it to the terminal. I think the built-in web server needs a lot of love before we could seriously consider this, however. Taken to its extreme, you could put a "terminal emulator" like terminal.js or https://hyperterm.org/ into the browser and create Jupyter Notebook style interactions where you type hg commands into your browser, send them to a command server, and render HTML results inline.
Excerpts from Gregory Szorc's message of 2016-07-17 10:27:58 -0700: > It occurred to me while writing this that "auto launch a browser UI" is > applicable to a number of commands, much like having command output go to a > pager is. I could envision various commands accepting a "--browser" > argument that would open a browser to show results instead of sending it to > the terminal. I think the built-in web server needs a lot of love before we > could seriously consider this, however. Since we have "ui.interface". How about adding suboptions to it? For example: ui.interface.serve=browser:firefox ui.interface.diff=browser:luakit It also makes it more flexible, for example, let commit -i use text, split use ncurses by default. It may be too flexible and can be abused as the pager though. > Taken to its extreme, you could put a "terminal emulator" like terminal.js > or https://hyperterm.org/ into the browser and create Jupyter Notebook > style interactions where you type hg commands into your browser, send them > to a command server, and render HTML results inline.
On 07/16/2016 06:57 AM, Gregory Szorc wrote: > # HG changeset patch > # User Gregory Szorc <gregory.szorc@gmail.com> > # Date 1468645039 25200 > # Fri Jul 15 21:57:19 2016 -0700 > # Node ID d9f80be11783508272240020c29ffd36529de53e > # Parent 1c22400db72de4bbeb992fde534c0abbe1367b03 > commands: possibly start a web browser during `hg serve` (BC) > > When D. Richard Hipp visited the Mozilla office several months ago > and was showing me all the awesomeness in his Fossil VCS, one of the > features that stood out to me was `fossil ui` starting a fully-featured > HTTP/HTML server including the web browser. It was so... elegant > to just type a command and get a web browser pointed to a local > HTTP server where you could interact with your VCS. > > From my own experience, when I run `hg serve` from an interactive > terminal I open a web browser 95% of the time. The other 5% of the > time I start the server so I can point another Mercurial client at it. > `hg serve` isn't currently optimized for my use case because I have > to run `hg serve` then copy or type a URL into my browser. What a waste > of time! > > This patch changes the behavior of `hg serve` to automatically start > a web browser if a) the terminal is interactive and we're not running > a background daemon or server for specialized clients b) the --browser > argument explicitly requests we start a browser. > > While this change is backwards incompatible, I think it strikes the > right balance of behavior: we only open browsers if it appears a user > is typing `hg serve`. And, the escape hatch is simple for people > wanting the previous behavior: `hg serve --browser=` or set > "web.browser" to an empty string or "none." I'm not super enthousiastic about making this the default either. pydoc have '-g' flag to pop up a "graphical interface" which is actually just the browser, I think a short flag would be good. Alternativement we could make `hg view` generic and have a browser option for it.
Jun Wu <quark@fb.com> writes: > Excerpts from Gregory Szorc's message of 2016-07-17 10:27:58 -0700: >> It occurred to me while writing this that "auto launch a browser UI" is >> applicable to a number of commands, much like having command output go to a >> pager is. I could envision various commands accepting a "--browser" >> argument that would open a browser to show results instead of sending it to >> the terminal. I think the built-in web server needs a lot of love before we >> could seriously consider this, however. > > Since we have "ui.interface". How about adding suboptions to it? For example: > > ui.interface.serve=browser:firefox > ui.interface.diff=browser:luakit I like this idea the most. One day, I hope to drag and drop commits to reorder them, along with other nice, modern ui via a web browser.
Patch
diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -6439,16 +6439,17 @@ def root(ui, repo): Returns 0 on success. """ ui.write(repo.root + "\n") @command('^serve', [('A', 'accesslog', '', _('name of access log file to write to'), _('FILE')), + ('', 'browser', '', _('web browser to run')), ('d', 'daemon', None, _('run server in background')), ('', 'daemon-postexec', [], _('used internally by daemon mode')), ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')), # use string type, then we can check if something was passed ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')), ('a', 'address', '', _('address to listen on (default: all interfaces)'), _('ADDR')), ('', 'prefix', '', _('prefix path to serve from (default: server root)'), @@ -6471,16 +6472,24 @@ def root(ui, repo): def serve(ui, repo, **opts): """start stand-alone webserver Start a local HTTP repository browser and pull server. You can use this for ad-hoc sharing and browsing of repositories. It is recommended to use a real web server to serve a repository for longer periods of time. + A web browser will be opened at the started server if the ``--browser`` + argument is defined to any value other than ``none`` or when starting + a server in the foreground (not using ``--daemon``), an interactive + terminal is detected, and we're not starting a server for remote clients. + By default, the system default browser will be opened. The browser to open + and the behavior of auto-opening a browser can be changed by setting the + ``web.browser`` config option. + Please note that the server does not implement access control. This means that, by default, anybody can read from the server and nobody can write to it by default. Set the ``web.allow_push`` option to ``*`` to allow everybody to push to the server. You should use a real web server if you need to authenticate users. By default, the server logs accesses to stdout and errors to stderr. Use the -A/--accesslog and -E/--errorlog options to log to diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -1921,16 +1921,28 @@ The full set of options is: Whether to recurse into subrepositories when archiving. (default: False) ``baseurl`` Base URL to use when publishing URLs in other locations, so third-party tools like email notification hooks can construct URLs. Example: ``http://hgserver/repos/``. +``browser`` + Web browser to open when starting a HTTP server via ``hg serve``. + + Value is one of the browser type names accepted by the Python + ``webbrowser`` module (run ``pydoc webbrowser`` to see choices). + Common values include ``firefox`` and ``chrome``. + + By default, the system default browser will be used. + + The value can be empty or ``none`` to disable the behavior of + automatically starting a browser. + ``cacerts`` Path to file containing a list of PEM encoded certificate authority certificates. Environment variables and ``~user`` constructs are expanded in the filename. If specified on the client, then it will verify the identity of remote HTTPS servers with these certificates. To disable SSL verification temporarily, specify ``--insecure`` from diff --git a/mercurial/hgweb/__init__.py b/mercurial/hgweb/__init__.py --- a/mercurial/hgweb/__init__.py +++ b/mercurial/hgweb/__init__.py @@ -4,16 +4,17 @@ # Copyright 2005 Matt Mackall <mpm@selenic.com> # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from __future__ import absolute_import import os +import webbrowser from ..i18n import _ from .. import ( error, util, ) @@ -73,24 +74,61 @@ class httpservice(object): fqaddr = self.httpd.fqaddr if ':' in fqaddr: fqaddr = '[%s]' % fqaddr if self.opts['port']: write = self.ui.status else: write = self.ui.write - write(_('listening at http://%s%s/%s (bound to %s:%d)\n') % - (fqaddr, port, prefix, bindaddr, self.httpd.port)) + self.url = 'http://%s%s/%s' % (fqaddr, port, prefix) + write(_('listening at %s (bound to %s:%d)\n') % + (self.url, bindaddr, self.httpd.port)) self.ui.flush() # avoid buffering of status message def run(self): + self._maybestartbrowser() self.httpd.serve_forever() + def _maybestartbrowser(self): + # If browser option is present and it isn't a special value "none", + # start the browser. + browser = self.opts.get('browser') + if browser: + if browser == 'none': + return + + # Otherwise, start a browser if in interactive mode, not starting + # a daemon, and the config option hasn't been set to stop this behavior. + else: + if not self.opts.get('interactive') or self.opts.get('daemon'): + return + + browser = self.ui.config('web', 'browser', None) + if browser == 'none' or (not browser and browser is not None): + return + + try: + browser = webbrowser.get(browser) + # Text-mode browsers block the calling process, which interferes + # with our server. + if (not isinstance(browser, webbrowser.BackgroundBrowser) and + not getattr(browser, 'background', None)): + self.ui.warn(_('(cannot start text-mode browsers; ' + 'continuing to start server)\n')) + return + browser.open_new_tab(self.url) + except webbrowser.Error as e: + self.ui.warn(_('(unable to start web browser: %s)\n') % e.args[0]) + def createservice(ui, repo, opts): + # Stash away whether UI is interactive so we can query it later + # to determine whether to start a web browser. + opts['interactive'] = ui.interactive() + # this way we can check if something was given in the command-line if opts.get('port'): opts['port'] = util.getport(opts.get('port')) alluis = set([ui]) if repo: baseui = repo.baseui alluis.update([repo.baseui, repo.ui]) diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -149,16 +149,17 @@ Show the global options -q -v -y Show the options for the "serve" command $ hg debugcomplete --options serve | sort --accesslog --address + --browser --certificate --cmdserver --config --cwd --daemon --daemon-postexec --debug --debugger @@ -214,17 +215,17 @@ Show all commands + options export: output, switch-parent, rev, text, git, nodates forget: include, exclude init: ssh, remotecmd, insecure log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude merge: force, rev, preview, tool pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure remove: after, force, subrepos, include, exclude - serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate + serve: accesslog, browser, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template summary: remote update: clean, check, date, rev, tool addremove: similarity, subrepos, include, exclude, dry-run archive: no-decode, prefix, rev, type, subrepos, include, exclude backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user bisect: reset, good, bad, skip, extend, command, noupdate bookmarks: force, rev, delete, rename, inactive, template