jota 0.8.1 → 0.9.0dev2

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/lib/helper.rb CHANGED
@@ -1,146 +1,65 @@
1
1
 
2
- # $Id: helper.rb 52 2009-09-24 14:17:25Z dz $
3
-
4
- # if you use vim and don't like folds type zR
5
-
6
- def get_filename(filename, mode)
7
- #{{{1
8
- if filename.class == Symbol and filename == :ask then
9
- case mode
10
- when :save
11
- action = Gtk::FileChooser::ACTION_SAVE
12
- ok_button = Gtk::Stock::SAVE
13
- when :open
14
- action = Gtk::FileChooser::ACTION_OPEN
15
- ok_button = Gtk::Stock::OPEN
16
- else
17
- raise "Wrong mode #{mode} in helper:get_filename"
18
- end
19
-
20
- title = "Select Filename"
21
-
22
- dialog = Gtk::FileChooserDialog.new(
23
- title,
24
- nil,
25
- action,
26
- nil,
27
- [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
28
- [ok_button, Gtk::Dialog::RESPONSE_ACCEPT])
29
-
30
- case dialog.run
31
- when Gtk::Dialog::RESPONSE_ACCEPT
32
- filename = dialog.filename
33
- else
34
- filename = nil
35
- end
36
- dialog.destroy
37
- end
38
-
39
- if filename.nil? then
40
- return
41
- end
42
-
43
- return filename
44
- end #}}}1
45
-
46
-
47
- def array_to_color(arr)
48
- #{{{1
49
- return Gdk::Color.new(arr[0],arr[1],arr[2])
50
- end #}}}1
51
-
52
- def color_to_array(gdk_color)
53
- #{{{1
54
- return [gdk_color.red, gdk_color.green, gdk_color.blue]
55
- end #}}}1
2
+ # $Id: helper.rb 257 2010-05-02 19:47:26Z dz $
56
3
 
57
4
  def escape_from(str)
58
- #{{{1
59
5
  str.gsub!(/\n(>*)From /,"\n\\1>From ")
60
6
  return str
61
- end #}}}1
7
+ end
62
8
 
63
9
  def unescape_from(str)
64
- #{{{1
65
10
  str.gsub!(/\n(>*)>From /,"\n\\1From ")
66
11
  return str
67
- end #}}}1
12
+ end
68
13
 
69
14
  # expand strftime() time in str and expand %s to 'filename'
70
15
  def expand_filename(str, dirname, filename)
71
- #{{{1
72
16
  result = Time.now.strftime(str)
73
17
  result = result.gsub(/\$f/,filename)
74
- result = result.gsub(/\$d/,dirname)
18
+ result = result.gsub(/\$d/,dirname.gsub(/[^a-z0-9._-]+/i,"_"))
75
19
  result = result.gsub(/\$p/,Process::pid.to_s)
20
+ result = result.gsub(/\$h/,ENV["HOME"]?ENV["HOME"]:"/") # TODO on windows?
76
21
  result = result.gsub(/\$\$/,"$")
77
22
  print_debug "expanding '#{filename}' to '#{result}'"
78
23
  return result
79
- end #}}}1
80
-
81
- #
82
- # Locking
83
- #
84
-
85
- def obtain_shared_lock(file)
86
- #{{{1
87
- release_lock(file) # necessary for win32
88
-
89
- # a shared, non-blocking lock
90
- print_debug "obtaining SHARED LOCK on '#{file.path}'"
91
- if not file.flock(File::LOCK_SH|File::LOCK_NB) then
92
- print_debug " cannot lock"
93
- #file.flock(File::LOCK_SH) TODO
94
- end
95
- end #}}}1
96
-
97
- def obtain_exclusive_lock(file)
98
- #{{{1
99
- release_lock(file) # necessary for win32
100
-
101
- # an exclusive, non-blocking lock
102
- print_debug "obtaining EXCLUSIVE LOCK on '#{file.path}'"
103
- if not file.flock(File::LOCK_EX|File::LOCK_NB) then
104
- print_debug " cannot lock"
105
- #file.flock(File::LOCK_EX) TODO
106
- end
107
- end #}}}1
108
-
109
- def release_lock(file)
110
- #{{{1
111
- print_debug "releasing LOCK from '#{file.path}'"
112
- file.flock(File::LOCK_UN)
113
- end #}}}1
114
-
115
- def print_verbose(msg)
116
- #{{{1
117
- if $VERBOSE then
118
- debug_file.puts "#{Process.pid}# #{msg}"
119
- end
120
- end #}}}1
24
+ end
121
25
 
122
26
  def debug_file
123
27
  if $debug_file.nil? then
124
28
  begin
125
- $debug_file = File.open($debug_filename,"w+")
29
+ if $debug_filename then
30
+ $debug_file = File.open($debug_filename,"a")
31
+ print_verbose "logging to #{$debug_filename}"
32
+ else
33
+ $debug_file = $stdout
34
+ print_verbose "logging to stdout"
35
+ end
126
36
  rescue Exception => msg
127
37
  $debug_file = $stdout
128
- print_verbose "logging to '#{$debug_filename}' not possible: #{msg}"
38
+ print_verbose "logging to '#{$debug_filename}' "+
39
+ "not possible: #{msg}, using stdout"
129
40
  end
130
41
 
131
42
  end
132
43
  return $debug_file
133
44
  end
134
45
 
46
+ def print_verbose(msg)
47
+ if $VERBOSE then
48
+ # do not write to $debug_file, this can be nil
49
+ debug_file.puts "#{Process.pid}-1# #{msg}"
50
+ debug_file.flush
51
+ end
52
+ end
53
+
135
54
  def print_debug(msg)
136
- #{{{1
137
55
  if $DEBUG then
138
- debug_file.puts "#{Process.pid}- #{msg}"
56
+ # do not write to $debug_file, this can be nil
57
+ debug_file.puts "#{Process.pid}-2# #{msg}"
58
+ debug_file.flush
139
59
  end
140
- end #}}}1
60
+ end
141
61
 
142
62
  def editor(str)
143
- #{{{1
144
63
  file = Tempfile.new("jota")
145
64
  filename = file.path
146
65
  print_verbose "creating temporary file '#{filename}'"
@@ -151,7 +70,7 @@ def editor(str)
151
70
  if ENV["EDITOR"] then
152
71
  cmdline = ENV["EDITOR"]
153
72
  else
154
- cmdline = "/usr/bin/vi"
73
+ cmdline = "vi"
155
74
  end
156
75
  cmdline = "%s %s" % [cmdline, filename]
157
76
  print_verbose "executing '#{cmdline}'"
@@ -168,10 +87,9 @@ def editor(str)
168
87
  File.unlink(filename)
169
88
 
170
89
  return lines
171
- end #}}}1
90
+ end
172
91
 
173
92
  def q_encode(charset,str)
174
- #{{{1
175
93
  #if str =~ /^[ -<>@-^`-~]*$/ then # all printable except "=?_"
176
94
  if str =~ /[ -~]*/ then
177
95
  result = str
@@ -184,10 +102,9 @@ def q_encode(charset,str)
184
102
  end
185
103
 
186
104
  return result
187
- end #}}}1
105
+ end
188
106
 
189
107
  def q_decode(str)
190
- #{{{1
191
108
  md = /^=\?(.*)?\?Q\?(.*?)\?=/i.match(str)
192
109
  if md then
193
110
  charset = md[1]
@@ -198,6 +115,4 @@ def q_decode(str)
198
115
  end
199
116
 
200
117
  return str,charset
201
- end #}}}1
202
-
203
- # vim: set foldmethod=marker:
118
+ end
data/lib/immediate.rb ADDED
@@ -0,0 +1,63 @@
1
+
2
+ # $Id: $
3
+
4
+ require 'clip_array'
5
+ require 'version'
6
+
7
+ class Immediate
8
+
9
+ # Variables
10
+ # @data Clip_Array the clip array
11
+
12
+ def open(filename)
13
+ begin
14
+ new_data = ClipArray.open(filename)
15
+ rescue AppError, SystemCallError => msg
16
+ return nil
17
+ end
18
+
19
+ @data = new_data
20
+ return @data
21
+ end
22
+
23
+ def clip_array
24
+ return @data
25
+ end
26
+
27
+ def create
28
+ new = STDIN.readlines.join($/)
29
+ @data.new
30
+ @data.current.text = new
31
+ print_verbose "immediately creating clip '#{@data.current.title}'"
32
+ @data.close
33
+ end
34
+
35
+ def retrieve
36
+ puts @data.current.text
37
+ print_verbose "immediately retrieving clip '#{@data.current.title}'"
38
+ @data.close
39
+ end
40
+
41
+ def update
42
+ new = STDIN.readlines.join($/)
43
+ @data.current.text = new
44
+ print_verbose "immediately updating clip '#{@data.current.title}'"
45
+ @data.close
46
+ end
47
+
48
+ def delete
49
+ print_verbose "immediately deleting clip '#{@data.current.title}'"
50
+ @data.delete
51
+ @data.close
52
+ end
53
+
54
+ def list
55
+ print_verbose "immediately listing #{@data.length} clips"
56
+ @data.each do | c |
57
+ puts c.title! if c.type != :pref
58
+ end
59
+ @data.close
60
+ end
61
+
62
+
63
+ end # class Immediate
data/lib/jota.rb CHANGED
@@ -1,12 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # $Id: jota.rb 53 2009-09-24 14:22:04Z dz $
4
-
5
- # if you use vim and don't like folds type zR
3
+ # $Id: jota.rb 270 2010-06-02 16:00:02Z dz $
6
4
 
7
5
 
8
6
  require 'getoptlong'
9
7
  require 'helper'
8
+ require 'immediate'
10
9
  require 'version'
11
10
 
12
11
  class Jota
@@ -14,36 +13,71 @@ class Jota
14
13
  # from sysexits(3)
15
14
  EX_OK = 0
16
15
  EX_USAGE = 64
17
- EX_SOFTWARE = 70
18
16
 
19
- def usage
20
- #{{{1
21
- puts("%s Version %s, (C) %s %s" % [
17
+ private
18
+
19
+ def puts_version(full)
20
+ puts("%s Version %s, (C) %s %s <%s>" % [
22
21
  Version::PROGRAM_NAME,
23
22
  Version::STRING,
24
23
  Version::YEARS,
25
- Version::AUTHOR])
26
- puts
27
- puts("usage: #{$0} -dhv 'file' [ 'regular-expression' ]")
28
- puts("\t-v\t\tset verbose mode")
29
- puts("\t-d\t\tset debug mode")
24
+ Version::AUTHOR,
25
+ Version::AUTHOR_EMAIL])
26
+ if (full) then
27
+ print " using #{Version.ruby_version}"
28
+ begin
29
+ require "gui"
30
+ print " and #{Gui.gtk_version}"
31
+ rescue Exception
32
+ end
33
+ print " on #{Version.platform}"
34
+ puts
35
+ end
36
+ end
30
37
 
31
- puts("\t-D 'file'\twrite debug and verbose output to 'file'")
32
- puts("\t-t\t\tforce text mode")
33
- puts("\t-g\t\tforce graphical mode")
34
- puts("\t-h\t\tthis help")
35
- end #}}}1
38
+ def usage
39
+ puts_version(false)
36
40
 
41
+ puts
42
+ puts("usage: #{$0} 'options' 'file' [ 'regular-expression' ]")
43
+ puts
44
+ puts("MODES")
45
+ puts("\t--text or -t\t\t\tforce text mode")
46
+ puts("\t--gui or -g\t\t\tforce graphical mode")
47
+ puts
48
+ puts("IMMEDIATE MODE")
49
+ puts("\t--create or -C\t\t\tcreate a new clip from stdin ('regexp' ignored)")
50
+ puts("\t--retrieve or -R\t\twrite clip to stdout ('regexp' required)")
51
+ puts("\t--update or -U \t\t\tchange clip from stdin ('regexp' required)")
52
+ puts("\t--delete or -D \t\t\tdelete a clip ('regexp' required)")
53
+ puts("\t--list or -L\t\t\tlist all clips ('regexp' ignored)")
54
+ puts
55
+ puts("HELPING")
56
+ puts("\t--help or -h\t\t\tthis help")
57
+ puts("\t--version or -V\t\t\tshow version")
58
+ puts("\t--verbose or -v\t\t\tset verbose mode, -vv is more verbose ")
59
+ puts("\t--logfile or -f 'file'\t\twrite verbose output to 'file'")
60
+ end
61
+
62
+ def error(msg)
63
+ puts msg
64
+ puts
65
+ exit(EX_USAGE)
66
+ end
37
67
 
38
68
  def parse_args
39
- #{{{1
40
69
  opts = GetoptLong.new(
41
70
  [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
42
- [ '--debug', '-d', GetoptLong::NO_ARGUMENT ],
43
- [ '--debug-file', '-D', GetoptLong::REQUIRED_ARGUMENT ],
71
+ [ '--logfile', '-f', GetoptLong::REQUIRED_ARGUMENT ],
44
72
  [ '--text', '-t', GetoptLong::NO_ARGUMENT ],
45
73
  [ '--gui', '-g', GetoptLong::NO_ARGUMENT ],
46
- [ '--help', '-h', GetoptLong::NO_ARGUMENT ]
74
+ [ '--create', '-C', GetoptLong::NO_ARGUMENT ],
75
+ [ '--retrieve', '-R', GetoptLong::NO_ARGUMENT ],
76
+ [ '--update', '-U', GetoptLong::NO_ARGUMENT ],
77
+ [ '--delete', '-D', GetoptLong::NO_ARGUMENT ],
78
+ [ '--list', '-L', GetoptLong::NO_ARGUMENT ],
79
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
80
+ [ '--version', '-V', GetoptLong::NO_ARGUMENT ]
47
81
  )
48
82
 
49
83
  @force = nil
@@ -54,11 +88,11 @@ def parse_args
54
88
  opts.each do |opt, arg|
55
89
  case opt
56
90
  when '--verbose'
91
+ if $VERBOSE then
92
+ $DEBUG = true
93
+ end
57
94
  $VERBOSE = true
58
- when '--debug'
59
- $VERBOSE = true
60
- $DEBUG = true
61
- when '--debug-file'
95
+ when '--logfile'
62
96
  $debug_filename = arg
63
97
  when '--text'
64
98
  @force = :text
@@ -67,9 +101,26 @@ def parse_args
67
101
  when '--help'
68
102
  usage
69
103
  exit(EX_OK)
104
+ when '--version'
105
+ puts_version(true)
106
+ exit(EX_OK)
107
+ when '--create'
108
+ @force = :immediate
109
+ @immediate_cmd = :create
110
+ when '--retrieve'
111
+ @force = :immediate
112
+ @immediate_cmd = :retrieve
113
+ when '--update'
114
+ @force = :immediate
115
+ @immediate_cmd = :update
116
+ when '--delete'
117
+ @force = :immediate
118
+ @immediate_cmd = :delete
119
+ when '--list'
120
+ @force = :immediate
121
+ @immediate_cmd = :list
70
122
  else
71
- usage
72
- exit(EX_USAGE)
123
+ error("Illegal argument '#{opt}'")
73
124
  end
74
125
  end
75
126
  rescue GetoptLong::InvalidOption
@@ -87,64 +138,54 @@ def parse_args
87
138
  @filename = ARGV[0]
88
139
  @regexp = ARGV[1]
89
140
  else
90
- usage
91
- exit(EX_USAGE)
141
+ error("Illegal number of arguments")
92
142
  end
93
143
 
94
144
  if $VERBOSE then
95
145
  print_verbose "started at #{Time.now}"
96
- print_verbose "running version #{Version::STRING}, build #{Version::build}"
97
- print_verbose "verbose set to #{$VERBOSE}"
98
- print_verbose "debug set to #{$DEBUG}"
146
+ print_verbose "running version #{Version::STRING}"
147
+ print_verbose "verbose set to level 1" if $VERBOSE
148
+ print_verbose "verbose set to level 2" if $DEBUG
149
+ print_verbose "logfile set to '#{$debug_filename}'" if $VERBOSE and $debug_filename
99
150
  print_verbose "filename set to '#{@filename}'"
100
151
  print_verbose "regexp set to '#{@regexp}'"
152
+ print_verbose "forcing #{@force.to_s} mode"
153
+ print_verbose "using immediate command :#{@immediate_cmd.to_s}" if @force == :immediate
101
154
  end
102
- end #}}}1
155
+ end
103
156
 
104
- def run
105
- #{{{1
106
- parse_args
107
-
108
- begin
109
- # this 'require' must be after the command line is parsed,
110
- # because 'require libglade2' parses the commandline too.
111
- require 'gui'
112
- gui_ok = true
113
- rescue Exception
114
- gui_ok = false
157
+ def goto_or_fail(object,re)
158
+ if not object.clip_array.goto_regexp(re) then
159
+ error("Clip with title matching /#{re}/ not found.")
115
160
  end
161
+ end
116
162
 
117
- if @force == :text or gui_ok == false then
118
- require 'jota_curses'
119
- start_curses
120
- else
121
- start_gui
163
+ def open_or_fail(object,filename)
164
+ if not object.open(filename) then
165
+ error("File '#{filename}' not found.")
122
166
  end
123
-
124
- end #}}}1
167
+ end
125
168
 
126
169
  def start_curses
127
- #{{{1
128
170
  curses = JotaCurses.new
129
171
  if @filename then
130
- curses.open(@filename)
172
+ open_or_fail(curses,@filename)
131
173
  if @regexp then
132
- curses.goto_regexp(@regexp)
174
+ goto_or_fail(curses,@regexp)
133
175
  end
134
176
  end
135
177
 
136
178
  print_verbose "entering curses main loop"
137
179
 
138
180
  curses.run
139
- end # start_curses }}}1
181
+ end # start_curses
140
182
 
141
183
  def start_gui
142
- #{{{1
143
184
  glade = Gui.new
144
185
  if @filename then
145
- glade.open(@filename)
186
+ open_or_fail(glade,@filename)
146
187
  if @regexp
147
- glade.goto_regexp(@regexp)
188
+ goto_or_fail(glade,@regexp)
148
189
  end
149
190
  end
150
191
 
@@ -165,57 +206,87 @@ def start_gui
165
206
  Gtk::Dialog::MODAL,
166
207
  Gtk::MessageDialog::ERROR,
167
208
  Gtk::MessageDialog::BUTTONS_NONE,
168
- "Oops! I am about to crash")
209
+ "Oops! I crashed")
169
210
  msgbox.title = "Internal Error"
170
- msgbox.secondary_text = "You are strongly advised to save your data "+
171
- "as soon as possible and restart the program."+
211
+ msgbox.secondary_text = "I'm terribly sorry."+
172
212
  "\n\nDetails:\n#{e.class}: #{e.message}"
173
- msgbox.add_button("Crash",Gtk::Dialog::RESPONSE_CANCEL)
174
- msgbox.add_button("Recover",Gtk::Dialog::RESPONSE_OK)
175
-
213
+ msgbox.add_button("Crash",Gtk::Dialog::RESPONSE_OK)
214
+
176
215
  msgbox.run do | response |
177
216
  case response
178
217
  when Gtk::Dialog::RESPONSE_OK
179
218
  msgbox.destroy
180
- sleep 2
181
- print_verbose "recovering"
182
- puts "recovering"
183
- retry
184
- when Gtk::Dialog::RESPONSE_CANCEL
185
- msgbox.destroy
186
- exit(EX_SOFTWARE)
219
+ exit(EX_OK)
220
+ end
221
+ end
222
+ end
223
+ end # start_gui
224
+
225
+ def start_immediate
226
+ im = Immediate.new
227
+ regexp_necessary = { :create => false,
228
+ :retrieve => true,
229
+ :update => true,
230
+ :delete => true,
231
+ :list => false}
232
+ if @filename then
233
+ open_or_fail(im,@filename)
234
+ if regexp_necessary[@immediate_cmd] then
235
+ if @regexp then
236
+ goto_or_fail(im,@regexp) # @regexp may be nil
237
+ else
238
+ error("Illegal number of arguments")
239
+ end
240
+ else
241
+ if @regexp then
242
+ puts "Regexp /#{@regexp}/ ignored."
243
+ print_verbose "ignoring regexp /#{@regexp}/"
187
244
  end
188
245
  end
246
+ else
247
+ error("Illegal number of arguments")
189
248
  end
190
- end # start_gui }}}1
191
249
 
192
- def run_cli
193
- #{{{1
194
- require 'cli'
250
+ print_verbose "executing #{@immediate_cmd} immediately"
251
+ im.send(@immediate_cmd)
252
+ end # start_immediate
195
253
 
254
+ public
255
+
256
+ def run
196
257
  parse_args
197
258
 
198
- cli = JotaCli.new
199
- if @filename then
200
- cli.do_open(@filename)
201
- if @regexp then
202
- cli.do_edit(@regexp)
203
- end
259
+ begin
260
+ # this 'require' must be after the command line is parsed,
261
+ # because 'require libglade2' parses the commandline too.
262
+ require 'gui'
263
+ gui_ok = true
264
+ rescue Exception
265
+ gui_ok = false
204
266
  end
205
267
 
206
- # If ARGV is empty, Cmd runs in a loop, otherwise it runs only once.
207
-
208
- # in short: no arg -> loop
209
- # only filename -> loop
210
- # filename + re -> once
268
+ if @force == :immediate then
269
+ start_immediate
270
+ elsif @force == :gui and not gui_ok then
271
+ puts "GUI not available (leave out the option '-g' or '--gui')"
272
+ elsif @force == :text or not gui_ok then
273
+ begin
274
+ require "jota_curses"
275
+ rescue LoadError
276
+ if :gui_ok then
277
+ error("Cannot load 'ncurses', try '--gui'")
278
+ else
279
+ error("Cannot load 'GTK+' nor 'ncurses'")
280
+ end
281
+ end
282
+ start_curses
283
+ else
284
+ start_gui
285
+ end
211
286
 
212
- if @filename and @regexp.nil? then # i.e. only one arg
213
- ARGV.clear
287
+ if $VERBOSE then
288
+ print_verbose "stopped at #{Time.now}"
214
289
  end
215
-
216
- cli.run
217
- end # run_cli }}}1
290
+ end
218
291
 
219
292
  end # class Jota
220
-
221
- # vim: set foldmethod=marker: