ソースコード(テキスト)を行番号付きでPDFにするプログラムです。あまり用途はなさ王ですが、pythonからPDFにする勉強のために作成しました。python3 code2pdf.py <ソースコード> -o <出力先> で動きます。
環境
- ubuntu 24
- python3
- python fpdf2
- Unicode フォント
Unicode フォントのインストール
広範囲のUnicodeをカバーする「No Tofu」フォントファミリーをインストールします。
sudo apt install fonts-noto-cjk
fpdf2 のインストール
pip install fpdf2
ソースコードをPDFに変換するプログラム
ヘッダとフッターを付けるためFPDFクラスを継承してPDFクラスを作成しました。
PDF クラス
PDFクラスのコンストラクタでUnicodeフォントを設定しています。ヘッダにファイル名、フッターにページ番号の表示が入ってます。
ファイルの読み込みとPDF化
ファイルを読み込んで、行番号をつけるために、1行ごとに処理をしています。
行番号をPDF出力してから読み込んだ行を出力しています。
fpdf2は、デフォルトで{nb}が総ページ数に置き換わるようになってました。ソースコードに「{nb}」があると総ページ数に置き換わるため、{nb}を{\0nb}に変換しました。どのように変換するのかが不明ですが、{\0nb}へ変換するので表示はできるようになりました。
もしかしたら、何が弊害があるかもしれませんが、とりあえずこれで進めました。
#!/usr/bin/env python3
import argparse
import fpdf
import os
import re
parser = argparse.ArgumentParser(description='Convert code to PDF')
parser.add_argument('file',
help='input file')
parser.add_argument('-o', '--output',
default='output.pdf',
help='output file (default is output.pdf)')
args = parser.parse_args()
class PDF(fpdf.FPDF):
def __init__(self, header_text):
self.header_text = header_text
super().__init__(orientation='portrait', unit='mm', format='A4')
self.set_margins(left=10, top=20, right=10)
self.set_auto_page_break(auto=True, margin=20)
self.add_font(
family='Noto Sans Mono CJK JP',
style='',
fname='/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc')
self.set_font('Noto Sans Mono CJK JP', size=8)
self.add_page()
def centering(self, y, text):
org_y = self.get_y()
self.set_y(y)
self.cell(w=0, text=text, align='C')
self.set_y(org_y)
def header(self):
self.centering(y=10,
text=self.header_text)
def footer(self):
self.centering(y=-10-self.font_size_pt/self.k,
text=f'Page {self.page_no()} of {{nb}}')
pdf = PDF(header_text=os.path.basename(args.file))
with open(args.file, 'r', encoding='utf-8') as f:
for i, line in enumerate(f.readlines(), start=1):
pdf.cell(w=10, h=None, text=f'{i}', align='R')
# Fixed an issue where "{nb}" was replaced with the total page number
line = re.sub(r'{nb}', '{\0nb}', line)
pdf.multi_cell(w=0, h=None, text=line, new_y='LAST')
pdf.output(args.output)
さいごに
少ないコードで、python からPDFを作成できるのが分かりました。何かの参考になればと思います。