openai-please 0.1.2 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d2e77c2b839915788f9db15c6f6a75b90d3c52c4a9033f3145aa687ff0d21a3
4
- data.tar.gz: b021e9384596d305d472224ee726cd9a4f16c514cc378c051d079b1ac9c58555
3
+ metadata.gz: de7075efdfbec978dc13fa6621f80e9e146e81cffb9652b19c17577befb4258a
4
+ data.tar.gz: 22fcdec50244d7d02826e25a3f4fb7a5e542f151da749ab67d7d9a3de0e7d7cb
5
5
  SHA512:
6
- metadata.gz: 3f349c795f25116281574e882f2299104654d399a29dc7481d1066ca576d8f6bb2f754b25dd12d6d9725aa4edc677fac7bb827e10307a69caee0da03f471cee9
7
- data.tar.gz: 97014f5dfc48adb96767c9b52996511d1cc2d1666256c0f8720181503b9aa9780c5c81ad34ae384c8e880ac9c853e3c9b25f795a0ccad78a6fab27a002f02e32
6
+ metadata.gz: 7aa0a478868627ba84898ca812958f5c37a46bd0872fe4ddbba4d1c222d2700f0d887b0e7ba207683e3a4620e9a73c63e61d73f77e6bf76f8b422a9f54a2bbf6
7
+ data.tar.gz: 978bcfb2597c5b2f7c1157cedd755b6a058395c9d844472649524ddc9531d5f9a4fde7e6f7af5dd237ed4801274f3274d14753cfd6c25e65387ff16b38ee2250
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  .env
10
+ config.yml
data/.rubocop.yml CHANGED
@@ -19,8 +19,15 @@ Style/TrailingCommaInArguments:
19
19
  Enabled: true
20
20
  EnforcedStyleForMultiline: comma
21
21
 
22
+ Style/TrailingCommaInArrayLiteral:
23
+ Enabled: true
24
+ EnforcedStyleForMultiline: comma
25
+
22
26
  Style/Documentation:
23
27
  Enabled: false
24
28
 
29
+ Layout/MultilineMethodCallIndentation:
30
+ Enabled: false
31
+
25
32
  Layout/LineLength:
26
- Max: 120
33
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openai-please (0.1.1)
4
+ openai-please (0.1.2)
5
5
  ruby-openai (>= 1.3)
6
6
  tty-prompt (>= 0.23)
7
7
 
data/docker-compose.yml CHANGED
@@ -8,3 +8,4 @@ services:
8
8
  env_file: .env
9
9
  volumes:
10
10
  - '.:/app'
11
+ - './config.yml:/root/.config/please/config.yml:ro'
data/lib/please/cli.rb CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  require 'English'
4
4
  require 'tty-prompt'
5
+ require 'yaml'
5
6
  require 'optparse'
6
7
  require 'please'
7
8
  require 'tempfile'
8
9
 
10
+ USAGE = 'Usage: please [options] <instruction>'
11
+ CONFIG_FILE_PATH = File.expand_path('~/.config/please/config.yml')
12
+
9
13
  begin
10
14
  tty_prompt = TTY::Prompt.new
11
15
 
@@ -14,13 +18,27 @@ begin
14
18
  send_pwd: true,
15
19
  send_uname: true,
16
20
  send_ls: true,
21
+ access_token: ENV.fetch('OPENAI_ACCESS_TOKEN', nil),
22
+ examples: [],
23
+ skip_default_examples: false,
17
24
  }
18
25
 
19
- USAGE = 'Usage: please [options] <instruction>'
26
+ if File.exist?(CONFIG_FILE_PATH)
27
+ begin
28
+ options.merge! YAML.load_file(CONFIG_FILE_PATH).transform_keys(&:to_sym)
29
+ options[:examples].each { |example| example.transform_keys!(&:to_sym) }
30
+ rescue StandardError
31
+ tty_prompt.warn 'Could not parse config file. Ignoring.'
32
+ end
33
+ end
20
34
 
21
35
  OptionParser.new do |opts|
22
36
  opts.banner = USAGE
23
37
 
38
+ opts.on('--show-config-path', 'Output the location of the config file, and then exit') do |v|
39
+ options[:show_config_path] = v
40
+ end
41
+
24
42
  opts.on('--show-prompt', 'Output the prompt that would ordinarily be sent to OpenAI Codex, and then exit') do |v|
25
43
  options[:show_prompt] = v
26
44
  end
@@ -38,12 +56,17 @@ begin
38
56
  end
39
57
  end.parse!
40
58
 
41
- access_token = ENV.fetch('OPENAI_ACCESS_TOKEN') do
42
- tty_prompt.error 'Ensure the OPENAI_ACCESS_TOKEN environment variable is set'
59
+ if options[:show_config_path]
60
+ tty_prompt.say CONFIG_FILE_PATH
61
+ exit
62
+ end
63
+
64
+ if options[:access_token].nil?
65
+ tty_prompt.error "Access token not found. Set it in #{CONFIG_FILE_PATH} or $OPENAI_ACCESS_TOKEN."
43
66
  exit 1
44
67
  end
45
68
 
46
- codex_service = Please::OpenAI::CodexService.new(access_token: access_token)
69
+ codex_service = Please::OpenAI::CodexService.new(access_token: options[:access_token])
47
70
 
48
71
  instruction = ARGV.join(' ')
49
72
 
@@ -1,30 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ DEFAULT_EXAMPLES = [
4
+ {
5
+ instruction: 'Find all files older than 1 week and open each of them in vim',
6
+ command: 'find . -type f -mtime +7 -exec vim {} \;',
7
+ },
8
+
9
+ {
10
+ instruction: 'Show a clock which updates every second on a single line',
11
+ command: 'printf \'import time\nwhile True:\n\tprint(time.strftime("%%H:%%M:%%S"), end="\\\\r")\n\ttime.sleep(1)\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
12
+ },
13
+
14
+ {
15
+ instruction: 'Write a python program that prints out hello world with each letter on its own line',
16
+ command: 'printf \'print("\\\\n".join(list("Hello World"))\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
17
+ },
18
+
19
+ {
20
+ instruction: 'Read from stdin until EOF, and then output the length of the string',
21
+ command: 'printf \'import sys\nprint(len(sys.stdin.read().strip()))\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
22
+ },
23
+
24
+ {
25
+ instruction: 'Run the fortune command 5 times',
26
+ command: 'for i in $(seq 5); do fortune; done',
27
+ },
28
+
29
+ {
30
+ instruction: 'Repeadedly read a single line from the user, reverse it, and print it back',
31
+ command: 'printf \'while True:\n\tline = input()\n\tprint(line[::-1])\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
32
+ },
33
+ ].freeze
34
+
35
+ OPTIONAL_EXAMPLES = {
36
+ pwd: {
37
+ instruction: 'Print the current working directory',
38
+ command: 'pwd',
39
+ execute: true,
40
+ },
41
+
42
+ uname: {
43
+ instruction: 'Show information about the operating system',
44
+ command: 'uname -a',
45
+ execute: true,
46
+ },
47
+
48
+ ls: {
49
+ instruction: 'List all files in the current directory',
50
+ command: 'ls -a',
51
+ execute: true,
52
+ },
53
+ }.freeze
54
+
3
55
  module Please
4
56
  class Context
5
57
  def initialize(options)
6
- @examples = default_examples
58
+ @examples = []
7
59
 
8
- if options[:send_pwd]
9
- @examples << {
10
- instruction: 'Print the current working directory',
11
- command: 'pwd',
12
- }
13
- end
60
+ @examples += DEFAULT_EXAMPLES unless options[:skip_default_examples]
14
61
 
15
- if options[:send_uname]
16
- @examples << {
17
- instruction: 'Show information about the operating system',
18
- command: 'uname -a',
19
- }
20
- end
62
+ @examples << OPTIONAL_EXAMPLES[:pwd] if options[:send_pwd]
63
+ @examples << OPTIONAL_EXAMPLES[:uname] if options[:send_uname]
64
+ @examples << OPTIONAL_EXAMPLES[:ls] if options[:send_ls]
21
65
 
22
- if options[:send_ls]
23
- @examples << {
24
- instruction: 'List all files in the current directory',
25
- command: 'ls -a',
26
- }
27
- end
66
+ @examples += options[:examples]
28
67
  end
29
68
 
30
69
  def to_s
@@ -32,45 +71,9 @@ module Please
32
71
  <<~EXAMPLE.chomp
33
72
  # #{example[:instruction]}
34
73
  $ #{example[:command]}
35
- #{example.fetch(:result) { `#{example[:command]}` }}
74
+ #{example[:execute] ? `#{example[:command]}` : ""}
36
75
  EXAMPLE
37
76
  end.join("\n")
38
77
  end
39
-
40
- private
41
-
42
- def default_examples
43
- [
44
- {
45
- instruction: 'Find all files older than 1 week and open each of them in vim',
46
- command: 'find . -type f -mtime +7 -exec vim {} \;',
47
- result: '',
48
- },
49
-
50
- {
51
- instruction: 'Download a random dog picture',
52
- command: 'printf \'import urllib.request\nimport json\nimport subprocess\ndata = urllib.request.urlopen("https://dog.ceo/api/breeds/image/random").read()\nurl = json.loads(data)["message"]\nsubprocess.call(["curl", url, "-o", "dog.jpg"])\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
53
- result: '',
54
- },
55
-
56
- {
57
- instruction: 'Read from stdin until EOF, and then output the length of the string',
58
- command: 'printf \'import sys\nprint(len(sys.stdin.read().strip()))\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
59
- result: '',
60
- },
61
-
62
- {
63
- instruction: 'Run the fortune command 5 times',
64
- command: 'for i in $(seq 5); do fortune; done',
65
- result: '',
66
- },
67
-
68
- {
69
- instruction: 'Repeadedly read a single line from the user, reverse it, and print it back',
70
- command: 'printf \'while True:\n\tline = input()\n\tprint(line[::-1])\' > /tmp/program.py; python3 /tmp/program.py; rm /tmp/program.py',
71
- result: '',
72
- },
73
- ]
74
- end
75
78
  end
76
79
  end
@@ -8,7 +8,7 @@ module Please
8
8
  # Collapse multiline commands into one line
9
9
  .gsub(/\s*\\\n\s*/, ' ')
10
10
  # Remove subsequent lines that do not contain commands
11
- .gsub(/\n[^\$][^\n]*$/, '')
11
+ .gsub(/\n[^$][^\n]*$/, '')
12
12
  # Collapse multiple commands into one line
13
13
  .gsub(/\n\$ /, '; ')
14
14
  # Remove multiple consecutive spaces
@@ -19,7 +19,7 @@ module Please
19
19
  <<~PROMPT.chomp
20
20
  Write a one-line bash command for each of the following tasks.
21
21
 
22
- #{context.to_s}
22
+ #{context}
23
23
 
24
24
  # #{instruction.gsub(/\n/, " ")}
25
25
  $
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Please
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openai-please
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Anderson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-15 00:00:00.000000000 Z
11
+ date: 2021-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-openai