kdwatch 0.1.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +142 -0
- data/bin/kdwatch +110 -7
- data/kdwatch.gemspec +2 -1
- data/lib/kdwatch/version.rb +1 -1
- data/lib/kdwatch-app.rb +34 -7
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77f59a0c0a41535d090f2b858a44759a830b7cddc4e760a39c75613f06d2b37f
|
4
|
+
data.tar.gz: 6c53346765beb3f0391991db58bda4f00debfed880b8dca8763462567bbcd435
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9c2df05241e752a0d7d80e34cf8324872110a0aa4bc800bb9ef7ec1afe0ad2034b06691b56d84c14a6462c252606ef371cad1f85f021ac424046c09dcdc5182
|
7
|
+
data.tar.gz: 001ca06bd402115c0d63e8cd06e3558a99787f12ba97b9641c158ec8f9f8d87f99cdea3850a5121b28f53336d14c1312c13ec037ace624b97c19effba70fdea8
|
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
# Kdwatch
|
2
|
+
|
3
|
+
Auto-formatting, auto-reloading display of formatted [kramdown-rfc][] document in browser
|
4
|
+
|
5
|
+
[kramdown-rfc]: http://rfc.space
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
$ pip3 install --upgrade xml2rfc
|
11
|
+
$ gem update
|
12
|
+
$ gem install kdwatch
|
13
|
+
```
|
14
|
+
|
15
|
+
* For some reason, the initial `gem install` takes a couple of minutes,
|
16
|
+
during the first few of which it may seem nothing happens.
|
17
|
+
* If the above `pip3` (or `pip`) doesn't work, no problem: in a pinch,
|
18
|
+
kdrfc will use the IETF web service for xml2rfc processing (but that
|
19
|
+
may be a bit slower).
|
20
|
+
* Depending on system configuration, add `sudo` on the pip/gem
|
21
|
+
commands (but don't if it isn't actually needed).
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
* Open a separate terminal window/screen.
|
26
|
+
* Go to a directory that has a single draft-*.md (or select one by
|
27
|
+
specifying the markdown file name on the command line) and run:
|
28
|
+
|
29
|
+
```
|
30
|
+
$ kdwatch
|
31
|
+
```
|
32
|
+
|
33
|
+
* After about 10 seconds, a browser will open (or an error message will
|
34
|
+
pop up with the URL to use, which depends on the options given, but
|
35
|
+
defaults to <http://127.0.0.1:7991/>).
|
36
|
+
|
37
|
+
Now, whenever you do an editor save of the kramdown-rfc markdown file,
|
38
|
+
kdwatch auto-formats and, after a couple of seconds(*), you see an
|
39
|
+
updated HTML in the browser without pressing buttons or switching windows.
|
40
|
+
|
41
|
+
You will need to keep the `kdwatch` terminal/screen open to see
|
42
|
+
potential error messages, e.g., if you break the markdown in some way.
|
43
|
+
(The author uses an Emacs "Async Shell Command" buffer for that.)
|
44
|
+
|
45
|
+
(*) The latency depends on your computer and a bit on the size of the
|
46
|
+
file, say, around 1.6 s for my Intel Mac, 0.8 s for my M1 Mac.
|
47
|
+
|
48
|
+
### There can only be one (per host/port)
|
49
|
+
|
50
|
+
There can only be one kdwatch active on each host and port. You will
|
51
|
+
need to specify a different port (or host!) to run more than one
|
52
|
+
kdwatch at the same time.
|
53
|
+
|
54
|
+
* `-p port` to select a port number (default: 7991)
|
55
|
+
* `-1` to `6` as a shortcut for `-p 7991` (default) to `-p 7996` (must be last
|
56
|
+
option because of an idiosyncrasy of the optionparser library)
|
57
|
+
|
58
|
+
kdwatch has two flags to simplify handling servers that might be
|
59
|
+
accumulating on one host/port:
|
60
|
+
|
61
|
+
* `-e` to kill (SIGINT) any current holder of the port given and exit
|
62
|
+
* `-r` to do this, and to start a new instance as well
|
63
|
+
|
64
|
+
So the most likely use is going to be:
|
65
|
+
|
66
|
+
```
|
67
|
+
kdwatch -r
|
68
|
+
```
|
69
|
+
|
70
|
+
or maybe
|
71
|
+
|
72
|
+
```
|
73
|
+
kdwatch -r2
|
74
|
+
```
|
75
|
+
|
76
|
+
for the second draft you are editing at the same time,
|
77
|
+
|
78
|
+
or, if your drafts are weirdly named or you need to select one out of
|
79
|
+
many
|
80
|
+
|
81
|
+
```
|
82
|
+
kdwatch -r5 weird-draft.md
|
83
|
+
```
|
84
|
+
|
85
|
+
(Glitches are to be expected if you *start* more than one server out of
|
86
|
+
the same directory at the same instant; TODO; for now, wait 10 seconds
|
87
|
+
before starting another from the same directory.)
|
88
|
+
|
89
|
+
### 7991, haven't I heard that number before?
|
90
|
+
|
91
|
+
The default port number was chosen after [RFC 7991], the initial (no
|
92
|
+
longer really authoritative) version of the v3 RFCXML specification,
|
93
|
+
and the port shortcuts 1 to 6 point to this and further RFCs from this
|
94
|
+
series.
|
95
|
+
(7997 is a particularly lame RFC, so it cannot be chosen by a
|
96
|
+
shortcut [actually: this port is already registered for something else].)
|
97
|
+
|
98
|
+
[RFC 7991]: https://rfc-editor.org/rfc/rfc7991.html
|
99
|
+
|
100
|
+
### kdwatch is a web server
|
101
|
+
|
102
|
+
kdwatch essentially is a web server and can listen on any host
|
103
|
+
interface you might have:
|
104
|
+
|
105
|
+
* `-o host` to select an interface address on the serving host (default: 127.0.0.1)
|
106
|
+
* `-i` as a shortcut for `-o :: ` (`i` stands for "on the Internet")
|
107
|
+
|
108
|
+
Unless used on 127.0.0.1 (or ::1), kdwatch is accessible to anyone who
|
109
|
+
can access your laptop over IP. That may be a security problem -- do
|
110
|
+
not specify a non-local interface unless you know you are not “on the
|
111
|
+
Internet” (or trust the way I cobble together software). If you are,
|
112
|
+
maybe `kdwatch -e` before going there!
|
113
|
+
|
114
|
+
The fun thing with the `-i` option is that you can replace the local
|
115
|
+
URL by filling in the hostname of the laptop and use the resulting URL
|
116
|
+
on a different browser (e.g., `http://mylaptop.local:7991` on your iPad or
|
117
|
+
another laptop), and save some screen real-estate on your laptop.
|
118
|
+
With a globally routable address, kdwatch even can be used for joint
|
119
|
+
viewing in a team.
|
120
|
+
|
121
|
+
## Feedback, please
|
122
|
+
|
123
|
+
This has only been tested on macOS and briefly on Linux. No idea about WSL.
|
124
|
+
There is very little error handling yet, so restarts of the tool may
|
125
|
+
be required, or sometimes reloading in the browser (CMD-R/F5) is all
|
126
|
+
that is needed.
|
127
|
+
|
128
|
+
If you try it, please send feedback (and, in case of an error, *all*
|
129
|
+
output on the kdwatch terminal window, please).
|
130
|
+
|
131
|
+
Bug reports, pull requests, or simple suggestions are welcome on GitHub at
|
132
|
+
<https://github.com/cabo/kdwatch>, e.g., simply [submit an
|
133
|
+
issue][issues] or send me [mail][].
|
134
|
+
|
135
|
+
[issues]: https://github.com/cabo/kdwatch/issues
|
136
|
+
[mail]: mailto:cabo@tzi.org?Subject=kdwatch
|
137
|
+
|
138
|
+
## License
|
139
|
+
|
140
|
+
The gem is available as open source under the terms of the [MIT License][].
|
141
|
+
|
142
|
+
[MIT License]: https://opensource.org/licenses/MIT
|
data/bin/kdwatch
CHANGED
@@ -3,25 +3,128 @@ ENV["LANG"]="en_US.utf-8"
|
|
3
3
|
ENV["LC_CTYPE"]="en_US.utf-8"
|
4
4
|
ENV["KRAMDOWN_PERSISTENT"]="yes"
|
5
5
|
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
require_relative "../lib/kdwatch/version"
|
11
|
+
|
12
|
+
KDWATCH_PORT = 7991 # currently unregistered...
|
13
|
+
|
14
|
+
options = OpenStruct.new
|
15
|
+
|
16
|
+
op = OptionParser.new do |opts|
|
17
|
+
opts.banner = <<BANNER
|
18
|
+
Usage: kdwatch [options] draft-foo.md|.mkd|.xml
|
19
|
+
Version: #{Kdwatch::VERSION}
|
20
|
+
BANNER
|
21
|
+
opts.on("-V", "--version", "Show version and exit") do |v|
|
22
|
+
puts "kdwatch #{Kdwatch::Version}"
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
opts.on("-H", "--help", "Show option summary and exit") do |v|
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
opts.on("-e", "--[no-]end", "End existing server and exit")
|
30
|
+
opts.on("-r", "--[no-]replace", "Replace existing server")
|
31
|
+
opts.on("-oNAME", "--host=NAME", String, "Server host (127.0.0.1)")
|
32
|
+
opts.on("-i", "--internet", 'Abbr. "on the Internet" (host = "::")')
|
33
|
+
opts.on("-pNUM", "--port=NUM", Integer, "Port number (#{KDWATCH_PORT})")
|
34
|
+
opts.on("-[1-6]", "--[1-6]", Integer, "Abbr. port number (#{KDWATCH_PORT/10}x), must be last")
|
35
|
+
end
|
36
|
+
begin
|
37
|
+
op.parse!(into: options)
|
38
|
+
rescue OptionParser::InvalidOption => e
|
39
|
+
warn "** #{e}"
|
40
|
+
warn op
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
if options.internet
|
45
|
+
warn "** overriding host #{options.host} with ::" if options.host
|
46
|
+
options.host = "::"
|
47
|
+
else
|
48
|
+
options.host ||= "127.0.0.1"
|
49
|
+
end
|
50
|
+
if short_port = options[""]
|
51
|
+
port = short_port + KDWATCH_PORT/10*10
|
52
|
+
warn "** overriding port #{options.port} with #{port}" if options.port
|
53
|
+
options.port = port
|
54
|
+
else
|
55
|
+
options.port ||= KDWATCH_PORT
|
56
|
+
end
|
57
|
+
|
58
|
+
# p options
|
59
|
+
|
60
|
+
## -r: Kill any previous kdwatch and continue ("restart")
|
61
|
+
## -e: Kill any previous kdwatch and exit
|
62
|
+
if options.replace || options.end
|
63
|
+
require 'open3'
|
64
|
+
|
65
|
+
status = 1
|
66
|
+
|
67
|
+
lsof_host = case options.host
|
68
|
+
when "::", "0.0.0.0"
|
69
|
+
"" # can't do more specific with lsof; hope for the best
|
70
|
+
when /:/
|
71
|
+
"@'[#{options.host}]'"
|
72
|
+
else
|
73
|
+
"@'#{options.host}'"
|
74
|
+
end
|
75
|
+
|
76
|
+
stdout_str, stderr_str, s = Open3.capture3("lsof -ti #{lsof_host}:#{options.port} -s TCP:LISTEN")
|
77
|
+
pids = if s.success? && stdout_str =~ /\A[0-9\s]*\z/ && stderr_str
|
78
|
+
stdout_str.split
|
79
|
+
else
|
80
|
+
text = stdout_str + stderr_str
|
81
|
+
warn "** lsof, status #{s}, says: #{text}" if text != "" || s.exitstatus != 1
|
82
|
+
[]
|
83
|
+
end
|
84
|
+
if pids == []
|
85
|
+
warn "** Nothing listening on kdwatch port" unless options.replace
|
86
|
+
elsif pids.size != 1
|
87
|
+
warn "** More than one process listening on kdwatch port, nothing done"
|
88
|
+
else
|
89
|
+
begin
|
90
|
+
status = Process.kill(2, Integer(pids[0])) - 1 # should be 1 for 1 kill, exit 0 then
|
91
|
+
rescue Errno => e
|
92
|
+
warn "** #{pids[0]}: #{e.inspect}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
exit(status) if options.end
|
96
|
+
end
|
97
|
+
|
98
|
+
## Find an .mkd or a draft-*.md (excluding README.md and such)
|
6
99
|
if ARGV == []
|
7
|
-
ARGV.replace Dir["draft-*.md"]
|
100
|
+
ARGV.replace Dir.glob(["draft-*.md", "*.mkd"])
|
8
101
|
warn_replace = 1
|
9
102
|
end
|
10
103
|
|
11
104
|
if ARGV.size != 1
|
12
|
-
warn
|
13
|
-
|
14
|
-
|
105
|
+
warn op
|
106
|
+
if warn_replace
|
107
|
+
if ARGV.size > 1
|
108
|
+
warn "** More than one draft file found #{ARGV.inspect}"
|
109
|
+
warn "** Please select one for watching."
|
110
|
+
else
|
111
|
+
warn "** No draft file draft-*.md or *.mkd found."
|
112
|
+
end
|
113
|
+
end
|
15
114
|
exit 1
|
16
115
|
end
|
17
116
|
|
18
|
-
ENV["
|
117
|
+
ENV["KDWATCH_SRC"] = ARGV[0]
|
118
|
+
ENV["KDWATCH_HOST"] = options.host
|
119
|
+
ENV["KDWATCH_PORT"] = options.port.to_s
|
120
|
+
live_reload_port = options.port + 51234 # move up into ephemeral space
|
121
|
+
ENV["KDWATCH_LRPORT"] = live_reload_port.to_s
|
19
122
|
|
20
123
|
File.write(".config.ru", <<HERE)
|
21
124
|
require 'rack-livereload'
|
22
|
-
use Rack::LiveReload, min_delay: 500, source: :vendored, no_swf: true
|
125
|
+
use Rack::LiveReload, min_delay: 500, source: :vendored, no_swf: true, port: #{live_reload_port}, live_reload_port: #{live_reload_port}
|
23
126
|
require 'kdwatch-app.rb'
|
24
127
|
run Sinatra::Application
|
25
128
|
HERE
|
26
129
|
|
27
|
-
exec("rackup -E production -s thin -p
|
130
|
+
exec("rackup -E production -s thin -o #{options.host} -p #{options.port} .config.ru")
|
data/kdwatch.gemspec
CHANGED
@@ -28,10 +28,11 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_dependency "bundler", '~> 2.2'
|
30
30
|
spec.add_dependency "thin", '~> 1.8'
|
31
|
+
# spec.add_dependency "cabo-guard-livereload", '~> 2.5' #, require: false
|
31
32
|
spec.add_dependency "guard-livereload", '~> 2.5' #, require: false
|
32
33
|
spec.add_dependency "rack-livereload", '~> 0.3'
|
33
34
|
spec.add_dependency "guard", '~> 2.17'
|
34
35
|
spec.add_dependency "sinatra", '~> 2.1'
|
35
|
-
spec.add_dependency "kramdown-rfc2629", '~> 1.
|
36
|
+
spec.add_dependency "kramdown-rfc2629", '~> 1.5'
|
36
37
|
spec.add_dependency "net-http-persistent", '~> 4.0'
|
37
38
|
end
|
data/lib/kdwatch/version.rb
CHANGED
data/lib/kdwatch-app.rb
CHANGED
@@ -9,25 +9,49 @@ require "rack-livereload"
|
|
9
9
|
require "guard"
|
10
10
|
require "sinatra"
|
11
11
|
require "kramdown-rfc2629"
|
12
|
+
ENV["KDRFC_PREPEND"] = "time"
|
13
|
+
require "kramdown-rfc/kdrfc-processor"
|
12
14
|
require "net/http/persistent"
|
13
15
|
|
16
|
+
host = ENV["KDWATCH_HOST"]
|
17
|
+
port = ENV["KDWATCH_PORT"]
|
14
18
|
|
15
|
-
sfn = ENV["
|
19
|
+
sfn = ENV["KDWATCH_SRC"]
|
16
20
|
fail "No source given" unless sfn
|
17
21
|
|
18
22
|
dfn = File.join(File.dirname(sfn), "#{File.basename(sfn, ".*")}.html")
|
19
23
|
|
20
24
|
puts dfn
|
21
25
|
|
26
|
+
kdrfc = KramdownRFC::KDRFC.new
|
27
|
+
kdrfc.options.v3 = true
|
28
|
+
kdrfc.options.html = true
|
29
|
+
|
22
30
|
get "/" do
|
23
31
|
sfc = File.stat(sfn).ctime
|
24
32
|
dfc = File.stat(dfn).ctime rescue Time.at(0)
|
25
33
|
if sfc > dfc
|
26
34
|
warn "Rebuilding..."
|
27
|
-
|
28
|
-
|
35
|
+
begin
|
36
|
+
kdrfc.process sfn
|
37
|
+
rescue StandardError => e
|
38
|
+
warn e.to_s
|
39
|
+
else
|
40
|
+
warn "...done"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
dfc = File.stat(dfn).ctime rescue Time.at(0)
|
44
|
+
ret = File.read(dfn)
|
45
|
+
if sfc > dfc # somehow the above went wrong
|
46
|
+
ret.gsub!(<<CSS, <<RED)
|
47
|
+
/* general and mobile first */
|
48
|
+
html {
|
49
|
+
CSS
|
50
|
+
/* general and mobile first */
|
51
|
+
html { border: 5px solid red;
|
52
|
+
RED
|
29
53
|
end
|
30
|
-
|
54
|
+
ret
|
31
55
|
end
|
32
56
|
|
33
57
|
get "/metadata.min.js" do
|
@@ -39,17 +63,20 @@ get "/rfc-local.css" do
|
|
39
63
|
end
|
40
64
|
|
41
65
|
File.write(".Guardfile", <<GF)
|
42
|
-
guard
|
66
|
+
guard :livereload, :port => #{ENV["KDWATCH_LRPORT"]} do
|
43
67
|
watch("#{sfn}")
|
44
68
|
end
|
45
69
|
GF
|
46
70
|
|
47
71
|
rd, _wr = IO.pipe
|
48
|
-
spawn("guard -G .Guardfile", in: rd)
|
72
|
+
spawn("guard -G .Guardfile", in: rd, close_others: true)
|
49
73
|
|
50
74
|
# wrong: puts settings.port
|
51
75
|
|
52
|
-
|
76
|
+
host = "localhost" if host == "::" # work around macOS peculiarity
|
77
|
+
host = "[#{host}]" if host =~ /:/
|
78
|
+
|
79
|
+
url = "http://#{host}:#{port}"
|
53
80
|
|
54
81
|
spawn("sleep 5; open #{url} || xdg-open #{url} || echo @@@ Please open #{url}")
|
55
82
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kdwatch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carsten Bormann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '1.
|
103
|
+
version: '1.5'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '1.
|
110
|
+
version: '1.5'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: net-http-persistent
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- ".gitignore"
|
134
134
|
- Gemfile
|
135
135
|
- LICENSE.txt
|
136
|
+
- README.md
|
136
137
|
- bin/kdwatch
|
137
138
|
- kdwatch.gemspec
|
138
139
|
- lib/kdwatch-app.rb
|
@@ -156,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
157
|
- !ruby/object:Gem::Version
|
157
158
|
version: '0'
|
158
159
|
requirements: []
|
159
|
-
rubygems_version: 3.2.
|
160
|
+
rubygems_version: 3.2.22
|
160
161
|
signing_key:
|
161
162
|
specification_version: 4
|
162
163
|
summary: 'kdwatch: open auto-reloaded HTML for kramdown-rfc in a browser.'
|