怎样维护自己hack过的package

这样的话,本地的文件又自动下载到了.emacs.d里面吗?还有是否存在和已有layer的配置重复问题?

Spacemace 也支持 recipe 了,这是什么都要自己搞一套么。

非 Spacemacs 用户可以试试 el-get,它内置了大量的 recipe 可直接使用:

(el-get-bundle yasnippet)
(el-get-bundle color-moccur)

或者手动指定来源,来源可以是:

  • elpa
  • 文件 url
  • 代码仓库(git/svn/hg),并可以指定 commit。如果是 github 还可以省略网址前缀
;; Locally defined recipe
(el-get-bundle yaicomplete
  :url "https://github.com/tarao/elisp.git"
  :features yaicomplete)

;; With initialization code
(el-get-bundle zenburn-theme
  :url "https://raw.githubusercontent.com/bbatsov/zenburn-emacs/master/zenburn-theme.el"
  (load-theme 'zenburn t))

(el-get-bundle tarao/tab-group-el)
;; equivalent to
;; (el-get-bundle tab-group-el :type github :pkgname "tarao/tab-group-el")

(el-get-bundle gist:4468816:pit
;; equivalent to
;; (el-get-bundle pit :type git :url "http://gist.github.com/4468816.git")

(el-get-bundle elpa:undo-tree)
;; equivalent to
;; (el-get-bundle undo-tree :type elpa)

如果已有 layer 是 spacemacs 的,你也可以 fork 一份 spacemacs,然后修改那个 layer 的 recipe,令它指向你修改后的包。我现在用的 spacemacs 就是自己稍作修改的版本。

我用过recipe,是不是这样的:

    (package-name :location (recipe
                           :fetcher github
                           :repo "github-name/package-name"))

这样就要求package必须要上传到github了,我觉得应该是先在本地修改,改好了还要测试,测试通过才会push到github。 对于测试阶段,这种方法就不合适了吧?


擦,跟山人写的是一样的:sweat: @guanghui.qu

我看这还是文档里推荐的写法 Configuration layers @twlz0ne

如果已有 layer 是 spacemacs 的,你也可以 fork 一份 spacemacs,然后修改那个 layer 的 recipe,令它指向你修改后的包。我现在用的 spacemacs 就是自己稍作修改的版本。

如果想本地测试可以用 :location local,写完整就是:

(package-name :location local)

然后放到你的 private layer 中 local 文件夹下面,比如:

/my-private-layer/local/my-package/my-package.el

ps:这个文件夹是可以用 git 版本控制的。

1 个赞

有道理!听您这么讲,我感觉明朗了许多。

我在syl20bnr/spacemacs中搜索了一下google-translate, 发现其配置是在 spacemacs/layers/+spacemacs/spacemacs-language/packages.el里(话说有别的方法快速定位package所属的layer吗?):

(setq spacemacs-language-packages
      '((define-word :toggle (not (bound-and-true-p osx-use-dictionary-app)))
       google-translate))

您的意思是这样改吧:

(setq spacemacs-language-packages
      '((define-word :toggle (not (bound-and-true-p osx-use-dictionary-app)))
       (google-translate:location local)))

然后把google-translate 放在 .spacemacs.d/private/local/ 下面,单独用git控制,我看了一下.spacemacs.d下的.gitignore,它确实不控制private这个目录。

应该是

(google-translate :location local)

冒号的位置不对

但是这个 layer 不是 private layer,这样做应该不行的

应该是可以的,你参考一下 python layer,它用了几个 local package

哦,忘了空格了。

我先试试看

google-translate 好像是个多文件的包?

上面的方法好像只适用于单文件的包,多文件暂时还不支持。

但是我注意到最近有人 PR 解决了这一问题,只是暂时还没有 merge。你可以试用一下:

2 个赞

我靠,好复杂呀。。。。

自己 fork 一份不好和源 package 同步,我是用 with-eval-after-load 修改特定的代码

不建议直接改插件代码。用advice或其他手段修改。如果是bug就直接提issue,就算是feature request也不用顾虑。

2 个赞

确实,但是上面的方法也可以用于维护自己写的包,我就是这么干的。

其实不麻烦,可以两个本地分支 upstreammasterupstream 的 remote 设为上游 repo (比如我就将 upstream 的 remote 设为 spacemacs 的 develop 分支)。 master 分支作为你的主力分支,它的 remote 设为你 fork 的repo。每次 upstream 更新后,rebase 一下 master 分支就好了,用 magit 根本不费什么事。这样做还有一个好处就是方便向 spacemacs 提交 PR

因为 org 的代码太长了,我 hack org 的时候连 with-eval-after-load 也没用,直接用正则搜索替换。缺点是每次更新 org 后都要重新运行一下。不过我现在想想,是不是也应该 fork 一份 org-mode 到 github 上。

我说的就是,上游有更新,你得手动去更新,如果 hack 的包多了,很难和上游保持同步;用 with-eval-after-load 直接用 Spacemacs 的 update package 功能就可以了

请问能解释下advice手段吗?

“很难和上游保持同步”

我协作开发经验不足。请问如果自己hack的部分不合并到源分支(PR尚未被采纳是不是就是这种情况?),那是不是根本没法同步?应该存在冲突了吧

这是论坛中已有的范例。adviace用于在原函数运行前/后添加一些东西,也可以用来覆盖原函数,好处是随时控制是否开启 advice。详细用法请C-h f advice-add RET查看文档。

在有 hook 可以用的时候优先用hook,如无必要不建议在写 package 的时候用 advice。

2 个赞

如果是给上游提了 PR 并且被采用了,那就直接用 elpa 仓库里的包就好了,这就不存在同步和冲突的问题了;有写情况,比如需要对某个包做个定制,但是这个包没有提供需要的定制接口或者是自己的定制需求比较奇葩,这样的修改是个性化的,不太可能适合这个包的其他用户,所以这样的修改就不太好提 PR,这种情况有两个解决方法:

  1. with-eval-after-load 直接修改需要定制的部分
  2. fork 一份上游的源代码仓库,在 fork 的代码里做修改,然后像楼上几位提到的指定这个包的 location 为自己的 github fork repo。这样的缺点是你不知道上游什么时候有更新,当你得知上游有更新之后,也需要手动同步上游的代码到自己的 fork repo
1 个赞

另类是要付出代价的。。。