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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc8f8c23c6efa56df70b322eb61dc16b913fdf1a93640d3de4da1feeadfba752
4
- data.tar.gz: ab67e9ebabd65974a86d65f89a0ffc20af380a1806a13501fa6ecefb07076663
3
+ metadata.gz: 77f59a0c0a41535d090f2b858a44759a830b7cddc4e760a39c75613f06d2b37f
4
+ data.tar.gz: 6c53346765beb3f0391991db58bda4f00debfed880b8dca8763462567bbcd435
5
5
  SHA512:
6
- metadata.gz: c072cf5ae36599a794e6af8520f2fb0d4cb31d87441cec63c9e9137198bea04f4169b553a173787b1073759f04e27603f162b20ca8b0df745f24b2be4b1aa033
7
- data.tar.gz: '012684f1584c8f9ddb902a52369510b137840d9a29bac34732cc1939821d6ae96f6598bd57eb925515f9715936935351aa123fd4c9f619c63976b99274e174fc'
6
+ metadata.gz: d9c2df05241e752a0d7d80e34cf8324872110a0aa4bc800bb9ef7ec1afe0ad2034b06691b56d84c14a6462c252606ef371cad1f85f021ac424046c09dcdc5182
7
+ data.tar.gz: 001ca06bd402115c0d63e8cd06e3558a99787f12ba97b9641c158ec8f9f8d87f99cdea3850a5121b28f53336d14c1312c13ec037ace624b97c19effba70fdea8
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ *.gem
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 "** Usage: #$0 [draft-foo.md]"
13
- warn "** More than one draft file found #{ARGV.inspect}" if warn_replace
14
- warn "** Please select one for watching." if warn_replace
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["KD_WATCH_SRC"] = ARGV[0]
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 7991 .config.ru")
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.4'
36
+ spec.add_dependency "kramdown-rfc2629", '~> 1.5'
36
37
  spec.add_dependency "net-http-persistent", '~> 4.0'
37
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kdwatch
4
- VERSION = "0.1.0"
4
+ VERSION = "0.4.0"
5
5
  end
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["KD_WATCH_SRC"]
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
- system("time kdrfc -3h --no-txt #{sfn}")
28
- warn "...done"
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
- File.read(dfn)
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 'livereload' do
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
- url = "http://127.0.0.1:7991"
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.1.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-07-03 00:00:00.000000000 Z
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.4'
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.4'
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.15
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.'