Re: [PATCH] show: new extension for displaying various repository data

2017-03-24 Thread Jun Wu
Excerpts from Denis Laxalde's message of 2017-03-23 10:14:14 +0100:
> Ryan McElroy a écrit :
> > On 3/22/17 7:29 AM, Sean Farley wrote:
> >> Yuya Nishihara  writes:
> >>
> >>> On Sun, 12 Mar 2017 21:38:00 -0700, Gregory Szorc wrote:
>  # HG changeset patch
>  # User Gregory Szorc 
>  # Date 1489378362 25200
>  #  Sun Mar 12 21:12:42 2017 -0700
>  # Node ID d30057d358076cbe7d632cd573095af97543f932
>  # Parent  1c3352d7eaf24533ad52d4b8a024211e9189fb0b
>  show: new extension for displaying various repository data
> >>> The idea sounds nice to me. I just checked minor implementation details
> >>> about formatter.
> >> Just a quick reply (as I whittle down my backlog), but a lot of people
> >> (including myself) have a 'show' alias (inspired by 'git show').
> >>
> >> That may or may not be a factor in this.
> >
> > Greg called this out specifically in his excellent summary.
> >
> > FB also has a "show" extension that replaced our "show" alias:
> > https://bitbucket.org/facebook/hg-experimental/src/default/hgext3rd/show.py 
> 
> It seems to me that all "show" extensions/aliases can be replaced by the
> proposed extension. Also if we look to the future, it seems to me that

The problem is top-level command names are rare resources. It's really hard
to name things. I think subcommands is a great choice.

> we'd have hard time to explain that this command is not called "show"
> because there used to be extensions/aliases with this name and that got
> replaced by said command.

Another benefit of the "show" approach is it's supposed to be read-only.
It feels cleaner than for example "hg bookmark" which could do either read
or write.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] show: new extension for displaying various repository data

2017-03-22 Thread Ryan McElroy



On 3/22/17 7:29 AM, Sean Farley wrote:

Yuya Nishihara  writes:


On Sun, 12 Mar 2017 21:38:00 -0700, Gregory Szorc wrote:

# HG changeset patch
# User Gregory Szorc 
# Date 1489378362 25200
#  Sun Mar 12 21:12:42 2017 -0700
# Node ID d30057d358076cbe7d632cd573095af97543f932
# Parent  1c3352d7eaf24533ad52d4b8a024211e9189fb0b
show: new extension for displaying various repository data

The idea sounds nice to me. I just checked minor implementation details
about formatter.

Just a quick reply (as I whittle down my backlog), but a lot of people
(including myself) have a 'show' alias (inspired by 'git show').

That may or may not be a factor in this.


Greg called this out specifically in his excellent summary.

FB also has a "show" extension that replaced our "show" alias: 
https://bitbucket.org/facebook/hg-experimental/src/default/hgext3rd/show.py


Therefore, I would also slightly prefer "view", but I admit I don't care 
about hgk (even though we have it on at FB and it doesn't seem to work 
at all...)


I'll respond to the original as well so I can respond inline to the code 
and summary.

___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] show: new extension for displaying various repository data

2017-03-22 Thread Gregory Szorc
On Mon, Mar 13, 2017 at 7:21 PM, Yuya Nishihara  wrote:

> On Sun, 12 Mar 2017 21:38:00 -0700, Gregory Szorc wrote:
> > # HG changeset patch
> > # User Gregory Szorc 
> > # Date 1489378362 25200
> > #  Sun Mar 12 21:12:42 2017 -0700
> > # Node ID d30057d358076cbe7d632cd573095af97543f932
> > # Parent  1c3352d7eaf24533ad52d4b8a024211e9189fb0b
> > show: new extension for displaying various repository data
>
> The idea sounds nice to me. I just checked minor implementation details
> about formatter.
>
> > +@command('show', commands.formatteropts, _('[VIEW]'))
> > +def show(ui, repo, view=None, template=None):
> > +"""show various repository information
> > +
> > +A requested view of repository data is displayed.
> > +
> > +If no view is requested, the list of available views is shown.
> > +
> > +.. note::
> > +
> > +   The default output from this command is not covered under
> Mercurial's
> > +   default backwards-compatible mechanism (which puts an emphasis on
> > +   not changing behavior). This means output from this command may
> change
> > +   in any future release. However, the values fed to the formatter
> are
> > +   covered under the default backwards-compatible mechanism.
> > +
> > +   Automated consumers of this command should specify an explicit
> template
> > +   via ``-T/--template`` to guarantee output is stable.
> > +
> > +List of available views:
> > +
> > +"""
> > +views = showview._table
> > +
> > +if not view:
> > +ui.write(_('available views:\n'))
> > +ui.write('\n')
> > +
> > +for name, func in sorted(views.items()):
> > +ui.write(_('%s\n') % func.__doc__)
> > +
> > +ui.write('\n')
> > +raise error.Abort(_('no view requested'),
> > +  hint=_('use `hg show ` to choose a
> view'))
> > +
> > +if view not in views:
> > +raise error.Abort(_('unknown view: %s') % view,
> > +  hint=_('run `hg show` to see available
> views'))
> > +
> > +template = template or 'show'
> > +fmtopic = views[view]._formatter
> > +formatter = ui.formatter(fmtopic, {'template': template})
> > +
> > +return views[view](ui, repo, formatter)
>
> s/formatter/fm/ seems better for consistency. Also, I prefer calling
> fm.end()
> here as it should be paired with the construction.
>
>   with ui.formatter(...) as fm:
>   return views[view](...)
>
> > +@showview('bookmarks', formatter='bookmarks')
>
> s/formatter=/topic=/ or /fmtopic=/ ?
>
> If this 'bookmarks' template can't be compatible with the default template
> used by "hg bookmarks" command, we'll need another topic name.
>
> > +def showbookmarks(ui, repo, fm):
> > +"""bookmarks and their associated changeset"""
> > +marks = repo._bookmarks
> > +if not len(marks):
> > +ui.write_err('(no bookmarks set)\n')
> > +return 0
>
> If this is an error, it should error out. Otherwise, use fm.plain().
>

fm.plain() no-ops when using templateformatter though.

I'm not sure what to do here. We probably want a message printed to the
user without an error exit code. So I'm going to keep this as ui.write() in
V2 and you can suggest a workaround.


>
> > +active = repo._activebookmark
> > +longest = max(len(b) for b in marks)
> > +
> > +for bm, node in sorted(marks.items()):
> > +fm.startitem()
> > +fm.write('bookmark', '%s', bm)
> > +fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
> > +fm.data(ctx=repo[node],
> > +active=bm == active,
> > +longestlen=longest)
>
> As changectx can't be serialized, it shouldn't be passed to e.g.
> jsonformatter.
> fm.context(ctx=repo[node]) can be used. It's unfortunate that 'longestlen'
> appears in JSON output, but I have no better idea other than abusing
> fm.context().
>

I have an idea. I may test the waters in V2.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] show: new extension for displaying various repository data

2017-03-14 Thread Yuya Nishihara
On Sun, 12 Mar 2017 21:38:00 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc 
> # Date 1489378362 25200
> #  Sun Mar 12 21:12:42 2017 -0700
> # Node ID d30057d358076cbe7d632cd573095af97543f932
> # Parent  1c3352d7eaf24533ad52d4b8a024211e9189fb0b
> show: new extension for displaying various repository data

The idea sounds nice to me. I just checked minor implementation details
about formatter.

> +@command('show', commands.formatteropts, _('[VIEW]'))
> +def show(ui, repo, view=None, template=None):
> +"""show various repository information
> +
> +A requested view of repository data is displayed.
> +
> +If no view is requested, the list of available views is shown.
> +
> +.. note::
> +
> +   The default output from this command is not covered under Mercurial's
> +   default backwards-compatible mechanism (which puts an emphasis on
> +   not changing behavior). This means output from this command may change
> +   in any future release. However, the values fed to the formatter are
> +   covered under the default backwards-compatible mechanism.
> +
> +   Automated consumers of this command should specify an explicit 
> template
> +   via ``-T/--template`` to guarantee output is stable.
> +
> +List of available views:
> +
> +"""
> +views = showview._table
> +
> +if not view:
> +ui.write(_('available views:\n'))
> +ui.write('\n')
> +
> +for name, func in sorted(views.items()):
> +ui.write(_('%s\n') % func.__doc__)
> +
> +ui.write('\n')
> +raise error.Abort(_('no view requested'),
> +  hint=_('use `hg show ` to choose a view'))
> +
> +if view not in views:
> +raise error.Abort(_('unknown view: %s') % view,
> +  hint=_('run `hg show` to see available views'))
> +
> +template = template or 'show'
> +fmtopic = views[view]._formatter
> +formatter = ui.formatter(fmtopic, {'template': template})
> +
> +return views[view](ui, repo, formatter)

s/formatter/fm/ seems better for consistency. Also, I prefer calling fm.end()
here as it should be paired with the construction.

  with ui.formatter(...) as fm:
  return views[view](...)

> +@showview('bookmarks', formatter='bookmarks')

s/formatter=/topic=/ or /fmtopic=/ ?

If this 'bookmarks' template can't be compatible with the default template
used by "hg bookmarks" command, we'll need another topic name.

> +def showbookmarks(ui, repo, fm):
> +"""bookmarks and their associated changeset"""
> +marks = repo._bookmarks
> +if not len(marks):
> +ui.write_err('(no bookmarks set)\n')
> +return 0

If this is an error, it should error out. Otherwise, use fm.plain().

> +active = repo._activebookmark
> +longest = max(len(b) for b in marks)
> +
> +for bm, node in sorted(marks.items()):
> +fm.startitem()
> +fm.write('bookmark', '%s', bm)
> +fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
> +fm.data(ctx=repo[node],
> +active=bm == active,
> +longestlen=longest)

As changectx can't be serialized, it shouldn't be passed to e.g. jsonformatter.
fm.context(ctx=repo[node]) can be used. It's unfortunate that 'longestlen'
appears in JSON output, but I have no better idea other than abusing
fm.context().
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] show: new extension for displaying various repository data

2017-03-12 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1489378362 25200
#  Sun Mar 12 21:12:42 2017 -0700
# Node ID d30057d358076cbe7d632cd573095af97543f932
# Parent  1c3352d7eaf24533ad52d4b8a024211e9189fb0b
show: new extension for displaying various repository data

Currently, Mercurial has a number of commands to show information. And,
there are features coming down the pipe that will introduce more
commands for showing information.

Currently, when introducing a new class of data or a view that we
wish to expose to the user, the strategy is to introduce a new command
or overload an existing command, sometimes both. For example, there is
a desire to formalize the wip/smartlog/underway/mine functionality that
many have devised. There is also a desire to introduce a "topics"
concept. Others would like views of "the current stack." In the
current model, we'd need a new command for wip/smartlog/etc (that
behaves a lot like a pre-defined alias of `hg log`). For topics,
we'd likely overload `hg topic[s]` to both display and manipulate
topics.

Adding new commands for every pre-defined query doesn't scale well
and pollutes `hg help`. Overloading commands to perform read-only and
write operations is arguably an UX anti-pattern: while having all
functionality for a given concept in one command is nice, having a
single command doing multiple discrete operations is not. Furthermore,
a user may be surprised that a command they thought was read-only
actually changes something.

We discussed this at the Mercurial 4.0 Sprint in Paris and decided that
having a single command where we could hang pre-defined views of
various data would be a good idea. Having such a command would:

* Help prevent an explosion of new query-related commands
* Create a clear separation between read and write operations
  (mitigates footguns)
* Avoids overloading the meaning of commands that manipulate data
  (bookmark, tag, branch, etc) (while we can't take away the
  existing behavior for BC reasons, we now won't introduce this
  behavior on new commands)
* Allows users to discover informational views more easily by
  aggregating them in a single location
* Lowers the barrier to creating the new views (since the barrier
  to creating a top-level command is relatively high)

So, this commit introduces the `hg show` command via the "show"
extension. This command accepts a positional argument of the
"view" to show. New views can be registered with a decorator. To
prove it works, we implement the "bookmarks" view, which shows a
table of bookmarks and their associated nodes.

We introduce a new style to hold everything used by `hg show`.

For our initial bookmarks view, the output varies from `hg bookmarks`:

* Padding is performed in the template itself as opposed to Python
* Revision integers are not shown
* shortest() is used to display a 5 character node by default (as
  opposed to static 12 characters)

I chose to implement the "bookmarks" view first because it is simple
and shouldn't invite too much bikeshedding that detracts from the
evaluation of `hg show` itself. But there is an important point
to consider: we now have 2 ways to show a list of bookmarks. I'm not
a fan of introducing multiple ways to do very similar things. So it
might be worth discussing how we wish to tackle this issue for
bookmarks, tags, branches, MQ series, etc.

I also made the choice of explicitly declaring the default show
template not part of the standard BC guarantees. History has shown
that we make mistakes and poor choices with output formatting but
can't fix these mistakes later because random tools are parsing
output and we don't want to break these tools. Optimizing for human
consumption is one of my goals for `hg show`. So, by not covering
the formatting as part of BC, the barrier to future change is much
lower and humans benefit.

At the aforementioned Sprint, we discussed and discarded various
alternatives to `hg show`.

We considered making `hg log ` perform this behavior. The main
reason we can't do this is because a positional argument to `hg log`
can be a file path and if there is a conflict between a path name and
a view name, behavior is ambiguous. We could have introduced
`hg log --view` or similar, but we felt that required too much typing
(we don't want to require a command flag to show a view) and wasn't
very discoverable. Furthermore, `hg log` is optimized for showing
changelog data and there are things that `hg display` could display
that aren't changelog centric.

There were concerns about using "show" as the command name.

Some users already have a "show" alias that is similar to `hg export`.

There were also concerns that Git users adapted to `git show` would
be confused by `hg show`'s different behavior. The main difference
here is `git show` prints an `hg export` like view of the current
commit by default and `hg show` requires an argument. `git show`
can also display any Git object. `git show` does not support