前から気になっていたのでやってみた。
疑問はあまり解決しないまま。
まずはエディタの設定。
elm-mode
に加えてflycheck
やelm-oracle
、lsp-mode
などを試してみたけど動かない。
仕方がないので取り敢えずelm-mode
だけでやってみた。
C-c C-c
はダメっぽい。
https://emacs.stackexchange.com/questions/50479/elm-mode-cant-compile-file
色々大きく変更する必要があるっぽい。
C-c C-l
はファイル名と場所を正しくすれば動くけど、アクティブウィンドウが切り替わるのが使いづらい。
https://emacs.stackexchange.com/questions/7409/is-there-a-generic-toggle-previous-window-function
ここに書いてある設定を使って
(defun switch-to-last-window ()
(interactive)
(let ((win (get-mru-window t t t)))
(unless win (error "Last window not found."))
(let ((frame (window-frame win)))
(raise-frame frame)
(select-frame frame)
(select-window win))))
(defun elm-repl-load-back ()
(interactive)
(elm-repl-load)
(switch-to-last-window)
)
(require 'elm-mode)
(add-hook 'elm-mode-hook
(lambda ()
;; (elm-format-on-save-mode)
(local-set-key (kbd "C-c C-l") 'elm-repl-load-back)
))
こんな感じにして、C-c C-l
でアクティブウィンドウを切り替えないようにした。もっと単純な設定がある気がするが。
マニュアルを見ながら書いていく。
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
init = undefined
view = undefined
update = undefined
subscriptions = undefined
というようにまずはコンパイルを通すようにしてC-c C-l
をカチカチしながら進めたいんだけど、Elm
だとundefinedが無い?少しずつ書くにはどうしたらいいんだろう。
分からないのでそれも置いておいて、 https://github.com/evancz/elm-architecture-tutorial この辺を適当にいじってみる。
https://qiita.com/arowM/items/dfb38d1c5f3dfde8b8bf
この辺を読んでいると、どうも合ってない気がするが…。HTMLは普通にファイルで書きたいので、The Elm Architecture じゃなくなるよね。
例えば Closure Tools
を使いつつ
goog.provide('app.main');
goog.require('goog.dom');
goog.require('ElmJs');
function runQ(){
var q = window['q'] || [];
for (var i = 0; i < q.length; i++){
q[i]();
}
window['q'] = {
push: function(f){
f();
}
};
}
function runApp()
{
var el = goog.dom.getElement('elm');
console.log(el);
var app = window['Elm']['Main']['init']({
node: document.getElementById('elm')
});
}
window['runApp'] = runApp;
runQ();
こんな感じにしたい。Closure Compiler
でまとめて圧縮しても一応動くけど、HTMLはサーバーサイドで書いたものをそのまま使いたいんだよなー…。
ていうわけで
https://qiita.com/ymtszw/items/d195c098445476527539
この辺を参考にしつつ
port module Main exposing (..)
import Platform
import Task
import Time
import Json.Encode as Encode
import Time.Extra
main =
Platform.worker
{ init = init
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ zone : Time.Zone
, time : Time.Posix
}
init : () -> (Model, Cmd Msg)
init _ =
( Model Time.utc (Time.millisToPosix 0)
, Task.perform AdjustTimeZone Time.here
)
-- UPDATE
type Msg
= Tick Time.Posix
| AdjustTimeZone Time.Zone
dateToStr : Model -> String
dateToStr model =
let
hour =
String.fromInt (Time.toHour model.zone model.time)
minute =
String.fromInt (Time.toMinute model.zone model.time)
second =
String.fromInt (Time.toSecond model.zone model.time)
in
hour ++ ":" ++ minute ++ ":" ++ second
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Tick newTime ->
let newmodel = { model | time = newTime }
in
( newmodel
, sender (Encode.string <| dateToStr newmodel)
)
AdjustTimeZone newZone ->
let newmodel = { model | zone = newZone }
in
( newmodel
, sender (Encode.string <| dateToStr newmodel)
)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Time.every 1000 Tick
port sender : Encode.Value -> Cmd msg
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<script src="main.js"></script>
</head>
<body>
<h1>test</h1>
<div id="elm"></div>
<script>
var app = Elm.Main.init();
app.ports.sender.subscribe(
function(a){
document.getElementById('elm').innerHTML = a;
}
);
</script>
</body>
</html>
こんなコードをテストしてみたり。
検索して出てくるPlatform.program
がworker
に変わった?
動くけど、こんな使い方をしていいものかどうか。
理想は
https://qiita.com/arowM/items/6c32db1f9e4b92445f3b
ここに書いてあるようなパーサー等を使いつつ、HTMLやCSSは普通に別ファイルで書きたい。
https://n314.hatenablog.com/entry/20110824/1314182177 昔自分がScalaで書いたやつ。こんな感じにタグのclassやnameを読み取って自動でバインディングしたい。
可能かどうかで言えば可能な気がするし他の言語でやるよりやりやすい気がするけど、用途がズレているのが気になる。
あと気になるのが、PHPでParsecを書いたときは超遅くなってメモリも大量に使ったんだけど、JavaScriptは大丈夫なのかね。
トランスパイル時に良い感じに最適化してくれるんかな。