html/templateで key=val を出力する際は template.HTMLAttr型を使う
すごい久しぶりに goコードを書いたらいろいろと忘れていたのでメモ
templateに任意の属性を出力するようなコードを書きたかったが,
package main import ( "html/template" "log" "os" ) var htmlTemplate = ` <p {{.Attr}}> ` type Data struct { Attr string } func main() { t, err := template.New("test").Parse(htmlTemplate) if err != nil { log.Fatal(err) } d := Data{ Attr: `class="foo"`, } if err := t.Execute(os.Stdout, &d); err != nil { log.Fatal(err) } }
string
と宣言してしまうと下記のようになってしまう
<p ZgotmplZ>
どうするだと思って調べたところ template.HTMLAttr 型を使えばよかった
package main import ( "html/template" "log" "os" ) var htmlTemplate = ` <p {{.Attr}}> ` type Data struct { Attr template.HTMLAttr } func main() { t, err := template.New("test").Parse(htmlTemplate) if err != nil { log.Fatal(err) } d := Data{ Attr: `class="foo"`, } if err := t.Execute(os.Stdout, &d); err != nil { log.Fatal(err) } }
出力は以下のようになる
<p class="foo">
ドキュメントにあるように信頼できる入力に対してのみ使うべきで何でも使うべきではないので利用の際は注意が必要
use-packageで :vcキーワードが使えるようになった
開発版だけど, use-packageで :vc
キーワードがサポートされ標準のパッケージマネージャだけでも gitなどで管理されているパッケージも管理できるようになった. この機能がなかったため, やむおえず ここに書いたような設定を追加していたが:vc
キーワードサポートにより不要になった. 以下のように書けば ok. 詳しくは最新版を入れて info use-package
を参照してください.
(use-package editutil :vc (:url "https://github.com/syohex/emacs-editutil.git" :rev :newest) :config (editutil-default-setup) (set-face-attribute 'editutil-clean-space nil :foreground "purple") (set-face-attribute 'editutil-vc-branch nil :foreground "color-202" :weight 'extra-bold))
Ubuntu 23.04にアップデートしたら clangdが動かなくなった問題の対応
先日 Ubuntu 23.04にアップデートしたら clangdが動かなくなり, Emacsの eglotや VScodeの C++の補完等が一切効かなくなってしまった. その修正方法のメモ.
問題
clang, clang++が標準ヘッダファイルを見つけることができずファイルを解析できなくなってしまっていた.
原因
clang, clang++の include search pathが GCC 13のものになっており, GCC13がインストールされていないことが原因であった. clang++ -v
で確かめてみると, GCC13のヘッダファイルを見ていることが確認できる.
% clang++ -v test.cpp #include <...> search starts here: /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward /usr/lib/llvm-15/lib/clang/15.0.7/include /usr/local/include /usr/include/x86_64-linux-gnu /usr/include
なので gcc-13をインストールすることで問題は解消した
# gcc-13も入るので, g++を入れておく sudo apt install g++-13
しかし Ubuntu 23.04の標準の gccは 12だし, gcc 13はそもそもインストールしていなかったのにその場所を見るというのも変である.
自分の環境による問題かは不明だが, これで問題は解消し, eglotも VSCodeも問題はなくなった.
el-getから package.el + use-packageに移行した
Emacsをあまりヘビーに使っていないし、できれば標準のものだけで済ませたいと思ってパッケージマネージャを el-getから標準ツールに移行した。前から考えていたんだけど、MELPAなどに登録されていないパッケージをいくつか使っていてそれで el-get使っていたんだけど、Emacs29から use-packageが標準パッケージ化、さらに package-vc.elも加わり、使い勝手はさておき移行は可能になったので移行してみた。(el-getが開発中の Emacsで動かない問題がありそのパッチが全然マージされないなどの理由もある)
package-vcは以下のようなシグネチャで url
に git repositoryなどを渡せばそれをパッケージとして使える
(package-vc-install url rev nil name)
use-packageと組み合わせて使う
以下のような helperを用意し
(cl-defun from-github (&key repo name rev) (unless (package-installed-p name) (let ((url (format "https://github.com/%s" repo))) (package-vc-install url rev nil name))))
:init
でインストール済みかをチェックするようにしてそれっぽく使えるようにした
(use-package editutil :init (from-github :repo "syohex/emacs-editutil" :name 'editutil) :config (editutil-default-setup) (set-face-attribute 'editutil-clean-space nil :foreground "purple") (set-face-attribute 'editutil-vc-branch nil :foreground "color-202" :weight 'extra-bold))
とりあえず標準のパッケージマネジャーだけで必要なものだけはインストールできるようにはなった. まあただインストールが失敗することがあったり、使い勝手が el-getに比べると微妙な部分があるように思える. でもまあそこまでヘビーには使っていないのでひとまずこれでしばらくやってみる
2023 パズル in F#
他の人の回答などを見ずに愚直に解いてみたが全部を算出しようとすると遅すぎた.
type Opcode = | Add | Sub | Mul | Div type Operand = | Opcode of Opcode | Number of int let calculateRpnExpression (exp: Operand list) : Option<int> = let rec calculateRpnExpression' exp stack = match exp with | [] -> Some(List.head stack) | Number (n) :: t -> calculateRpnExpression' t (n :: stack) | Opcode (op) :: t -> match stack with | n2 :: n1 :: rest -> match op with | Add -> calculateRpnExpression' t ((n1 + n2) :: rest) | Sub -> calculateRpnExpression' t ((n1 - n2) :: rest) | Mul -> calculateRpnExpression' t ((n1 * n2) :: rest) | Div -> if n2 = 0 then None else calculateRpnExpression' t ((n1 / n2) :: rest) | _ -> printfn $"stack=${stack} exp=${exp}" failwith "never reach here" calculateRpnExpression' exp [] let normalizeRpnExpression (exp: Operand list) : string = let rec normalizeRpnExpression' exp stack = match exp with | [] -> List.head stack | Number (n) :: t -> normalizeRpnExpression' t ((string n) :: stack) | Opcode (op) :: t -> match stack with | v2 :: v1 :: rest -> match op with | Add -> normalizeRpnExpression' t ((sprintf "(%s+%s)" v1 v2) :: rest) | Sub -> normalizeRpnExpression' t ((sprintf "(%s-%s)" v1 v2) :: rest) | Mul -> normalizeRpnExpression' t ((sprintf "(%s*%s)" v1 v2) :: rest) | Div -> normalizeRpnExpression' t ((sprintf "(%s/%s)" v1 v2) :: rest) | _ -> failwith "never reach here" normalizeRpnExpression' exp [] let createRpnExpression (nums: int list) (target: int) = let len = nums |> List.length let limit = len * 2 - 1 let rec createRpnExpression' nums prevNum numCount opCount exp acc = if numCount + opCount >= limit then let exp' = List.rev exp match calculateRpnExpression exp' with | None -> acc | Some (v) -> if v = target then printfn "%A" (normalizeRpnExpression exp') exp' :: acc else acc else let acc' = if numCount - opCount >= 2 then let ops = if prevNum = 8 then [ Div ] else [ Add; Sub; Mul; Div ] ops |> List.fold (fun acc' op -> createRpnExpression' nums -1 numCount (opCount + 1) (Opcode(op) :: exp) acc') acc else acc if prevNum <> 8 && numCount < len then let n = List.head nums createRpnExpression' (List.tail nums) n (numCount + 1) opCount (Number(n) :: exp) acc' else acc' createRpnExpression' nums -1 0 0 [] [] let quiz2023 (nums: int list) (target: int) : string list = let rpnExpressions = createRpnExpression nums target rpnExpressions |> List.map normalizeRpnExpression
この本に単純な場合のものは載っているので全くわからない人は見ても良いかもしれません。
Ubuntu 22.10に handbrakeをflatpakで インストールする
大昔の DVD整理を今更やろうとして bandbrakeをインストールしようとしたが, apt版だと SEGVが出てしまい使えなかったので flatpakで最新版を入れる必要があった. flatpakを使ったことがなかったのでそのメモ
flatpakのインストール
sudo apt install flatpak
最新版の handbrakeを flatpakでインストール
flatpak install https://dl.flathub.org/repo/appstream/fr.handbrake.ghb.flatpakref
handbrakeを起動する
flatpak run fr.handbrake.ghb
clangdを使う際のメモ
最近ささっと C/C++書くとき, Emacsを使っているのだが, LSP serverとして clangdを使う際のメモ
Emacsの設定
Emacs開発版を使っているので, eglotをそのまま使う(C/C++ではデフォルトではサーバとして clangdが使われる)
(add-hook 'c-mode-hook #'eglot-ensure) (add-hook 'c++-mode-hook #'eglot-ensure)
1ファイルの場合
特に対応が不要. よしなし補完なりエラーを表示してくれる
ビルドファイルがあるような本格的なプロジェクトの場合
各種フラグをセットしていたり, include pathを指定しておく必要があるので compile_commands.json
を生成しておく必要がある. compile_commands.json
はファイルの親ディレクトリかそのいずれかのディレクトリにある build/
サブディレクトリ以下にある必要がある. なのでビルドディレクトリ名には注意が必要となる.
CMakeの場合
CMAKE_EXPORT_COMPILE_COMMANDS
というフラグがあるのでこれを onにしてビルドファイルを生成する
mkdir build/ cd build/ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=YES ..
Makefileの場合
compiledbや bear が Makefileから compile_commands.json
を生成することができるので利用する. 一応ビルドせずファイルを生成する機能があるが, 1度ビルドした方が無難なようである.
# compiledbの場合 compiledb make # bearの場合 bear -- make
これで補完やら定義元ジャンプやらが使えるようになる.