Class: Xiki

Inherits:
Object show all
Defined in:
lib/xiki.rb,
lib/xiki.rb

Overview

Launcher.add_class_launchers classes

Constant Summary collapse

@@dir =

Store current dir when xiki first launches

"#{Dir.pwd}/"

Class Method Summary collapse

Class Method Details

.dirObject

TODO Just use XIKI_DIR from above?



10
11
12
# File 'lib/xiki.rb', line 10

def self.dir
  @@dir
end

.dont_searchObject



219
220
221
222
# File 'lib/xiki.rb', line 219

def self.dont_search
  $xiki_no_search = true
  nil
end

.dont_show_welcomeObject



465
466
467
# File 'lib/xiki.rb', line 465

def self.dont_show_welcome
  Menu.append_line "misc config", "- don't show welcome"
end

.finished_loading?Boolean

Returns:

  • (Boolean)


469
470
471
# File 'lib/xiki.rb', line 469

def self.finished_loading?
  @@finished_loading
end

.github(page) ⇒ Object



211
212
213
214
215
216
217
# File 'lib/xiki.rb', line 211

def self.github page
  Firefox.url case page
    when 'files'; "http://github.com/trogdoro/xiki"
    when 'commits'; "https://github.com/trogdoro/xiki/commits/master"
    end
  ".flash - Opened in browser!"
end

.initObject



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/xiki.rb', line 392

def self.init

  # Get rest of files to require

  classes = Dir["./lib/xiki/*.rb"]

  classes = classes.select{|i|
    i !~ /\/ol.rb$/ &&   # Don't load Ol twice
    i !~ /\/xiki.rb$/ &&   # Remove self
    i !~ /\/key_bindings.rb$/ &&   # Remove key_bindings
    i !~ /__/   # Remove __....rb files
  }

  #     classes = Dir["**/*.rb"]
  #     classes = classes.select{|i|
  #       i !~ /xiki.rb$/ &&   # Remove self
  #       i !~ /key_bindings.rb$/ &&   # Remove key_bindings
  #       i !~ /\// &&   # Remove all files in dirs
  #       i !~ /tests\// &&   # Remove tests
  #       i !~ /__/   # Remove __....rb files
  #     }

  classes.map!{|i| i.sub(/\.rb$/, '')}.sort!

  # Require classes
  Requirer.require_classes classes

  # key_bindings has many dependencies, require it last
  Requirer.require_classes ['./lib/xiki/key_bindings.rb']

  Launcher.add_class_launchers classes.map{|o| o[/.*\/(.+)/, 1]}
  Launcher.reload_menu_dirs

  Launcher.add "xiki"

  # Pull out into .define_mode

  Mode.define(:xiki, ".xiki") do
    Xiki.on_open
  end

  if $el
    # If the first time we've loaded
    if ! $el.elvar.xiki_loaded_once && ! Menu.line_exists?("misc config", /^- don't show welcome$/) && ! View.buffer_visible?("Issues Loading Xiki")
      Launcher.open("welcome/", :no_search=>1)
    end

    $el.elvar.xiki_loaded_once = true
  end

end

.insert_menuObject



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/xiki.rb', line 172

def self.insert_menu
  line = Line.value
  indent = Line.indent line
  blank = Line.blank?

  prefix = Keys.prefix

  # If line not blank, usually indent after

  Line.<<("\n#{indent}  @") if ! blank

  # If at end of line, and line not blank, go to next line

  # Todo: if dash+, do auto-complete even if exact match - how to implement?

  input = Keys.input(:timed=>true, :prompt=>"Start typing a menu that might exist (or type 'all'): ")

  View << input

  Launcher.launch
end

.install_icon(arg) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/xiki.rb', line 112

def self.install_icon arg

  emacs_dir = "/Applications/Aquamacs Emacs.app"

  return "- Couldn't find #{emacs_dir}!" if ! File.exists?("#{emacs_dir}")

  plist_path = "#{emacs_dir}/Contents/Info.plist"

  plist = File.read "#{emacs_dir}/Contents/Info.plist"

  # TODO
  # "Back up plist file - where - xiki root?!
  # "Tell them where it was backed up!
  # "Show diffs of change that was made!

  return "- This file wasn't in the format we expected: #{plist_path}" if plist !~ %r"^\t<key>CFBundleDocumentTypes</key>\n\t<array>\n"

  # TODO
  # .plist
    # if change was already made, say so

  # TODO

  # 1. Copy icon into app
  # cp "#{Xiki.dir}etc/shark.icns" "/Applications/Aquamacs Emacs.app/Contents/Resources/"
  # - /Applications/Aquamacs Emacs.app/
  #   - Contents/Resources/
  #     + shark.icns
  #     + emacs-document.icns

  # 2. Update Info.plist
  # /Applications/Aquamacs Emacs.app/Contents/
  #   - Info.plist
  #     |+ 		<dict>
  #     |+ 			<key>CFBundleTypeExtensions</key>
  #     |+ 			<array>
  #     |+ 				<string>notes</string>
  #     |+ 				<string>menu</string>
  #     |+ 				<string>xiki</string>
  #     |+ 			</array>
  #     |+ 			<key>CFBundleTypeIconFile</key>
  #     |+ 			<string>shark.icns</string>
  #     |+ 			<key>CFBundleTypeName</key>
  #     |+ 			<string>Xiki File</string>
  #     |+ 			<key>CFBundleTypeOSTypes</key>
  #     |+ 			<array>
  #     |+ 				<string>TEXT</string>
  #     |+ 				<string>utxt</string>
  #     |+ 			</array>
  #     |+ 			<key>CFBundleTypeRole</key>
  #     |+ 			<string>Editor</string>
  #     |+ 		</dict>

  # 3. Tell user to drag the .app icon out of the "Applications" folder and back in
  #   - Or google to find a command that will do the same thing


  "- TODO: finish implementing!"
end


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/xiki.rb', line 36

def self.menu
  %`
  - .tests/
  - .github/
    - commits/
    - files/
  - .setup/
    - install command/
      | Double-click on these lines to add the executable 'xiki' command to
      | your path:
      |
      @#{Xiki.dir}/
        $ ruby etc/command/copy_xiki_command_to.rb /usr/local/bin/xiki
      |
      | Then you can type 'xiki' on a command line outside of emacs as a
      | shortcut to opening xiki and opening menus, like so:
      |
      |   $ xiki computer
      |
    - .install icon/
      | Double-click on this line to make .xiki files have the xiki 'shark'
      | icon:
      |
      - install/
      |
      | When you right-click on a .xiki file and select "Open With" and
      | choose emacs, the files will be assigned the xiki shark icon.
      |
    - install global shortcut/
      - 1) With cursor on the following, type open+in+os, then click "Install"
        @ #{Xiki.dir}etc/services/Xiki Menu.workflow

      - 2) In Mac OS, open
        | System Preferences > Keyboard > Keyboard Shortcuts > Services

      - 3) Scroll down to the bottom and give "Xiki Menu" the shortcut
        | Command+Control+X

      - 4) Try it out by typing Command+Control+X from any application
        | It should prompt you to type a xiki menu
    - .process/
      - status/
      - start/
      - stop/
      - restart/
      - log/
    - el4r/
      > Configure
      @#{Xiki.dir}
        % sudo bash etc/install/el4r_setup.sh

      - docs/
        | This will create/update files in your home directory, which make el4r
        | point to the version of ruby currently active.
        |
        | You can run this multiple times.
    - .misc/
      - .dont show welcome/
    @web interface/
  - api/
    > Summary
    Here are some functions that will always be available to menu classes,
    even external ones.
    |
    | Put pipes at beginning of lines (except bullets etc)
    |   p Xiki.quote "hey\\nyou"
    |
    | Return path to tree's root including current line, will be a list with 1
    | path unless nested.
    |   p Xiki.trunk
    |
    Here are some functions that will always be available toxxxxxxxxxxxxxxxxxx
  `

end


207
208
209
# File 'lib/xiki.rb', line 207

def self.menus
  CodeTree.menu
end


345
346
347
348
349
350
351
352
# File 'lib/xiki.rb', line 345

def self.nav_to path, *searches
  View.open path
  View.to_highest
  searches.each { |s| Search.forward "[\"']#{$el.regexp_quote s}[\"']" }
  Move.to_axis
  Color.colorize :l
  nil
end


333
334
335
336
337
338
339
340
341
342
343
# File 'lib/xiki.rb', line 333

def self.nav_to_line
  match = Line.value.match(/([\/\w.]+)?:(\d+)/)
  return if ! match

  file, line = match[1..2]
  file.sub! /^\.\//, Bookmarks["$x"]
  View.open file
  View.to_line line.to_i

  return true   # Did navigate
end

.on_openObject

Other .init mode defined below



367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/xiki.rb', line 367

def self.on_open
  orig = View.name
  name = orig[/(.+?)\./, 1]

  file = View.file

  # Figure out whether menu or class
  txt = File.read file
  kind = txt =~ /^class / ? "class" : "menu"
  require_menu file, :force_as=>kind

  View.kill

  Buffers.delete name if View.buffer_open? name

  View.to_buffer name
  Notes.mode

  View.dir = "/tmp/"

  View.<< "- #{name}/\n", :dont_move=>1
  Launcher.launch

end

.open_menuObject



194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/xiki.rb', line 194

def self.open_menu

  return Launcher.open("- last/") if Keys.prefix_u

  input = Keys.input(:timed=>true, :prompt=>"Start typing a menu that might exist (or type 'all'): ")
  View.to_buffer "menu"
  Notes.mode
  View.kill_all
  View << "#{input}\n"
  View.to_highest
  Launcher.launch
end

.path(options = {}) ⇒ Object



358
359
360
# File 'lib/xiki.rb', line 358

def self.path options={}
  Tree.path options
end

.process(action) ⇒ Object



444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/xiki.rb', line 444

def self.process action

  case action
  when "status"
    "- #{`xiki status`}"
  when "stop"
    response = `xiki stop`
    response = "apparently it wasn't running" if response.blank?
    response.gsub /^/, '- '
  when "restart"
    response = `xiki restart`
    response = "apparently it wasn't running" if response.blank?
    response.gsub /^/, '- '
  when "log"
    "@/tmp/xiki_process.rb.output"
  when "start"
    result = `xiki`
    "- started!"
  end
end

.quote(txt) ⇒ Object



362
363
364
# File 'lib/xiki.rb', line 362

def self.quote txt
  Tree.quote txt
end

.quote_spec(txt) ⇒ Object



224
225
226
227
228
229
230
# File 'lib/xiki.rb', line 224

def self.quote_spec txt
  txt.
    gsub(/^/, '| ').
    gsub(/ +$/, '').
    gsub(/^\|(        )([+-])/) {|o| "|#{$2 == '-' ? '+' : '-'}#{$1}"}   # Make "expected" be green

end

.tests(clazz = nil, describe = nil, test = nil, quote = nil) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/xiki.rb', line 232

def self.tests clazz=nil, describe=nil, test=nil, quote=nil

  prefix = Keys.prefix :clear=>1

  return if self.nav_to_line   # If on line to navigate to, just navigate

  # If no class, list all classes

  if clazz.nil?
    return ["all/"] + Dir["#{Xiki.dir}/spec/*_spec.rb"].entries.map{|o| "#{o[/.+\/(.+)_spec\.rb/, 1]}/"}
  end

  # If /class, list describes

  path = Bookmarks["$x/spec/#{clazz}_spec.rb"]

  sync_options = prefix == :u ? {} : {:sync=>1}

  if describe.nil?
    return View.open path if prefix == "open"

    if clazz == "all"   # Run all specs
      return self.quote_spec( #prefix == :u ?
        Console.run("rspec spec", sync_options.merge(:dir=>Xiki.dir))
        )
    end

    txt = File.read path
    return "- all/\n" + txt.scan(/^ *describe .*"(.+)"/).map{|o|
      "- #{o.first}/"
    }.join("\n")
  end

  # If /class/describe, list tests

  if test.nil?

    return self.nav_to path, describe if prefix == "open"

    if describe == "all"   # Run whole test
      return self.quote_spec(
        Console.run("rspec spec/#{clazz}_spec.rb", sync_options.merge(:dir=>Xiki.dir))
        )
    end

    txt = File.read path

    is_match = false
    return "- all/\n" + txt.scan(/^ *(describe|it) .*"(.+)"/).map{|o|
      next is_match = o[1] == describe if o[0] == "describe"   # If describe, set whether it's a match
      next if ! is_match
      "- #{o[1]}/"
    }.select{|o| o.is_a? String}.join("\n")

  end

  # If /class/describe/test, run test

  if ! quote
    if test == "all"   # Run all for describe
      return self.quote_spec(
        Console.run("rspec spec/#{clazz}_spec.rb -e \"#{describe}\"", sync_options.merge(:dir=>Xiki.dir))
        #           Console.run("rspec spec", sync_options.merge(:dir=>Xiki.dir))
        )
    end

    # If U prefix, just jump to file
    if prefix == "open"
      return self.nav_to path, describe, test if prefix == "open"
    end


    # Run it
    command = "rspec spec/#{clazz}_spec.rb -e \"#{describe} #{test}\""
    result = Console.run command, :dir=>"$x", :sync=>true

    if result =~ /^All examples were filtered out$/
      TextUtil.title_case! clazz
      describe.sub! /^#/, ''

      return %`
        > Test doesn't appear to exist.  Create it?
        | Copy this text into the file:

        @#{path}
          | describe #{clazz}, "##{describe}" do
          |   it "#{test}" do
          |     #{clazz}.#{describe}.should == "hi"
          |   end
          | end
      `
    end

    return self.quote_spec result
  end

  # Quoted line, so jump to line number

  nil
end

.trunk(options = {}) ⇒ Object



354
355
356
# File 'lib/xiki.rb', line 354

def self.trunk options={}
  self.path options
end