nendo 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/nendo +37 -2
- data/example/cgi/dekamoji.cgi +100 -0
- data/example/cgi/sample.cgi +32 -0
- data/{sample → example}/exit.nnd +0 -0
- data/{sample → example}/fact.nnd +2 -2
- data/{sample → example}/fizzbuzz1.nnd +2 -2
- data/example/html-lite-sample.nnd +51 -0
- data/{sample → example}/scratch.nnd +1 -5
- data/{sample → example}/tak.nnd +0 -0
- data/lib/init.nnd +171 -30
- data/lib/init.nndc +3736 -2009
- data/lib/nendo.rb +322 -127
- data/lib/text/html-lite.nnd +231 -0
- data/lib/text/html-lite.nndc +2652 -0
- data/lib/text/tree.nnd +23 -0
- data/lib/text/tree.nndc +215 -0
- metadata +14 -7
data/bin/nendo
CHANGED
@@ -1,12 +1,47 @@
|
|
1
1
|
#!/usr/local/bin/ruby -W0
|
2
|
+
# -*- encoding: utf-8 -*-
|
2
3
|
#
|
3
|
-
# Nendo: "
|
4
|
+
# Nendo: "Nendo is a diarect of Lisp."
|
4
5
|
#
|
5
6
|
require 'nendo'
|
7
|
+
require 'getoptlong'
|
6
8
|
|
7
9
|
def main
|
10
|
+
loadInit = true
|
8
11
|
core = Nendo.new()
|
9
|
-
|
12
|
+
|
13
|
+
opts = GetoptLong.new(
|
14
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
15
|
+
[ '--no-init-file', '-q', GetoptLong::NO_ARGUMENT ],
|
16
|
+
[ '--load', '-l', GetoptLong::REQUIRED_ARGUMENT ]
|
17
|
+
).each { |opt, arg|
|
18
|
+
case opt
|
19
|
+
when '--help'
|
20
|
+
puts <<-EOF
|
21
|
+
|
22
|
+
nendo [OPTION] [script-file]
|
23
|
+
|
24
|
+
-h, --help:
|
25
|
+
show help
|
26
|
+
|
27
|
+
-q, --no-init-file:
|
28
|
+
Does not read the default initialization file.
|
29
|
+
|
30
|
+
-l, --load:
|
31
|
+
Does not read the default initialization file.
|
32
|
+
|
33
|
+
EOF
|
34
|
+
when '--no-init-file'
|
35
|
+
loadInit = false
|
36
|
+
when '--load'
|
37
|
+
core.load( arg )
|
38
|
+
STDERR.printf( "loaded file [%s]\n", arg )
|
39
|
+
end
|
40
|
+
}
|
41
|
+
|
42
|
+
if loadInit
|
43
|
+
core.loadInitFile
|
44
|
+
end
|
10
45
|
if 0 < ARGV.length
|
11
46
|
core.load( ARGV[0] )
|
12
47
|
else
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
:; #-*- mode: nendo; syntax: scheme -*-;;
|
3
|
+
:; exec /usr/local/bin/nendo $0 $*
|
4
|
+
|
5
|
+
(load-library "text/html-lite")
|
6
|
+
(load-library "text/tree")
|
7
|
+
(require "cgi")
|
8
|
+
(require "RMagick")
|
9
|
+
|
10
|
+
(define (response-dekamoji str pointsize)
|
11
|
+
(let* ((font-dots pointsize)
|
12
|
+
(margin (* pointsize 0.3))
|
13
|
+
(image (Magick::Image.new (+ (* str.size font-dots) margin) (+ font-dots margin)))
|
14
|
+
(imlist (Magick::ImageList.new))
|
15
|
+
(dr (Magick::Draw.new)))
|
16
|
+
(set! image.background_color "none")
|
17
|
+
(set! image.format "PNG")
|
18
|
+
(imlist.push image)
|
19
|
+
;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ホリデイMDJP03")
|
20
|
+
;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/みかちゃん")
|
21
|
+
;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ヒラギノ丸ゴ ProN W4.otf")
|
22
|
+
;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ヒラギノ明朝 Pro W6.otf")
|
23
|
+
(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ヒラギノ明朝 Pro W3.otf")
|
24
|
+
(set! dr.pointsize pointsize)
|
25
|
+
(set! dr.fill "#404040")
|
26
|
+
(set! dr.stroke "#080808")
|
27
|
+
(set! dr.font_weight Magick::BoldWeight)
|
28
|
+
(set! dr.gravity Magick::CenterGravity)
|
29
|
+
(dr.annotate imlist 0 0 0 0 str)
|
30
|
+
(let1 blur (imlist.blur_image 1.0 1.0)
|
31
|
+
(blur.to_blob))))
|
32
|
+
|
33
|
+
|
34
|
+
(define default-wording "デカ文字")
|
35
|
+
(define default-size 2)
|
36
|
+
(define size-list '(
|
37
|
+
(1 . "サイズ小")
|
38
|
+
(2 . "サイズ中")
|
39
|
+
(3 . "サイズ大")
|
40
|
+
(4 . "サイズ特大")
|
41
|
+
))
|
42
|
+
|
43
|
+
|
44
|
+
(define (top-page params)
|
45
|
+
(let* ((size (if (hash-table-exist? params "size")
|
46
|
+
(to-i (car (to-list (hash-table-get params "size"))))
|
47
|
+
default-size))
|
48
|
+
(wording (if (hash-table-exist? params "w")
|
49
|
+
(car (to-list (hash-table-get params "w")))
|
50
|
+
default-wording)))
|
51
|
+
(let* ((size (if (> 1 size) 1 size))
|
52
|
+
(size (if (< (length size-list) size) (length size-list) size)))
|
53
|
+
`(
|
54
|
+
,(html-doctype)
|
55
|
+
,(html:head
|
56
|
+
(html:title "デカ文字作成"))
|
57
|
+
,(html:body
|
58
|
+
(html:div :style "text-align: center; "
|
59
|
+
(html:h1 "デカ文字作成")
|
60
|
+
(html:p
|
61
|
+
"下記に文章を入れて『画像化』ボタンを押して下さい")
|
62
|
+
(html:form
|
63
|
+
:method "GET"
|
64
|
+
:action "./dekamoji.cgi"
|
65
|
+
(html:input :name "w" :type "text" :cols 140 :value wording)
|
66
|
+
(map
|
67
|
+
(lambda (x)
|
68
|
+
(list
|
69
|
+
(html:input :name "size" :type "radio"
|
70
|
+
:value (car x)
|
71
|
+
:CHECKED (eq? (car x) size))
|
72
|
+
(cdr x)))
|
73
|
+
size-list)
|
74
|
+
(html:br)
|
75
|
+
(html:input :type "submit" :value "画像化"))
|
76
|
+
(html:hr)
|
77
|
+
(html:img :src (sprintf "./dekamoji.cgi?img=1&size=%d&w=%s" size wording))
|
78
|
+
(html:hr)))))))
|
79
|
+
|
80
|
+
(define fontsize-alist '(
|
81
|
+
("1" . 40)
|
82
|
+
("2" . 80)
|
83
|
+
("3" . 160)
|
84
|
+
("4" . 260)
|
85
|
+
))
|
86
|
+
|
87
|
+
(let1 cgi (CGI.new)
|
88
|
+
(cond ((hash-table-exist? cgi.params "img")
|
89
|
+
(cgi.print
|
90
|
+
(cgi.header "image/png"))
|
91
|
+
(cgi.print
|
92
|
+
(response-dekamoji
|
93
|
+
(car (to-list (hash-table-get cgi.params "w")))
|
94
|
+
(assv-ref (car (to-list (hash-table-get cgi.params "size"))) fontsize-alist))))
|
95
|
+
(else
|
96
|
+
(cgi.print
|
97
|
+
(cgi.header))
|
98
|
+
(cgi.print
|
99
|
+
(tree->string
|
100
|
+
(top-page cgi.params))))))
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
:; #-*- mode: nendo; syntax: scheme -*-;;
|
3
|
+
:; exec /usr/local/bin/nendo $0 $*
|
4
|
+
|
5
|
+
(load-library "text/html-lite")
|
6
|
+
(load-library "text/tree")
|
7
|
+
(require "cgi")
|
8
|
+
|
9
|
+
(define (params-list-page cgi)
|
10
|
+
`(
|
11
|
+
,(html-doctype)
|
12
|
+
,(html:head
|
13
|
+
(html:title "CGI parameter list"))
|
14
|
+
,(html:body
|
15
|
+
(html:h1 "CGI parameter list")
|
16
|
+
(html:table :border 1
|
17
|
+
(html:tr
|
18
|
+
(html:th "key")
|
19
|
+
(html:th "value"))
|
20
|
+
(hash-table-for-each cgi.params
|
21
|
+
(lambda (key value)
|
22
|
+
(html:tr
|
23
|
+
(html:td key)
|
24
|
+
(html:td (string-join value.to_list "/")))))))))
|
25
|
+
|
26
|
+
|
27
|
+
(let1 cgi (CGI.new)
|
28
|
+
(cgi.print
|
29
|
+
(cgi.header))
|
30
|
+
(cgi.print
|
31
|
+
(tree->string
|
32
|
+
(params-list-page cgi))))
|
data/{sample → example}/exit.nnd
RENAMED
File without changes
|
data/{sample → example}/fact.nnd
RENAMED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
:; #-*- mode: nendo; syntax: scheme -*-;;
|
3
|
+
:; exec /usr/local/bin/nendo $0 $*
|
4
|
+
|
5
|
+
(load-library "text/html-lite")
|
6
|
+
(load-library "text/tree")
|
7
|
+
|
8
|
+
(define (page-sample)
|
9
|
+
`(
|
10
|
+
,(html:head
|
11
|
+
(html:title "title of page"))
|
12
|
+
,(html:body
|
13
|
+
(html:p "これはサンプルです")
|
14
|
+
(html:h1 "section 1")
|
15
|
+
(html:h2 "section 1-2")
|
16
|
+
(html:table :border 1
|
17
|
+
(html:tr
|
18
|
+
(html:th "head1")
|
19
|
+
(html:th "head2"))
|
20
|
+
(html:tr
|
21
|
+
(html:td "data1")
|
22
|
+
(html:td "data2"))
|
23
|
+
(html:tr
|
24
|
+
(html:td "data3")
|
25
|
+
(html:td "data4"))
|
26
|
+
(html:hr)))))
|
27
|
+
|
28
|
+
(write-tree
|
29
|
+
(page-sample))
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
data/{sample → example}/tak.nnd
RENAMED
File without changes
|
data/lib/init.nnd
CHANGED
@@ -107,6 +107,8 @@
|
|
107
107
|
(define (ninth lst) (nth 8 lst))
|
108
108
|
(define (tenth lst) (nth 9 lst))
|
109
109
|
|
110
|
+
(define (x->string object) (to-s object))
|
111
|
+
|
110
112
|
;; ----------------------------------------
|
111
113
|
;; basic forms
|
112
114
|
;; ----------------------------------------
|
@@ -126,7 +128,9 @@
|
|
126
128
|
(let ((condition (if (eq? 'else (car elem))
|
127
129
|
true
|
128
130
|
(car elem)))
|
129
|
-
(body (cdr elem))
|
131
|
+
(body (if (null? (cdr elem))
|
132
|
+
'(#t)
|
133
|
+
(cdr elem)))
|
130
134
|
(tmpsym (gensym)))
|
131
135
|
;;(display "CONDITION") (print condition)
|
132
136
|
;;(display "BODY") (print body)
|
@@ -311,6 +315,13 @@
|
|
311
315
|
;; don't touch
|
312
316
|
`(let ,@lst))))
|
313
317
|
|
318
|
+
;; ----------------------------------------
|
319
|
+
;; errorf
|
320
|
+
;; ----------------------------------------
|
321
|
+
(define errorf
|
322
|
+
(macro (format . args)
|
323
|
+
`(error
|
324
|
+
(sprintf ,format ,@args))))
|
314
325
|
|
315
326
|
;; ----------------------------------------
|
316
327
|
;; List utilities imported from TinyScheme
|
@@ -388,6 +399,13 @@
|
|
388
399
|
(filter-map pred (cdr lst))))))
|
389
400
|
|
390
401
|
|
402
|
+
(define (find pred lst)
|
403
|
+
(let1 result (filter pred lst)
|
404
|
+
(if (null? result)
|
405
|
+
#f
|
406
|
+
(car result))))
|
407
|
+
|
408
|
+
|
391
409
|
(define lambda
|
392
410
|
(macro src
|
393
411
|
(if (not (list? (cadr src)))
|
@@ -477,43 +495,80 @@
|
|
477
495
|
(let*-expand exps body))))
|
478
496
|
|
479
497
|
|
498
|
+
;; ----------------------------------------
|
499
|
+
;; values
|
500
|
+
;; ----------------------------------------
|
501
|
+
(define (values . args)
|
502
|
+
(case (length args)
|
503
|
+
((1)
|
504
|
+
(car args))
|
505
|
+
(else
|
506
|
+
(make-values args))))
|
507
|
+
|
508
|
+
|
509
|
+
(define (call-with-values producer consumer)
|
510
|
+
(let ((v (producer)))
|
511
|
+
(if (values? v)
|
512
|
+
(apply consumer (values-values v))
|
513
|
+
(consumer v))))
|
514
|
+
|
515
|
+
;; srfi-8
|
516
|
+
(define receive
|
517
|
+
(macro (vars expr . body)
|
518
|
+
`(call-with-values
|
519
|
+
(lambda () ,expr)
|
520
|
+
(lambda ,vars ,@body))))
|
521
|
+
|
522
|
+
|
523
|
+
;; ----------------------------------------
|
524
|
+
;; keyword
|
525
|
+
;; ----------------------------------------
|
526
|
+
(define (get-keyword key kv-list . fallback)
|
527
|
+
(cond
|
528
|
+
((or (not (list? kv-list)) (>= 2 (length kv-list)))
|
529
|
+
(if (null? fallback)
|
530
|
+
(errorf "Error: imcomplete key list: %s\n" (write-to-string kv-list))
|
531
|
+
(car fallback)))
|
532
|
+
(else
|
533
|
+
(let loop ((k (car kv-list))
|
534
|
+
(v (cadr kv-list))
|
535
|
+
(rest (cddr kv-list)))
|
536
|
+
(if (eq? k key)
|
537
|
+
v
|
538
|
+
(case (length rest)
|
539
|
+
((0)
|
540
|
+
(if (null? fallback)
|
541
|
+
(errorf "Error: value for key %s is not provided : %s\n" (write-to-string key) (write-to-string kv-list))
|
542
|
+
(car fallback)))
|
543
|
+
((1)
|
544
|
+
(errorf "Error: incomplete key list: %s\n" (write-to-string kv-list)))
|
545
|
+
(else
|
546
|
+
(loop (car rest)
|
547
|
+
(cadr rest)
|
548
|
+
(cddr rest)))))))))
|
549
|
+
|
480
550
|
;; ----------------------------------------
|
481
551
|
;; for Ruby interop
|
482
552
|
;; ----------------------------------------
|
483
|
-
;; dot_operator
|
484
553
|
(define dot-operator
|
485
554
|
(macro lst
|
486
|
-
(letrec ((
|
555
|
+
(letrec ((generate-method-call-form
|
487
556
|
(lambda (lst)
|
488
|
-
(
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
(map
|
496
|
-
(lambda (x)
|
497
|
-
(if (pair? x)
|
498
|
-
(to-s (dot-operator-iter x))
|
499
|
-
(if (symbol? x)
|
500
|
-
(to-s x)
|
501
|
-
(error (sprintf "dot-operator requires symbol, but got %s" x)))))
|
502
|
-
(cdr lst))
|
503
|
-
"."))
|
504
|
-
(error "dot-operator requires symbol or (. symbol symbol) form.")))
|
505
|
-
(else
|
506
|
-
lst)))))
|
507
|
-
|
557
|
+
(let1 tmp (gensym)
|
558
|
+
(if (symbol? (first lst))
|
559
|
+
`(,(string->symbol (+ (to-s (first lst)) "." (to-s (second lst))))
|
560
|
+
,@(cddr lst))
|
561
|
+
`(let ((,tmp ,(first lst)))
|
562
|
+
(,(string->symbol (+ (to-s tmp) "." (to-s (second lst))))
|
563
|
+
,@(cddr lst))))))))
|
508
564
|
(cond
|
509
|
-
((
|
510
|
-
(
|
511
|
-
((and (eq? 1 (length lst))
|
512
|
-
(symbol? (car lst)))
|
513
|
-
(intern (+ "." (to-s (car lst)))))
|
565
|
+
((> 2 (length lst))
|
566
|
+
(raise ArgumentError ". dot-operator requires 2+ arguments."))
|
514
567
|
(else
|
515
|
-
((
|
516
|
-
|
568
|
+
(if (symbol? (second lst))
|
569
|
+
(generate-method-call-form lst)
|
570
|
+
(raise TypeError ". dot-operator requires method name as symbol.")))))))
|
571
|
+
|
517
572
|
|
518
573
|
(define (with-open filename pred . lst)
|
519
574
|
(let1 len (length lst)
|
@@ -538,6 +593,92 @@
|
|
538
593
|
x))
|
539
594
|
|
540
595
|
|
596
|
+
(define (cons* arg . args)
|
597
|
+
(if (null? args)
|
598
|
+
arg
|
599
|
+
(cons arg (apply list* args))))
|
600
|
+
(define list* cons*)
|
601
|
+
|
602
|
+
|
603
|
+
;; ----------------------------------------
|
604
|
+
;; hash-table library functions
|
605
|
+
;; ----------------------------------------
|
606
|
+
(define (make-hash-table)
|
607
|
+
(Hash.new))
|
608
|
+
|
609
|
+
(define (hash-table? h)
|
610
|
+
(h.is_a? Hash))
|
611
|
+
|
612
|
+
(define (hash-table-num-entries h)
|
613
|
+
(h.length))
|
614
|
+
|
615
|
+
(define (hash-table . kv-list)
|
616
|
+
(let1 h (make-hash-table)
|
617
|
+
(for-each
|
618
|
+
(lambda (entry)
|
619
|
+
(if (pair? (cdr entry))
|
620
|
+
(hash-table-put! h (car entry) (cadr entry))
|
621
|
+
(hash-table-put! h (car entry) (cdr entry))))
|
622
|
+
kv-list)
|
623
|
+
h))
|
624
|
+
|
625
|
+
(define (hash-table-exist? h key)
|
626
|
+
(h.has_key? key))
|
627
|
+
|
628
|
+
(define (hash-table-clear! h)
|
629
|
+
(h.clear))
|
630
|
+
|
631
|
+
(define (hash-table-delete! h key)
|
632
|
+
(h.delete key))
|
633
|
+
|
634
|
+
(define (hash-table-keys h)
|
635
|
+
(to-list (h.keys)))
|
636
|
+
|
637
|
+
(define (hash-table-values h)
|
638
|
+
(to-list (h.values)))
|
639
|
+
|
640
|
+
(define (hash-table-map h pred)
|
641
|
+
(let1 keys (hash-table-keys h)
|
642
|
+
(map
|
643
|
+
(lambda (key)
|
644
|
+
(pred key (hash-table-get h key)))
|
645
|
+
keys)))
|
646
|
+
(define hash-table-for-each hash-table-map)
|
647
|
+
|
648
|
+
(define (hash-table->alist h)
|
649
|
+
(if (not (h.is_a? Hash))
|
650
|
+
(raise TypeError "Error: hash-table->alist expects Hash instance.")
|
651
|
+
(let1 keys (hash-table-keys h)
|
652
|
+
(map
|
653
|
+
(lambda (key)
|
654
|
+
(cons key (hash-table-get h key)))
|
655
|
+
keys))))
|
656
|
+
|
657
|
+
(define (alist->hash-table alist)
|
658
|
+
(if (not (list? alist))
|
659
|
+
(raise TypeError "Error: alist->hash-table expects alist.")
|
660
|
+
(apply hash-table alist)))
|
661
|
+
|
662
|
+
;; ----------------------------------------
|
663
|
+
;; Ruby interop librarys
|
664
|
+
;; ----------------------------------------
|
665
|
+
;; I will implement in the future...
|
666
|
+
(define export
|
667
|
+
(macro (name)
|
668
|
+
`(define ,name nil)))
|
669
|
+
|
670
|
+
(define (load-library name)
|
671
|
+
(let* ((home (get-nendo-home))
|
672
|
+
(path (+ home "/" name)))
|
673
|
+
(cond
|
674
|
+
((File.exist? (+ path ".nndc"))
|
675
|
+
(load-compiled-code (+ path ".nndc")))
|
676
|
+
((File.exist? (+ path ".nnd"))
|
677
|
+
(load (+ path ".nnd")))
|
678
|
+
(else
|
679
|
+
(errorf "Error: can't load library file [%s]\n" path )))))
|
680
|
+
|
681
|
+
|
541
682
|
;; ----------------------------------------
|
542
683
|
;; Utility function for testing and debugging
|
543
684
|
;; ----------------------------------------
|