定制Powerline的显示内容

本文内容承接《安装Powerline并配置Vim、Bash、tmux、IPython、pdb · 零壹軒·笔记》,介绍Powerline显示内容的定制方法。

Powerline自定义配置

Powerline的配置,普遍采用JSON格式。 内容集中在安装目录、或Git仓库的config_files下。 它默认使用安装位置的这个配置,但优先使用.config/powerline下的配置,是常见的个人配置覆盖默认配置的模式。

cp -r config_files ~/.config/powerline

先复制,再修改。

config.json是总配置入口,colors.jsoncolorschemes/目录都是和配色相关,一般人不需要修改。 因此,只有themes/目录是需要修改的。 通常,只有Bash和tmux需要修改,其它如Vim、IPython等,基本上没有修改的必要。 所以,其实只需要改两个文件,也可以只复制、修改这两个文件。 后面会展示这两个文件,并给出修改指导。

默认Bash配置

powerline/config_files/themes/shell/default.json内容如下:

{
  "segments": {
    "left": [
      {
        "function": "powerline.segments.shell.mode"
      },
      {
        "function": "powerline.segments.common.net.hostname",
        "priority": 10
      },
      {
        "function": "powerline.segments.common.env.user",
        "priority": 30
      },
      {
        "function": "powerline.segments.common.env.virtualenv",
        "priority": 50
      },
      {
        "function": "powerline.segments.shell.cwd",
        "priority": 10
      },
      {
        "function": "powerline.segments.shell.jobnum",
        "priority": 20
      }
    ],
    "right": [
      {
        "function": "powerline.segments.shell.last_pipe_status",
        "priority": 10
      },
      {
        "function": "powerline.segments.common.vcs.stash",
        "priority": 50
      },
      {
        "function": "powerline.segments.common.vcs.branch",
        "priority": 40
      }
    ]
  }
}

这个配置其实很有问题,虽然zsh等其它shell可以支持右侧显示,但Bash是没有right的。 所以,所有right的配置在Bash中都无法显示。 至少要把他们都放到left里,否则就丧失了这部分功能。

状态栏内容调整

在调整Bash的配置前,需要先了解它的含义。 以下是shell配置各部分的含义。

# Theme file
{
    "segments": {
        "above": [
            {
                "left": [
                    # First line left segments
                ],
                "right": [
                    # First line right segments
                ]
            },
            {
                # Same for second line
            }
        ],
        "left": [
            # Usual last line segments
        ],
        "right": [
            # Usual last line right segments
        ]
    }
}

其中,注释部分在终端中的位置如下:

First line left segments >   < First line right segments
Second line left segments >  < Second line right segments
Left segments > Typed text               < Right segments

对Bash来说,right部分是无效的。 因此只能配置left部分。

Shell的提示符可以是多行的。 虽然使用\n也能达到类似的效果,但还是推荐使用这里的多行配置。

tmux默认配置

{
  "segments": {
    "right": [
      {
        "function": "powerline.segments.common.sys.uptime",
        "priority": 50
      },
      {
        "function": "powerline.segments.common.sys.system_load",
        "priority": 50
      },
      {
        "function": "powerline.segments.common.time.date"
      },
      {
        "function": "powerline.segments.common.time.date",
        "name": "time",
        "args": {
          "format": "%H:%M",
          "istime": true
        }
      },
      {
        "function": "powerline.segments.common.net.hostname"
      }
    ]
  }
}

tmux的状态栏一般是单行,并且由于左半部分是Window列表,所以只能配置右半部分。

这里顺便说一下,Powerline的每一项展示,就是这里的一个JSON小对象。 其中,最主要的是function,代表你所展示的内容。 args是传参,对展示内容做微调。 比如这里的powerline.segments.common.time.date,默认仅展示日期,配置format"%H:%m"后,可展示时间。 这是一个官方组件,可以在文档中找到可支持的参数。

状态设计

在了解如何配置以后,也需要知道如何设计。 比如,孤某一时期的Bash与tmux内容如下:

Powerline in Bash (and tmux)

为什么做多行? 最大原因,是首行显示内容如果太多,剩余输入命令的位置会变少,反而不利于操作。 但是如果显示内容太少,也没有好的提示效果。 所以,把输入部分放在第二行,是解决这个矛盾的最佳方案。

为什么要显示日期与时间? 一个命令是什么时间执行的,执行了多长,有时也是很重要的。 与其通过其它手段,通过重复执行来测量,不如每次都记录下来,随时查阅。

把自己在使用时想知道的内容,放到Bash或tmux的状态栏中去,就可以提高效率。 Bash状态栏中可以展示命令相关内容,以及部分系统信息的快照。 tmux状态栏默认大约每2秒刷新一次,部分组件可设置为1秒,适合展示系统信息。

如何找到官方支持的状态信息(segment)? 在官网文档的Common segments页面,可以找到所有常见的segment。 其中,某些segment会需要额外安装一些pip包,比如系统和网络的:

sudo pip install psutil netifaces

除了本地组件,还有远程信息组件,比如邮件、天气等信息。 不过,这些组件都比较耗电,而且未必有用,因此需要根据实际需要,谨慎选择。 另外,其实还有一些官网上没写的组件,这只能看源码自己找了。

此外,除了segment,还有lister和selector两种展示项,但通常不需要了解。 lister是列出一些内容,比如Vim的Tab或tmux的Window,而selector是对列出内容的选择。

自定义组件

如果官方组件不过瘾,当然可以自定义组件。 在function中可以配置任何系统已安装的函数,所以自定义组件也就是开发一个Python软件包并安装到系统而已。 这部分内容是基本操作,略。

至于函数怎么写,也很简单。 比如官方的powerline.segments.common.time.date,内容如下:

def date(pl, format='%Y-%m-%d', istime=False, timezone=None):
    '''Return the current date.

    :param str format:
            strftime-style date format string
    :param bool istime:
            If true then segment uses ``time`` highlight group.
    :param string timezone:
            Specify a timezone to use as ``+HHMM`` or ``-HHMM``.
            (Defaults to system defaults.)

    Divider highlight group used: ``time:divider``.

    Highlight groups used: ``time`` or ``date``.
    '''

    try:
        tz = datetime.strptime(timezone, '%z').tzinfo if timezone else None
    except ValueError:
        tz = None

    nw = datetime.now(tz)

    try:
        contents = nw.strftime(format)
    except UnicodeEncodeError:
        contents = nw.strftime(format.encode('utf-8')).decode('utf-8')

    return [{
        'contents': contents,
        'highlight_groups': (['time'] if istime else []) + ['date'],
        'divider_highlight_group': 'time:divider' if istime else None,
    }]

这个函数,第一个入参PowerlineLogger,通常没用。 其它入参都是自定义的,自带默认值,也支持一些定制。 而返回值则是一个列表,内容则是展示项。

对自定义组件来说,只要写个函数,入参保留第一个,并且返回值满足以上格式即可。 当然,执行效率不要太差。

参考

此外,孤的Bash与tmux配置如下,仅供参考:


相关笔记