2018年5月28日月曜日

helm-default-display-bufferの変更で手元のhelm-swoopが使用不能になったので修正

2018-05-28現在の最新のhelmにupdateした所、helm-swoopが
Symbol's value as variable is void: helm-swoop-pattern
なるerrorを吐くようになったので原因を調べてみた。

順当にhelm-swoopのgithubのpageを見てみる


今年(2018)の1/22に:

cf. [Symbol's value as variable is void: helm-swoop-pattern · Issue #123 · ShingoFukuyama/helm-swoop](https://github.com/ShingoFukuyama/helm-swoop/issues/123)

そのものずばりのtitleのissueがfileされている。この中で触れられているように、helmのcoreの方でhelm-default-display-bufferに修正が入って、それが影響しているとのこと。その後のdiffなどを見ている限り、vanillaのまま使っているなら対応済みのようだ。

原因と対策


個人的には、helm-swoop実行時にfull widthで表示させるために、問題になっているhelm-swoop-split-window-functionを自前で設定していたのが原因でerrorが出ていた。helm-default-display-bufferの変更に合わせて適当にargumentを追加しておく:

*** before ***

-  (setq helm-swoop-split-window-function
- '(lambda (buffer)
-    (helm-default-display-buffer buffer)))

*** after ***

+  (setq helm-swoop-split-window-function
+ '(lambda (buffer &optional resume)
+    (helm-default-display-buffer buffer)))

もしかしたら&optional resumeじゃなくて&rest resumeにしておいた方が、今後またargumentsに変更があった時に対応しやすいかもしれない。

おまけ1. 原因の特定の仕方


*scratch* bufferで:

(setq debug-on-error t)
(setq helm-swoop-pattern "")

などとお膳立てした後に徐にhelm-swoopを起動するとbacktraceが見られる。

自前の設定が問題だというのはこれで分かった。

おまけ2. helm-occur


helm-swoopはとても便利に使っているが、そのalternativeとなるものも存在している。その一つがhelm-occurで、helm-occurを実行する他に、isearchからもhelm-occur-from-isearchを使えば呼び出せる。

helm-swoopはメンテの頻度が低いとか (だからと言って本家にも取り込まれなさそうだ)、実行速度に問題があるとしてhelm-occurを勧める向きもある。機能の全てではないにしろ、候補の選択に伴ってcursor positionも移動するような設定も可能みたいなので一応紹介はしておく。

ちなみに設定すればmigemoも使える。


2018年5月26日土曜日

hg infoをMercurial 4.6に対応させる

Mercurial 4.6に更新されたために色々な部分が変更された (cf. [WhatsNew - Mercurial](https://www.mercurial-scm.org/wiki/WhatsNew))。

現在のMercurial repositoryに関する情報を表示するhg info (cf. [InfoExtension - Mercurial](https://www.mercurial-scm.org/wiki/InfoExtension))というextensionを導入しているのだが、4.6へのupgradeに伴ってerrorを吐くようになったので修正。

原因は2つある:

1. cmdutil.commandが削除された
2. changectx()の仕様変更

cmdutilの仕様変更への対処


changeset:   37957:fb0de0bcd297
user:        Matt Harbison <matt_harbison@yahoo.com>
date:        Thu May 10 21:53:48 2018 -0400
summary:     cmdutil: drop deprecated precursor of registrar.command (API)
diff -r f1f8b655da32 -r fb0de0bcd297 mercurial/cmdutil.py
--- a/mercurial/cmdutil.py      Fri May 11 00:53:29 2018 -0400
+++ b/mercurial/cmdutil.py      Thu May 10 21:53:48 2018 -0400
@@ -37,7 +37,6 @@
     patch,
     pathutil,
     pycompat,
-    registrar,
     revlog,
     rewriteutil,
     scmutil,
@@ -3151,12 +3150,6 @@
         if f in copied:
             repo.dirstate.copy(copied[f], f)

-class command(registrar.command):
-    """deprecated: used registrar.command instead"""
-    def _doregister(self, func, name, *args, **kwargs):
-        func._deprecatedregistrar = True  # flag for deprecwarn in extensions.p
y
-        return super(command, self)._doregister(func, name, *args, **kwargs)
-
 # a list of (ui, repo, otherpeer, opts, missing) functions called by
 # commands.outgoing.  "missing" is "missing" of the result of
 # "findcommonoutgoing()"
diff -r f1f8b655da32 -r fb0de0bcd297 mercurial/extensions.py
--- a/mercurial/extensions.py   Fri May 11 00:53:29 2018 -0400
+++ b/mercurial/extensions.py   Thu May 10 21:53:48 2018 -0400
@@ -145,9 +145,6 @@
     """Check if extension commands have required attributes"""
     for c, e in cmdtable.iteritems():
         f = e[0]
-        if getattr(f, '_deprecatedregistrar', False):
-            ui.deprecwarn("cmdutil.command is deprecated, use "
-                          "registrar.command to register '%s'" % c, '4.6')
         missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)]
         if not missing:
             continue
diff -r f1f8b655da32 -r fb0de0bcd297 tests/test-extension.t
--- a/tests/test-extension.t    Fri May 11 00:53:29 2018 -0400
+++ b/tests/test-extension.t    Thu May 10 21:53:48 2018 -0400
@@ -1697,10 +1697,6 @@
   >     pass
   > EOF

-  $ hg --config extensions.nonregistrar=`pwd`/nonregistrar.py version > /dev/nu
ll
-  devel-warn: cmdutil.command is deprecated, use registrar.command to register
'foo'
-  (compatibility will be dropped after Mercurial-4.6, update your code.) * (glo
b)
-
 Prohibit the use of unicode strings as the default value of options

   $ hg init $TESTTMP/opt-unicode-default

代わりにregistrar.commandを使えとあるので書き換えた。

- from mercurial import cmdutil
+ from mercurial import registrar

- command = cmdutil.command(cmdtable)
+ command = registrar.command(cmdtable)

changectx()の仕様変更への対処


changeset:   37852:8b86acc7aa64
user:        Martin von Zweigbergk <martinvonz@google.com>
date:        Sat Apr 28 23:16:41 2018 -0700
summary:     context: drop support for looking up context by ambiguous changeid
(API)
... 
-def changectxdeprecwarn(repo):
-    # changectx's constructor will soon lose support for these forms of
-    # changeids:
-    #  * stringinfied ints
-    #  * bookmarks, tags, branches, and other namespace identifiers
-    #  * hex nodeid prefixes
-    #
-    # Depending on your use case, replace repo[x] by one of these:
-    #  * If you want to support general revsets, use scmutil.revsingle(x)
-    #  * If you know that "x" is a stringified int, use repo[int(x)]
-    #  * If you know that "x" is a bookmark, use repo._bookmarks.changectx(x)
-    #  * If you know that "x" is a tag, use repo[repo.tags()[x]]
-    #  * If you know that "x" is a branch or in some other namespace,
-    #    use the appropriate mechanism for that namespace
-    #  * If you know that "x" is a hex nodeid prefix, use
-    #    repo[scmutil.resolvehexnodeidprefix(repo, x)]
-    #  * If "x" is a string that can be any of the above, but you don't want
-    #    to allow general revsets (perhaps because "x" may come from a remote
-    #    user and the revset may be too costly), use scmutil.revsymbol(repo, x)
-    #  * If "x" can be a mix of the above, you'll have to figure it out
-    #    yourself
-    repo.ui.deprecwarn("changectx.__init__ is getting more limited, see "
-                       "context.changectxdeprecwarn() for details", "4.6",
-                       stacklevel=4)

それぞれ以下のように対応した:

-    ui.write(_("Base Hash: %s [hg id -r0]\n") % (hex(repo.changectx(0).node()),))
+    ui.write(_("Base Hash: %s [hg id -r0]\n") % (hex(repo.changelog.node(0)),))

changectx().node()が削除されたので、changelog.node()に変更。

-    ui.write(_("Files: %s [hg manifest | wc -l]\n") % (len(repo.changectx(numrev-1).manifest()),))
+    ui.write(_("Files: %s [hg manifest | wc -l]\n") % (len(repo[numrev-1].manifest()),))

changectx().manifest()が削除されたので、repo[].manifest()に変更。


まとめ


--- info.py.orig 2018-05-26 15:23:14.524041991 +0900
+++ info.py 2018-05-26 15:23:25.523203385 +0900
@@ -7,9 +7,15 @@
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.

+from mercurial import registrar
 from mercurial.i18n import _
 from mercurial.node import short, hex

+cmdtable = {}
+command = registrar.command(cmdtable)
+
+@command('info')
+
 def info(ui, repo):
     """Print information about the repository"""
     try:
@@ -18,17 +24,11 @@
         numrev = len(repo)

     ui.write(_("Repository: %s [hg root]\n") % (repo.root,))
-    ui.write(_("Base Hash: %s [hg id -r0]\n") % (hex(repo.changectx(0).node()),))
+    ui.write(_("Base Hash: %s [hg id -r0]\n") % (hex(repo.changelog.node(0)),))
     ui.write(_('Revisions: %s [hg tip --template "{rev}"]\n') % (numrev,))
-    ui.write(_("Files: %s [hg manifest | wc -l]\n") % (len(repo.changectx(numrev-1).manifest()),))
+    ui.write(_("Files: %s [hg manifest | wc -l]\n") % (len(repo[numrev-1].manifest()),))
     ui.write(_("Cloned From: %s [hg paths default]\n") % (ui.config('paths','default'),))
     default_push = ui.config('paths','default-push')
     if default_push:
         ui.write(_("Push To: %s [hg paths default-push]\n") % (default_push,))

-
-cmdtable = {
-    # "command-name": (function-call, options-list, help-string)
-    "info": (info, [], _("hg info"))
-}
-

Links


* [MercurialApi - Mercurial](https://www.mercurial-scm.org/wiki/MercurialApi)