pkg-config、pacman.conf の Pygments lexer

もう練習はいいんじゃないか、とっとと本題に入れ、って声がきこえてきそうだ。

pkg-config なんてどれも小さいので、読みにくくて困る人なんか絶対に皆無(あるいは bash lexer で我慢出来る)だし、pacman.conf だって ini ファイル用の lexer でだいたいは満足出来るはずなので、どっちも需要ないと思いますの。強いていえば、pkg-config ファイルを大量に一気に読みたい人向け、だし、人の pacman.conf を読んで理解したい人(または pacman.conf の説明をしたい人)向け、ね。

pacman.conf を BitBucket とかで管理したい人は一定数いそうな気がするけど、pkg-config は絶対いないな。自分の PC 内の pkg-config を「読みたい人」もあんましいないと思うし。(pkg-config コマンド、を使いたいんであって、その設定を知りたいわけではないからね、フツー。だいたいにしてこれを書くのはパッケージの作者であって、ユーザが保守するもんではない。)

例によって「本当に欲しいが重量級」な lex/yacc/texinfo/m4 (と最近 SMTP ヘッダも仲間入り)の前の軽めのエクササイズな。

出来上がったのはこんなです:

  1 # -*- coding: utf-8 -*-
  2 """
  3     pygments.lexers.configs_pkgmng
  4     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5 
  6     Lexers for package manager configuration file formats.
  7 
  8     :copyright: Copyright 2006-2015 by the Pygments team, see AUTHORS.
  9     :license: BSD, see LICENSE for details.
 10 """
 11 
 12 import re
 13 
 14 from pygments.lexer import RegexLexer, bygroups, include, words
 15 from pygments.token import Text, Comment, Operator, Name, \
 16     Punctuation, String, Keyword
 17 
 18 __all__ = ['PkgConfigLexer', 'PacmanConfLexer']
 19 
 20 
 21 class PkgConfigLexer(RegexLexer):
 22     """
 23     Lexer for `pkg-config
 24     <http://www.freedesktop.org/wiki/Software/pkg-config/>`_
 25     (see also `manual page <http://linux.die.net/man/1/pkg-config>`_).
 26 
 27     .. versionadded:: 2.1
 28     """
 29 
 30     name = 'PkgConfig'
 31     aliases = ['pkgconfig',]
 32     filenames = ['*.pc',]
 33     mimetypes = []
 34 
 35     tokens = {
 36         'root': [
 37             (r'#.*$', Comment.Single),
 38 
 39             # variable definitions
 40             (r'^(\w+)(=)', bygroups(Name.Attribute, Operator)),
 41 
 42             # keyword lines
 43             (r'^([\w\.]+)(:)',
 44              bygroups(Name.Tag, Punctuation), 'spvalue'),
 45 
 46             # variable references
 47             include('interp'),
 48 
 49             # fallback
 50             (r'.', Text),
 51         ],
 52         'interp': [
 53             # you can escape literal "${" as "$${"
 54             (r'\$\$\{', Text),
 55 
 56             # variable references
 57             (r'\$\{', String.Interpol, 'curly'),
 58         ],
 59         'curly': [
 60             (r'\}', String.Interpol, '#pop'),
 61             (r'\w+', Name.Attribute),
 62         ],
 63         'spvalue': [
 64             include('interp'),
 65 
 66             (r'#.*$', Comment.Single, '#pop'),
 67             (r'\n', Text, '#pop'),
 68 
 69             # fallback
 70             (r'.', Text),
 71         ],
 72     }
 73 
 74 
 75 class PacmanConfLexer(RegexLexer):
 76     """
 77     Lexer for `pacman.conf
 78     <https://www.archlinux.org/pacman/pacman.conf.5.html>`_.
 79 
 80     Actually, IniLexer works almost fine for this format,
 81     but it yield error token. It is because pacman.conf has
 82     a form without assignment like:
 83 
 84         UseSyslog
 85         Color
 86         TotalDownload
 87         CheckSpace
 88         VerbosePkgLists
 89 
 90     These are flags to switch on.
 91 
 92     .. versionadded:: 2.1
 93     """
 94 
 95     name = 'PacmanConf'
 96     aliases = ['pacmanconf',]
 97     filenames = ['pacman.conf',]
 98     mimetypes = []
 99 
100     tokens = {
101         'root': [
102             # comment
103             (r'#.*$', Comment.Single),
104 
105             # section header
106             (r'^\s*\[.*?\]\s*$', Keyword),
107 
108             # variable definitions
109             # (Leading space is allowed...)
110             (r'(\w+)(\s*)(=)',
111              bygroups(Name.Attribute, Text, Operator)),
112 
113             # flags to on
114             (r'^(\s*)(\w+)(\s*)$',
115              bygroups(Text, Name.Attribute, Text)),
116 
117             # built-in special values
118             (words((
119                 '$repo',  # repository
120                 '$arch',  # architecture
121                 '%o',     # outfile
122                 '%u',     # url
123                 ), suffix=r'\b'),
124              Name.Variable),
125             
126             # fallback
127             (r'.', Text),
128         ],
129     }

もうアタシの WordPress 環境に取り込んでしまったので使えてます。

pkg-config のほう:

pkgconfig_example.pc
 1 # This is for a fictional package `yet another portable hatchpotch generator'.
 2 prefix=/usr/local/opt/site/private # define variable `prefix`
 3 exec_prefix=${prefix} # using variable reference
 4 libdir=${exec_prefix}/lib
 5 includedir=${prefix}/include
 6 just_for_test=$${this is not a part of variable reference} # escape with `$${`
 7 
 8 Name: YAPHatchPotchGen
 9 Description: Yet Another Portable HatchPotch GENerator.
10 Version: 352.9.3
11 URL: http://www9.yaphatchpotchgen.net  # Don't access.
12 Requires: piyohogelib-9.0 = 9.5.3
13 Requires.private: nyorolib-3.0 = 3.0.9
14 Conflicts: apiyohoge <= 8.3
15 Libs: -L${libdir} -lyaphatchpotchgen-352.9 # using variable reference
16 Libs.private: -ll -ly
17 Cflags: -I${includedir}/piyohogelib-9.0 -I${libdir}/yaphatchpotchgen/include

pacman.conf のほう:

pacman.conf
 1 #
 2 # /etc/pacman.conf
 3 #
 4 # This example file has no relation to `pacman.ijs`
 5 # but is of configuration of Arch Linux's package manager `pacman`.
 6 #
 7 
 8 #
 9 # GENERAL OPTIONS
10 #
11 [options]
12 RootDir     = /opt/local/site-private
13 #DBPath      = /var/lib/pacman/
14 #CacheDir    = /var/cache/pacman/pkg/
15 LogFile     = /opt/local/site-private/var/log/pacman.log
16 #GPGDir      = /etc/pacman.d/gnupg/
17 HoldPkg      = pacman
18 #XferCommand = /usr/bin/curl -C - -f %u > %o
19 XferCommand = /usr/local/bin/wget --passive-ftp -c -O %o %u
20 #CleanMethod = KeepInstalled
21 #UseDelta    = 0.7
22 Architecture = auto
23 
24 #IgnorePkg   =
25 #IgnoreGroup =
26 
27 NoUpgrade = etc/passwd etc/group etc/shadow
28 NoUpgrade = etc/fstab
29 #NoExtract   =
30 
31 #UseSyslog
32 Color
33 #TotalDownload
34 CheckSpace
35 #VerbosePkgLists
36 
37 #SigLevel = Never
38 SigLevel    = Required DatabaseOptional
39 LocalFileSigLevel = Optional
40 RemoteFileSigLevel = Required
41 
42 Server = ftp://ftp9.yaphatchpotchgen.net/$repo/os/$arch
43 
44 [fubar32]
45 Include = /etc/pacman.d/mirrorlist.fubar32 # comment is allowed here
46 
47 #[custom]
48 #SigLevel = Optional TrustAll
49 #Server = file:///home/custompkgs













っと、なんの前置きもなしに書いちゃったけれども。どっちも Unix 系の「パッケージマネージャ」の設定ファイルです。

前者はまぁまぁ歴史が古くて、記憶では10年くらいは経ってると思う。学生時代にはなかったので、なんとなくワタシにとっては「新しいもの」のイメージもいまだにあったりもするけど。WikiPedia によれば「Initial release 2006」。そうそう、だいたい記憶と合ってたわ。後者はワタシは MSYS2 で初めて知ったが、Arch Linux のパッケージマネージャなんだね、元々。

ところで「pacman」検索すれば当然「アレ」がヒットしてきます。そりゃそーだ。そしてだ。lexer のサンプルファイルを作るので気付いたんだけれども、pygments lexer の tests/examplefiles にこんなのが。J 言語で pacman を実装…してるのかな?