qmk-cli 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 915b0f8e03509b8c776660b1a9f335441707e1b4
4
+ data.tar.gz: f4541bde947171682ffa95db7b2d92084d458a5a
5
+ SHA512:
6
+ metadata.gz: 9aa6510c0fbad4586d251fab54ae968ee74542c83c596b87cf32e9480d54e3b68a44a017531a878afa19e0efa866b4ce6a57f8308ae679b2e86bf0dbb0229567
7
+ data.tar.gz: 1d0050383637fc83085fd80fd91a7e9f32049695df559abc0e14d5bed3e7a0d42dcc2f3269e3dc78891dc712e07436b8ae33b63e56917b4e380ae007fef31e35
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/LICENSE.txt ADDED
@@ -0,0 +1,5 @@
1
+ Copyright 2018 Nic Haynes
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,15 @@
1
+ .PHONY: build
2
+ build: clean
3
+ @gem build qmk_cli.gemspec
4
+
5
+ .PHONY: install
6
+ install:
7
+ @gem install *.gem
8
+
9
+ .PHONY: publish
10
+ publish: build
11
+ @gem push *.gem
12
+
13
+ .PHONY: clean
14
+ clean:
15
+ @rm -f *.gem
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # qmk-cli
2
+
3
+ A thin wrapper around QMK's `make` to make common tasks easier.
4
+
5
+ ## Why use this?
6
+
7
+ - Flashing is more intuitive (Example: `qmk flash planck`)
8
+ - Automatic programmer detection (No more "Does this board use dfu-programmer/avrdude/teensy/other?")
9
+ - Supports standalone keymaps
10
+
11
+ ## Usage
12
+
13
+ Usage:
14
+ qmk COMMAND [options]
15
+
16
+ Commands:
17
+ flash KEYBOARD Flash a keyboard
18
+ build KEYBOARD Compile a keyboard
19
+ clean [KEYBOARD] Cleans up output folders so things compile from scratch
20
+ setup Clone QMK firmware and checkout latest tag
21
+ update Update QMK firmware to latest tag
22
+
23
+ Options:
24
+ -k, --keymap KEYMAP Your keymap name (default: `whoami`)
25
+ -h, --help Show this help message
26
+
27
+ ## Standalone keymaps
28
+
29
+ - Add a `.qmk` file in your keymaps directory to designate this a standalone keymaps directory.
30
+ - Keyboard directories should be at the root with the keymap files inside. Since these are *your* keymaps there's no need to add additional namespacing.
31
+
32
+ View [nicinabox/keymaps](https://github.com/nicinabox/keymaps) for a complete example on how standalone keymaps should be organized.
33
+
34
+ ## Platforms
35
+
36
+ - [x] macOS
37
+ - [x] linux, probably
38
+ - [ ] windows
39
+
40
+ ## Requirements
41
+
42
+ - Ruby >= 2
43
+ - Git
44
+ - [build tools](https://docs.qmk.fm/getting_started_build_tools.html)
45
+
46
+ ## License
47
+
48
+ ISC
data/bin/qmk ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cli'
4
+
5
+ QMK::CLI.new(ARGV)
data/lib/cli.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'optparse'
2
+ require 'firmware'
3
+
4
+ USAGE = <<-USAGE
5
+ Usage:
6
+ qmk COMMAND [options]
7
+
8
+ Commands:
9
+ flash KEYBOARD Flash a keyboard
10
+ build KEYBOARD Compile a keyboard
11
+ clean [KEYBOARD] Cleans up output folders so things compile from scratch
12
+ keyboards List available keyboards (scope with --keymap)
13
+ setup Clone QMK firmware and checkout latest tag
14
+ update Update QMK firmware to latest tag
15
+
16
+ Options:
17
+ USAGE
18
+
19
+ module QMK
20
+ class CLI
21
+ def initialize(args)
22
+ @options = parser(args)
23
+ command, keyboard = args
24
+ @firmware = Firmware.new(keyboard, @options[:keymap], keymaps_only?)
25
+
26
+ self.send(parse_command(command || 'help'))
27
+ end
28
+
29
+ def setup
30
+ @firmware.setup
31
+ end
32
+
33
+ def update
34
+ @firmware.update
35
+ @firmware.update_submodules
36
+ end
37
+
38
+ def build
39
+ @firmware.make
40
+ end
41
+
42
+ def flash
43
+ @firmware.make @firmware.programmer
44
+ end
45
+
46
+ def clean
47
+ @firmware.make 'clean'
48
+ end
49
+
50
+ def keyboards
51
+ puts @firmware.keyboards
52
+ end
53
+
54
+ def help
55
+ puts @options[:help]
56
+ end
57
+
58
+ private
59
+ def parser(args)
60
+ options = {}
61
+
62
+ OptionParser.new do |parser|
63
+ parser.banner = USAGE
64
+
65
+ options[:keymap] = keymaps_only? ? `whoami`.strip : nil
66
+ parser.on("-k", "--keymap KEYMAP", "Your keymap name (default: #{options[:keymap]})") do |v|
67
+ options[:keymap] = v
68
+ end
69
+
70
+ options[:help] = parser
71
+ parser.on("-h", "--help", "Show this help message")
72
+ end.parse!
73
+
74
+ options
75
+ end
76
+
77
+ def parse_command(cmd)
78
+ cmd.gsub(/\-/, '_').downcase
79
+ end
80
+
81
+ def keymaps_only?
82
+ File.exists? '.qmk'
83
+ end
84
+
85
+ def method_missing(*args)
86
+ help
87
+ end
88
+ end
89
+ end
data/lib/firmware.rb ADDED
@@ -0,0 +1,136 @@
1
+ require 'fileutils'
2
+ require 'open3'
3
+ require 'programmer'
4
+ require 'git'
5
+
6
+ LIB_PATH = "/usr/local/lib/qmk_firmware"
7
+
8
+ module QMK
9
+ class Firmware
10
+ def initialize(keyboard, keymap, keymaps_only)
11
+ @keyboard = keyboard
12
+ @keymap = keymap
13
+ @repo = Git.new(LIB_PATH)
14
+ @keymaps_only = keymaps_only
15
+ end
16
+
17
+ def make(target = nil)
18
+ if @keymaps_only
19
+ prepare_firmware
20
+ end
21
+
22
+ in_repo do
23
+ run "make #{make_target(target)}"
24
+ end
25
+ end
26
+
27
+ def setup
28
+ @repo.clone 'https://github.com/qmk/qmk_firmware.git'
29
+
30
+ in_repo do
31
+ @repo.checkout_latest_tag
32
+ end
33
+ end
34
+
35
+ def update_submodules
36
+ in_repo do
37
+ run "make git-submodule"
38
+ end
39
+ end
40
+
41
+ def checkout_stable
42
+ in_repo do
43
+ @repo.fetch_origin
44
+ @repo.checkout_latest_tag
45
+ end
46
+ end
47
+
48
+ def update
49
+ in_repo do
50
+ @repo.clean
51
+ checkout_stable
52
+ end
53
+ end
54
+
55
+ def keyboards
56
+ if @keymaps_only
57
+ standalone_keyboards
58
+ else
59
+ qmk_keyboards @keymap
60
+ end
61
+ end
62
+
63
+ def standalone_keyboards
64
+ Dir["**/keymap.c"]
65
+ .map {|path| File.dirname(path) }
66
+ .sort
67
+ end
68
+
69
+ def qmk_keyboards(keymap=nil)
70
+ Dir["#{keyboards_path}/**/#{keymap}/keymap.c"]
71
+ .map {|path|
72
+ File.dirname(path)
73
+ .gsub(keyboards_path, '')
74
+ .split('/')
75
+ .reject(&:empty?)
76
+ .first
77
+ }
78
+ .uniq
79
+ .sort
80
+ end
81
+
82
+ def keyboard_name
83
+ @keyboard.gsub(/\/rev.*/, '')
84
+ end
85
+
86
+ def programmer
87
+ Programmer.new(keyboard_path).flasher
88
+ end
89
+
90
+ private
91
+ def in_repo(&block)
92
+ @repo.in_repo &block
93
+ end
94
+
95
+ def run(cmd)
96
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
97
+ while line = stdout.gets
98
+ puts line
99
+ end
100
+ end
101
+ end
102
+
103
+ def prepare_firmware
104
+ keyboard_path = File.expand_path "./#{keyboard_name}"
105
+ files = Dir.glob "#{keyboard_path}/*"
106
+
107
+ FileUtils.mkdir_p keymap_path
108
+ FileUtils.cp_r files, keymap_path
109
+ end
110
+
111
+ def make_target(target = nil)
112
+ return target unless @keyboard
113
+ [@keyboard, @keymap, target].compact.join(':')
114
+ end
115
+
116
+ def keyboards_path
117
+ "#{@repo.path}/keyboards"
118
+ end
119
+
120
+ def keyboard_path
121
+ "#{keyboards_path}/#{keyboard_name}"
122
+ end
123
+
124
+ def keymap_path
125
+ if handwired?
126
+ keyboard_path
127
+ else
128
+ "#{keyboard_path}/keymaps/#{@keymap}"
129
+ end
130
+ end
131
+
132
+ def handwired?
133
+ @keyboard =~ /handwired/
134
+ end
135
+ end
136
+ end
data/lib/git.rb ADDED
@@ -0,0 +1,41 @@
1
+ module QMK
2
+ class Git
3
+ def initialize(repo_path)
4
+ @repo_path = repo_path
5
+ end
6
+
7
+ def path
8
+ @repo_path
9
+ end
10
+
11
+ def ensure_path_exists
12
+ `mkdir -p #{@repo_path}`
13
+ end
14
+
15
+ def clone(repo)
16
+ ensure_path_exists
17
+ `git clone #{repo} #{@repo_path}`
18
+ end
19
+
20
+ def fetch_origin
21
+ `git fetch origin master`
22
+ end
23
+
24
+ def checkout_latest_tag
25
+ `git checkout #{latest_tag}`
26
+ end
27
+
28
+ def latest_tag
29
+ `git describe --tags $(git rev-list --tags --max-count=1)`
30
+ end
31
+
32
+ def clean
33
+ `git checkout .`
34
+ `git clean -df`
35
+ end
36
+
37
+ def in_repo(&block)
38
+ Dir.chdir @repo_path, &block
39
+ end
40
+ end
41
+ end
data/lib/makefile.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'tempfile'
2
+
3
+ class Makefile
4
+ def initialize(include_makefile)
5
+ @include_makefile = include_makefile
6
+ @file = Tempfile.new('makefile')
7
+
8
+ write
9
+ end
10
+
11
+ def write
12
+ @file.write contents
13
+ @file.close
14
+ end
15
+
16
+ def run(variable)
17
+ `make -f #{@file.path} -f #{@include_makefile} print-#{variable.upcase}`
18
+ end
19
+
20
+ def value(variable)
21
+ output = run variable
22
+ _, value = parse output
23
+ value
24
+ end
25
+
26
+ def parse(output)
27
+ match = output.match /^(\w+)=(.+)/
28
+ if match
29
+ [match[1], match[2]]
30
+ end
31
+ end
32
+
33
+ def contents
34
+ <<-contents
35
+ .PHONY: print-%
36
+ print-%:
37
+ \t@echo '$*=$($*)'
38
+ contents
39
+ end
40
+ end
data/lib/programmer.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'makefile'
2
+
3
+ FLASHERS = {
4
+ 'dfu': ['lufa-dfu', 'qmk-dfu', 'atmel-dfu'],
5
+ 'avrdude': ['caterina', 'usbasploader'],
6
+ 'teensy': 'halfkay',
7
+ }
8
+
9
+ BOOTLOADERS = {
10
+ 'halfkay': ['512', '1024'],
11
+ 'atmel-dfu': '4096',
12
+ 'usbasploader': '2048',
13
+ }
14
+
15
+ class Programmer
16
+ def initialize(keyboard_path)
17
+ @keyboard_path = keyboard_path
18
+ end
19
+
20
+ def bootloader
21
+ filename = "#{@keyboard_path}/rules.mk"
22
+ parse_bootloader_name(filename) if File.exists? filename
23
+ end
24
+
25
+ def flasher
26
+ bootloader and FLASHERS.each do |k, v|
27
+ break k if v.include? bootloader.downcase
28
+ end
29
+ end
30
+
31
+ private
32
+ def bootloader_from_size(size)
33
+ size and BOOTLOADERS.each do |k, v|
34
+ break k.to_s if v.include? size
35
+ end
36
+ end
37
+
38
+ def parse_bootloader_name(filename)
39
+ make = Makefile.new(filename)
40
+ name = make.value 'BOOTLOADER'
41
+ return name if name
42
+
43
+ size = make.value 'BOOTLOADER_SIZE'
44
+ return bootloader_from_size(size) if size
45
+
46
+ opt_defs = make.value 'OPT_DEFS'
47
+ match = opt_defs.match /BOOTLOADER_SIZE=(\w+)/
48
+ return bootloader_from_size(match[1]) if match
49
+ end
50
+ end
data/qmk_cli.gemspec ADDED
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "qmk-cli"
3
+ s.version = "0.2.0"
4
+ s.date = "2018-02-27"
5
+ s.summary = "A cli wrapper for QMK Firmware"
6
+ s.authors = ["Nic Haynes"]
7
+ s.email = "nic@nicinabox.com"
8
+ s.files = `git ls-files -z`.split("\x0")
9
+ s.homepage = "https://github.com/nicinabox/qmk-cli"
10
+ s.license = "MIT"
11
+
12
+ s.executables << "qmk"
13
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qmk-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Nic Haynes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: nic@nicinabox.com
15
+ executables:
16
+ - qmk
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - LICENSE.txt
22
+ - Makefile
23
+ - README.md
24
+ - bin/qmk
25
+ - lib/cli.rb
26
+ - lib/firmware.rb
27
+ - lib/git.rb
28
+ - lib/makefile.rb
29
+ - lib/programmer.rb
30
+ - qmk_cli.gemspec
31
+ homepage: https://github.com/nicinabox/qmk-cli
32
+ licenses:
33
+ - MIT
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 2.5.2
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: A cli wrapper for QMK Firmware
55
+ test_files: []