defstruct(構造体定義) について

common lisp の構造体の使い方がやっとわかったのでメモ

  • こんな感じで構造体を作ることができる
? (defstruct human
  (height 0)
  (weight 0))
HUMAN

? (make-human) ;; デフォルトのコンストラクタ名は make-<構造体名>
#S(HUMAN :HEIGHT 0 :WEIGHT 0)

? (make-human :height 999)
#S(HUMAN :HEIGHT 999 :WEIGHT 0)

? (make-human :weight 999)
#S(HUMAN :HEIGHT 0 :WEIGHT 999)

? (make-human :height 1 :weight 2)
#S(HUMAN :HEIGHT 1 :WEIGHT 2)
  • 引数 :constructor で 構造体を生成する関数名を指定することができる
?  (defstruct (keymap (:constructor aaa)) (a 1))
KEYMAP

? (aaa)
#S(KEYMAP :A 1)

? (aaa :a 100)
#S(KEYMAP :A 100)

? (make-keymap) ;; デフォルトの構造体コンストラクタは使えない
> Error: Undefined function MAKE-KEYMAP called with arguments () .
> While executing: CCL::TOPLEVEL-EVAL, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Retry applying MAKE-KEYMAP to NIL.
> Type :? for other options.
1 >
  • 引数 :print-function で渡した関数で表示方法を規定することができる
(defun print-hoge (hoge stream depth)
  (format stream "#hoge<~Ahoge>" (hoge-hoge hoge)))
;Compiler warnings :
;   In PRINT-HOGE: Undefined function HOGE-HOGE
;   In PRINT-HOGE: Unused lexical variable DEPTH
PRINT-HOGE

?  (defstruct (hoge (:print-function print-hoge)) (hoge 0))
HOGE

? (make-hoge)
#hoge<0hoge>

? (make-hoge :hoge 1000)
#hoge<1000hoge>

参考

qiita.com

素因数分解をしてみた

素因数分解をしてみたのでメモ

(defun primep-1 (n i)
    (cond
        ((> i (sqrt n)) T)
        ((zerop (mod n i)) nil)
        (t
            (primep-1 n (1+ i)))))
(defun primep (number)
    (primep-1 number 2))

(defun next-prime (n)
    (cond
        ((primep n) n)
        (t
            (next-prime (1+ n)))))

(defun factoring-1 (n divisor)
    (cond
        ((zerop n) n)
        ((primep n)
            (format t  "    ~A ~%" n)
            n)
        ((zerop (mod n divisor))
            (format t  "~A| ~A ~%----------~%" divisor n)
            (list divisor (factoring-1 (floor (/ n divisor)) divisor)))
        (t
            (factoring-1 n (next-prime (1+ divisor))))))
(defun factoring (n)
    (factoring-1 n 2))

こんな感じで使います

$ ros run
? (factoring 360)
2| 360
----------
2| 180
----------
2| 90
----------
3| 45
----------
3| 15
----------
    5
(2 (2 (2 (3 (3 5)))))
? 

※ 標準出力をちょっとだけ整えました

Ubuntu18.04 で apt upgrade が失敗

概要

定期的に apt upgrade を実行しているのですが、今日に限って急に失敗。
とりあえず upgradeができるまでは成功したので手順を書いておきます

ながれ

こんな感じで対応しました

ことのはじまり

apt upgrade に失敗

$ sudo apt upgrade
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
これらを直すためには 'apt --fix-broken install' を実行する必要があるかもしれません。
以下のパッケージには満たせない依存関係があります:
 libglvnd-dev : 依存: libglvnd0 (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
                依存: libglvnd-core-dev (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
                依存: libegl1 (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
                依存: libgles2 (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
                依存: libgl1 (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
                依存: libglx0 (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
                依存: libopengl0 (= 1.0.0-2ubuntu2.1) しかし、1.0.0-2ubuntu2.2 はインストールされています
E: 未解決の依存関係です。'apt --fix-broken install' を実行してみてください (または解法を明示してください)。

言われたとおり apt --fix-broken

$ sudo apt --fix-broken install 
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
依存関係を解決しています ... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  linux-headers-4.15.0-30 linux-headers-4.15.0-30-generic linux-image-4.15.0-30-generic
  linux-modules-4.15.0-30-generic linux-modules-extra-4.15.0-30-generic
これを削除するには 'sudo apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
  libgles1 libglvnd-dev
以下のパッケージが新たにインストールされます:
  libgles1
以下のパッケージはアップグレードされます:
  libglvnd-dev
アップグレード: 1 個、新規インストール: 1 個、削除: 0 個、保留: 53 個。
14.6 kB 中 0 B のアーカイブを取得する必要があります。
この操作後に追加で 66.6 kB のディスク容量が消費されます。
続行しますか? [Y/n] y
(データベースを読み込んでいます ... 現在 276241 個のファイルとディレクトリがインストールされています。)
.../libgles1_1.0.0-2ubuntu2.2_amd64.deb を展開する準備をしています ...
libgles1:amd64 (1.0.0-2ubuntu2.2) を展開しています...
dpkg: アーカイブ /var/cache/apt/archives/libgles1_1.0.0-2ubuntu2.2_amd64.deb の処理中にエラーが発生しました (--unpack):
 '/usr/lib/x86_64-linux-gnu/libGLESv1_CM.so.1' を上書きしようとしています。これはパッケージ nvidia-340 340.106-0ubuntu3 にも存在します
.../libglvnd-dev_1.0.0-2ubuntu2.2_amd64.deb を展開する準備をしています ...
libglvnd-dev:amd64 (1.0.0-2ubuntu2.2) で (1.0.0-2ubuntu2.1 に) 上書き展開しています ...
dpkg: アーカイブ /var/cache/apt/archives/libglvnd-dev_1.0.0-2ubuntu2.2_amd64.deb の処理中にエラーが発生しました (--unpack):
 '/usr/lib/x86_64-linux-gnu/libGLESv1_CM.so' を上書きしようとしています。これはパッケージ nvidia-340 340.106-0ubuntu3 にも存在します
処理中にエラーが発生しました:
 /var/cache/apt/archives/libgles1_1.0.0-2ubuntu2.2_amd64.deb
 /var/cache/apt/archives/libglvnd-dev_1.0.0-2ubuntu2.2_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

パッケージ nvidia-340 340.106-0ubuntu3 にも存在します

これが問題なんだな。

$ sudo apt list nvidia-340
一覧表示... 完了
nvidia-340/bionic,now 340.106-0ubuntu3 amd64 [インストール済み]

よし、このパッケージを消しちゃお。
ほんとに消していいかは不明だけど、だめだったら入れ直せばええやろ!ガハハ!

apt で消せなかったので dpkg で直接処すよ

aptaptitude で最初は消そうと思ったんですがなんかエラーが出てだめでした。
なので dpkg で直接やってしまいます

$ sudo dpkg -l | grep nvidia-340
ii  nvidia-340                                 340.106-0ubuntu3                           amd64        NVIDIA binary driver - version 340.106

~$ sudo dpkg -r nvidia-340
(データベースを読み込んでいます ... 現在 276240 個のファイルとディレクトリがインストールされています。)
nvidia-340 (340.106-0ubuntu3) を削除しています ...
Stopping nvidia-persistenced
nvidia-persistenced: no process found
Done.
Removing all DKMS Modules
Done.

なんかたくさん出てきたけどうまくいったみたい。

fix-broken 再チャレンジ

$ sudo apt --fix-broken install 
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
依存関係を解決しています ... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libcuda1-340 libxnvctrl0 linux-headers-4.15.0-30 linux-headers-4.15.0-30-generic
  linux-image-4.15.0-30-generic linux-modules-4.15.0-30-generic
  linux-modules-extra-4.15.0-30-generic nvidia-settings screen-resolution-extra
これを削除するには 'sudo apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
  libgles1 libglvnd-dev
以下のパッケージが新たにインストールされます:
  libgles1
以下のパッケージはアップグレードされます:
  libglvnd-dev
アップグレード: 1 個、新規インストール: 1 個、削除: 0 個、保留: 53 個。
14.6 kB 中 0 B のアーカイブを取得する必要があります。
この操作後に追加で 66.6 kB のディスク容量が消費されます。
続行しますか? [Y/n] y
(データベースを読み込んでいます ... 現在 275959 個のファイルとディレクトリがインストールされています。)
.../libgles1_1.0.0-2ubuntu2.2_amd64.deb を展開する準備をしています ...
libgles1:amd64 (1.0.0-2ubuntu2.2) を展開しています...
.../libglvnd-dev_1.0.0-2ubuntu2.2_amd64.deb を展開する準備をしています ...
libglvnd-dev:amd64 (1.0.0-2ubuntu2.2) で (1.0.0-2ubuntu2.1 に) 上書き展開しています ...
libgles1:amd64 (1.0.0-2ubuntu2.2) を設定しています ...
libglvnd-dev:amd64 (1.0.0-2ubuntu2.2) を設定しています ...
libc-bin (2.27-3ubuntu1) のトリガを処理しています ...

成功!

apt upgrade にも成功!

いちおう 消したパッケージを復旧しておく

$ sudo apt install nvidia-340/bionic
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
'nvidia-340' のバージョン '340.106-0ubuntu3' (Ubuntu:18.04/bionic [amd64]) を選択しました
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  linux-headers-4.15.0-30 linux-headers-4.15.0-30-generic linux-image-4.15.0-30-generic
  linux-modules-4.15.0-30-generic linux-modules-extra-4.15.0-30-generic
これを削除するには 'sudo apt autoremove' を利用してください。
以下のパッケージが新たにインストールされます:
  nvidia-340
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
51.9 MB のアーカイブを取得する必要があります。
この操作後に追加で 274 MB のディスク容量が消費されます。
取得:1 http://jp.archive.ubuntu.com/ubuntu bionic/restricted amd64 nvidia-340 amd64 340.106-0ubuntu3 [51.9 MB]
51.9 MB を 31秒 で取得しました (1,651 kB/s)                                                    
以前に未選択のパッケージ nvidia-340 を選択しています。
(データベースを読み込んでいます ... 現在 275967 個のファイルとディレクトリがインストールされています。)
.../nvidia-340_340.106-0ubuntu3_amd64.deb を展開する準備をしています ...
'nvidia-340 による /usr/lib/x86_64-linux-gnu/libGL.so.1 から /usr/lib/x86_64-linux-gnu/libGL.so.1.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/i386-linux-gnu/libGL.so.1 から /usr/lib/i386-linux-gnu/libGL.so.1.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/x86_64-linux-gnu/libGL.so から /usr/lib/x86_64-linux-gnu/libGL.so.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/i386-linux-gnu/libGL.so から /usr/lib/i386-linux-gnu/libGL.so.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/x86_64-linux-gnu/libEGL.so.1 から /usr/lib/x86_64-linux-gnu/libEGL.so.1.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/i386-linux-gnu/libEGL.so.1 から /usr/lib/i386-linux-gnu/libEGL.so.1.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/x86_64-linux-gnu/libEGL.so から /usr/lib/x86_64-linux-gnu/libEGL.so.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/i386-linux-gnu/libEGL.so から /usr/lib/i386-linux-gnu/libEGL.so.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/x86_64-linux-gnu/libGLESv2.so から /usr/lib/x86_64-linux-gnu/libGLESv2.so.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/i386-linux-gnu/libGLESv2.so から /usr/lib/i386-linux-gnu/libGLESv2.so.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/x86_64-linux-gnu/libGLESv2.so.2 から /usr/lib/x86_64-linux-gnu/libGLESv2.so.2.distrib への退避 (divert)' を追加しています
'nvidia-340 による /usr/lib/i386-linux-gnu/libGLESv2.so.2 から /usr/lib/i386-linux-gnu/libGLESv2.so.2.distrib への退避 (divert)' を追加しています
nvidia-340 (340.106-0ubuntu3) を展開しています...
dpkg: アーカイブ /var/cache/apt/archives/nvidia-340_340.106-0ubuntu3_amd64.deb の処理中にエラーが発生しました (--unpack):
 '/usr/lib/x86_64-linux-gnu/libGLESv1_CM.so' を上書きしようとしています。これはパッケージ libglvnd-dev:amd64 1.0.0-2ubuntu2.2 にも存在します
処理中にエラーが発生しました:
 /var/cache/apt/archives/nvidia-340_340.106-0ubuntu3_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

だめみたい。
まえっか。ガハハ!

その後

nvidia パッケージで問題が起きてるっていう警告は出ていますが
再起動、問題なく動きました。

しばらく様子見・・・

Caveman2 + keycloak で 認証サンプルを作ってみた

以下の記事を参考にしながらCaveman2 + Keycloak でOpenID connectをするサンプルを作ってみたいと思います

qiita.com

注意! OpenID 初心者によるサンプル実装ですので ご自身で使用するときは しっかりした調査とテストをよろしくおねがいします

Caveman2 をインストール

$ ros install caveman2 

プロジェクト作成

~/common-lisp ディレクトリ内であれば (ql:quickload :****) でロード可能なので
そこを作業ディレクトリにします

$ mkdir ~/common-lisp && cd ~/common-lisp

プロジェクトのひな型を作り、Webサーバを起動します

$ ros -s caveman2 -e "(caveman2:make-project #P\"openid-connect\" :auther \"moremagic\")" 
writing openid-connect/openid-connect.asd
writing openid-connect/openid-connect-test.asd
writing openid-connect/app.lisp
writing openid-connect/README.markdown
writing openid-connect/.gitignore
writing openid-connect/db/schema.sql
writing openid-connect/src/web.lisp
writing openid-connect/src/view.lisp
writing openid-connect/src/main.lisp
writing openid-connect/src/db.lisp
writing openid-connect/src/config.lisp
writing openid-connect/static/css/main.css
writing openid-connect/templates/index.html
writing openid-connect/templates/_errors/404.html
writing openid-connect/templates/layouts/default.html
writing openid-connect/tests/openid-connect.lisp

$ ros -s openid-connect -e "(openid-connect:start)" run

To load "openid-connect":
  Load 1 ASDF system:
    openid-connect
; Loading "openid-connect"

Hunchentoot server is started.
Listening on localhost:5000.
Clozure Common Lisp Version 1.11.5/v1.11.5  (LinuxX8664)

For more information about CCL, please see http://ccl.clozure.com.

CCL is free software.  It is distributed under the terms of the Apache
Licence, Version 2.0.
? 

http://localhost:5000 でWebアプリケーションが起動します。 停止したい場合は (openid-connect:stop) もしくは (quit) と打つことでWebアプリケーションが停止します

keycloak の起動

Docker で keycloak Imageを起動します

docker run -d -p 18080:8080 \
             -e KEYCLOAK_USER=admin \
             -e KEYCLOAK_PASSWORD=admin \
             --name keycloak \
             jboss/keycloak

http://localhost:18080/auth/admin/ にアクセス。admin / admin でログインできます

Keycloakの設定

client 設定を追加します f:id:moremagic:20180917173204p:plain

Instralletion からクライアントシークレット等を取得します f:id:moremagic:20180917173300p:plain

Client側に認証コードを実装します

git diff

~/common-lisp/openid-connect$ git diff
diff --git a/openid-connect.asd b/openid-connect.asd
index 35dff1e..ac20e92 100644
--- a/openid-connect.asd
+++ b/openid-connect.asd
@@ -17,7 +17,13 @@
 
                ;; for DB
                "datafly"
-               "sxql")
+               "sxql"
+
+               ;; for OAuth
+               "dexador"
+               "cl-base64"
+               "secure-random"
+               "jsown")
   :components ((:module "src"
                 :components
                 ((:file "main" :depends-on ("config" "view" "db"))
diff --git a/src/web.lisp b/src/web.lisp
index 45fe73d..a725828 100644
--- a/src/web.lisp
+++ b/src/web.lisp
@@ -6,7 +6,8 @@
         :openid-connect.view
         :openid-connect.db
         :datafly
-        :sxql)
+        :sxql
+        :quri)
   (:export :*web*))
 (in-package :openid-connect.web)
 
@@ -33,3 +34,135 @@
   (declare (ignore app))
   (merge-pathnames #P"_errors/404.html"
                    *template-directory*))
+
+;; auth parameter
+(defparameter +keycloak-client-id+
+  "openid-connect")
+(defparameter +keycloak-client-secret+
+  "9bc0468f-ce9b-4c90-ac93-4837b57494ab")
+(defparameter +keycloak-auth-url+
+  "http://localhost:18080/auth/realms/master/protocol/openid-connect/auth")
+(defparameter +keycloak-token-url+
+  "http://localhost:18080/auth/realms/master/protocol/openid-connect/token")
+(defparameter +keycloak-token-info-url+
+  "http://localhost:18080/auth/realms/master/protocol/openid-connect/userinfo")
+(defparameter +keycloak-logout-url+
+  "http://localhost:18080/auth/realms/master/protocol/openid-connect/logout")
+(defparameter +keycloak-redirect-uri+
+  "http://localhost:5000/oauth2callback")
+
+;;
+;; Utility functions
+
+(defun get-keycloak-auth-url (state-token)
+  "keycloakアカウントでの認証URLを生成"
+  (render-uri
+    (make-uri :defaults +keycloak-auth-url+
+              :query `(("client_id" . ,+keycloak-client-id+)
+                       ("redirect_uri" . ,+keycloak-redirect-uri+)
+                       ("scope" . "openid profile email")
+                       ("response_type" . "code")
+                       ("approval_prompt" . "force")
+                       ("access_type" . "offline")
+                       ("state" . ,state-token)))))
+
+(defun request-keycloak-token (code)
+  "トークンを要請"
+  (format t "[DEBUG] call request-token ~A~%" code)
+  (dex:post +keycloak-token-url+
+    :content `(("code" . ,code)
+               ("client_id" . ,+keycloak-client-id+)
+               ("client_secret" . ,+keycloak-client-secret+)
+               ("redirect_uri" . ,+keycloak-redirect-uri+)
+               ("grant_type" . "authorization_code"))))
+
+(defun request-keycloak-token-info (access_token)
+  "トークン情報を要請"
+  (format t "[DEBUG]===========================================~%")
+  (format t "[DEBUG][request-keycloak-token-info] '~A'~%" access_token)
+  (dex:post +keycloak-token-info-url+
+    :headers `(("content-type" . "application/json")
+               ("Accept" . "application/json")
+               ("Authorization" . ,(concatenate `string "Bearer " access_token)))
+    :content `()))
+
+(defun loginp ()
+  "ログインしているかどうかを確認"
+  (format t "[DEBUG] session in accsess_token '~A'~%" (gethash :access_token *session* nil))
+  (not (null (gethash :access_token *session* nil))))
+
+(defun logout (refresh_token)
+  "ログアウト処理"
+  (format t "[DEBUG]logout api call...")
+  (dex:post +keycloak-logout-url+
+    :headers `(("Content-Type" . "application/x-www-form-urlencoded"))
+    :content `(("client_id" . ,+keycloak-client-id+)
+               ("client_secret" . ,+keycloak-client-secret+)
+               ("refresh_token" . ,refresh_token )
+               )))
+
+(defroute "/" ()
+  (if (loginp)
+    (redirect "/home")
+    (render #P"index.html")))
+
+(defroute "/home" ()
+  (if (loginp)
+    (render #P"home.html")
+    (redirect "/")))
+
+(defroute ("/auth-keycloak" :method :POST) ()
+  (let ((state-token
+          (cl-base64:usb8-array-to-base64-string
+            (secure-random:bytes 32 secure-random:*generator*))))
+    (setf (gethash :oauth-keycloak *session*) (acons :state state-token (list)))
+    (redirect (get-keycloak-auth-url state-token))))
+
+(defroute ("/oauth2callback" :method :GET) (&key |error| |state| |code|)
+  ;; エラーが発生した場合はエラーを表示してそのままルートにリダイレクト
+  (unless (null |error|)
+    (format t "Error: ~A~%" |error|)
+    (redirect "/"))
+  (let ((session-oauth-keycloak (gethash :oauth-keycloak *session* nil)))
+    ;; セッションにステートトークンが存在するか確認
+    (if (not (null (assoc :state session-oauth-keycloak)))
+      ;; セッションのステートトークンがレスポンスのステートトークンと一致するか確認
+      (if (string= (cdr (assoc :state session-oauth-keycloak)) |state|)
+        ;; レスポンスに認証コードが存在するか確認
+        (if (not (null |code|))
+          ;; keycloakの認証サーバーにトークンを要請
+          (let ((response (jsown:parse (request-keycloak-token |code|))))
+            ;; ログイン成功。access_tokenを取り出してセッションの:access_tokenに格納
+            (format t "[DEBUG] response '~A'~%" response)
+            (setf (gethash :access_token *session*) (jsown:val response "access_token"))
+            (setf (gethash :refresh_token *session*) (jsown:val response "refresh_token"))
+            (format t "[DEBUG] refresh_token '~A'~%" (gethash :refresh_token *session*))
+
+            ;; トークンが有効か確認(ライフタイムが残っているか?)
+            ;; さらにIDトークンの存在を確認
+            (if (and (> (jsown:val response "expires_in") 0)
+                     (not (null (jsown:val response "id_token"))))
+              ;; IDトークンをkeycloakに投げてユーザー情報を取得
+              ;; この処理は不要かも
+              (let ((api-result
+                      (jsown:parse (request-keycloak-token-info (gethash :access_token *session*)))))
+
+                ;; ユーザ名を取り出してセッションの:preferred_usernameに格納
+                ;; 本来ならここでJWTをばらして、ロール等の情報をセッションに登録をする
+                (let ((preferred_username (jsown:val api-result "preferred_username")))
+                  (format t "Signin: success keycloak OAuth '~A'~%" preferred_username)
+                  (setf (gethash :preferred_username *session*) preferred_username)
+                  (redirect "/home")))))))))
+    ;; 認証に失敗した場合はHTTP 401認証エラーコードを投げる
+    (throw-code 401))
+
+(defroute "/logout" ()
+  (if (loginp)
+    (progn
+      (format t "[DEBUG] refresh_token '~A'~%" (gethash :refresh_token *session*))
+      (logout (gethash :refresh_token *session*))
+      (setf (gethash :access_token *session*) nil)
+      (setf (gethash :refresh_token *session*) nil)
+      (redirect "/"))
+    (render #P"index.html")))
+
diff --git a/templates/index.html b/templates/index.html
index 6a3c687..c45861e 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -3,5 +3,9 @@
 {% block content %}
 <div id="main">
   Welcome to <a href="http://8arrow.org/caveman/">Caveman2</a>!
+  <form action="/auth-keycloak" method="post">
+    <button>Login with Keycloak</button>
+  </form>
 </div>
+
 {% endblock %}

実行

http://localhost:5000 にアクセス。loginしてみます f:id:moremagic:20180917174021p:plain

admin/admin f:id:moremagic:20180917174056p:plain

login 成功! logout押してみると・・・ f:id:moremagic:20180917174145p:plain

ログアウトできました f:id:moremagic:20180917174313p:plain

ここまでの成果物はここにおいてあります。

github.com

大変だった・・・

チェックアウトしたソースコードから lemを動かす

(前の記事からの続きです)

チェックアウトしたソースコードをちょっとだけいじって
REPL から起動することに成功したのでメモ。

ソースをちょっとだけ改変

Visual mode のコードをちょっとだけ変えてみます

~/.roswell/local-project/cxxxr/lem/lem-vi-mode/visual.lisp

$ git diff

--- a/lem-vi-mode/visual.lisp
+++ b/lem-vi-mode/visual.lisp

 (define-command vi-visual-line () ()
   (if (visual-line-p)
       (vi-visual-end)
       (progn
         (change-state 'visual 'visual-line)
-        (message "-- VISUAL LINE --"))))
+        (message "-- VISUAL LINEa --"))))

起動

$ ros run

* (ql:quickload :lem-ncurses)

To load "lem-ncurses":
  Load 1 ASDF system:
    lem-ncurses
; Loading "lem-ncurses"
..................................................
[package trivial-clipboard].......................
[package lem.term]................................
[package lem-ncurses]...
(:LEM-NCURSES)

* (lem:lem)

Visual モードにしてみると・・・

f:id:moremagic:20180913091303p:plain

できたぁぁぁ!!

あれ、、もしかして、、、

ros -s lem-ncurses -e '(lem:lem)'

うごいた! なるほど・・・

参考にした資料

local-project フォルダの使い方がやっと理解できました。感謝。

qiita.com

REPL から lem を動かすことには成功したけど、、、

こないだの記事の続き

github.com

roswell/lem を覗いて、roswell/lem-ncurses.ros が呼ばれているっぽいことまでわかったので
roswell/lem-ncurses.ros の中身をまねっこして動かしてみた

ros -Q -m lem-ncurses -L sbcl-bin -e '(lem:lem)'

うぉー!lem が起動したぞ!
でも .roswell/local-project 内のソースコードをイジってみても挙動が変わるようには見えないなぁ
ソースコードから実行できているわけではなさそう。

-m オプション が味噌なのかな?
roswell のヘルプを読んでみても -m オプションの意味がよくわからない
-m IMAGE --image IMAGE continue from Lisp image IMAGE

うーん。もうちょっと調べてみよっと

lem を REPL から実行したいのだけど・・・

common lisp で作られたエディタがあるらしい。 早速試してみる

github.com

インストール

$ ros install cxxxr/lem

実行

$ ~/.roswell/bin/lem

ソースから実行してみたいなと思って やり方をいろいろググってみました。 peccu.hatenablog.com

$ ros -s lem -e '(lem:lem)'

debugger invoked on a UNBOUND-VARIABLE in thread
#<THREAD "main thread" RUNNING {10005505B3}>:
  The variable LEM:*IMPLEMENTATION* is unbound.

うーん・・・なんでじゃろ?