Class: Tkri::Tab
- Inherits:
-
TkFrame
- Object
- TkFrame
- Tkri::Tab
- Defined in:
- lib/tkri.rb
Overview
A Tab encapsulates an @address box, where you type the topic to go to; a “Go” button; and an @info box in which to show the topic.
Instance Attribute Summary collapse
-
#topic ⇒ Object
readonly
Returns the value of attribute topic.
Instance Method Summary collapse
- #_highlight_word(word_or_regexp, text, tag_name) ⇒ Object
- #_load_topic(topic) ⇒ Object
-
#fixup_topic(topic) ⇒ Object
Allow for some shortcuts when typing topics…
-
#focus_address ⇒ Object
Moves the keyboard focus to the address box.
-
#get_previous_class(cursor) ⇒ Object
Returns the first class mentioned before the cursor.
-
#get_previous_header(cursor) ⇒ Object
Returns the section (the header) the cursor is in.
-
#get_selection ⇒ Object
It seems RubyTk doesn’t support the the getSelected method for Text widgets.
-
#get_word(position) ⇒ Object
Get the “topic” at a certain postion.
-
#go(topic = nil) ⇒ Object
Navigates to some topic.
-
#go_caret_word(newtab = false) ⇒ Object
Navigate to the topic mentioned under the caret.
- #go_word(position, newtab = false) ⇒ Object
-
#go_xy_word(x, y, newtab = false) ⇒ Object
Navigate to the topic mentioned under the mouse cursor (given by x,y coordinates).
- #hide ⇒ Object
-
#highlight_word(word) ⇒ Object
Highlights a word in the text.
-
#initialize(tk_parent, app, configuration = {}) ⇒ Tab
constructor
A new instance of Tab.
- #interactive_focus_address(e) ⇒ Object
-
#interactive_go_up(e) ⇒ Object
Go “up”.
- #interactive_goto_topic_in_addressbox(e) ⇒ Object
- #interactive_goto_topic_under_caret_or_selected(e) ⇒ Object
- #interactive_goto_topic_under_mouse(e) ⇒ Object
- #interactive_goto_topic_under_mouse_in_new_tab(e) ⇒ Object
-
#interactive_history_back(e) ⇒ Object
Navigate to the previous topic in history.
-
#interactive_history_forward(e) ⇒ Object
Navigate to the next topic in history.
- #new? ⇒ Boolean
-
#restore_from_history ⇒ Object
Call this method after moving fack and forth in the history.
-
#search_next_word(word) ⇒ Object
Finds the next occurrence of a word.
-
#search_prev_word(word) ⇒ Object
Finds the previous occurrence of a word.
-
#set_ansi_text(text) ⇒ Object
Sets the text of the @info box, converting ANSI escape sequences to Tk tags.
-
#set_cursor(pos) ⇒ Object
Sets @info’s caret position.
- #show ⇒ Object
-
#store_in_history ⇒ Object
Call this method before switching to another topic.
Constructor Details
#initialize(tk_parent, app, configuration = {}) ⇒ Tab
Returns a new instance of Tab.
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 |
# File 'lib/tkri.rb', line 277 def initialize(tk_parent, app, configuration = {}) @app = app super(tk_parent, configuration) # # The address bar # = TkFrame.new(self) { |ab| pack :side => 'top', :fill => 'x' TkButton.new(ab) { configure Settings::get_configuration('go_button') text 'Go' command { app.go } pack :side => 'right' } } @address = TkEntry.new() { configure Settings::get_configuration('__base__') configure :width => 30 pack :side => 'left', :expand => true, :fill => 'both' } # # The info box, where the main text is displayed. # _frame = self @info = TkText.new(self) { |t| configure Settings::get_configuration('__base__') pack :side => 'left', :fill => 'both', :expand => true TkScrollbar.new(_frame) { |s| pack :side => 'right', :fill => 'y' command { |*args| t.yview *args } t.yscrollcommand { |first,last| s.set first,last } } } Settings::VISUALS.each do |name, hash| if hash[:is_tag] @info.tag_configure(name, Settings::get_configuration(name)) end end Tkri.attach_bindings @address, 'addressbox' Tkri.attach_bindings @info, 'info' @history = History.new end |
Instance Attribute Details
#topic ⇒ Object (readonly)
Returns the value of attribute topic.
275 276 277 |
# File 'lib/tkri.rb', line 275 def topic @topic end |
Instance Method Details
#_highlight_word(word_or_regexp, text, tag_name) ⇒ Object
410 411 412 413 414 415 416 417 |
# File 'lib/tkri.rb', line 410 def _highlight_word(word_or_regexp, text, tag_name) pos = -1 while pos = text.index(word_or_regexp, pos + 1) length = (word_or_regexp.is_a? String) ? word_or_regexp.length : $&.length @info.tag_add(tag_name, '1.0 + %d chars' % pos, '1.0 + %d chars' % (pos + length)) end end |
#_load_topic(topic) ⇒ Object
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'lib/tkri.rb', line 607 def _load_topic(topic) @app.status = 'Loading "%s"...' % topic @address.delete('0', 'end') @address.insert('end', topic) focus_address # We need to give our GUI a chance to redraw itself, so we run the # time-consuming 'ri' command "in the next go". TkAfter.new 100, 1 do ri = @app.fetch_ri(topic) set_ansi_text(ri) @app. @app.status = '' @info.focus set_cursor '1.0' yield if block_given? end.start end |
#fixup_topic(topic) ⇒ Object
Allow for some shortcuts when typing topics…
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 |
# File 'lib/tkri.rb', line 556 def fixup_topic(topic) case topic when 'S', 's', 'string' 'String' when 'A', 'a', 'array' 'Array' when 'H', 'h', 'hash' 'Hash' when 'File::new' # See qri bug at http://rubyforge.org/tracker/index.php?func=detail&aid=23504&group_id=2545&atid=9811 'File#new' else topic end end |
#focus_address ⇒ Object
Moves the keyboard focus to the address box. Also, selects all the text, like modern GUIs do.
357 358 359 360 361 |
# File 'lib/tkri.rb', line 357 def focus_address @address.selection_range('0', 'end') @address.icursor = 'end' @address.focus end |
#get_previous_class(cursor) ⇒ Object
Returns the first class mentioned before the cursor.
458 459 460 461 462 |
# File 'lib/tkri.rb', line 458 def get_previous_class cursor # The class (or module) is followed by a '(' ret = @info.rsearch_with_length(/\s\S+\(/, cursor) return ret[0].empty? ? nil : ret[2][1..-2] # skip the first char (a space) and the last (a parentheses) end |
#get_previous_header(cursor) ⇒ Object
Returns the section (the header) the cursor is in.
450 451 452 453 454 455 |
# File 'lib/tkri.rb', line 450 def get_previous_header cursor ret = @info.rsearch_with_length(/[\r\n]\w[^\r\n]*/, cursor) if !ret[0].empty? and @info.compare(cursor, '>=', ret[0]) return ret[2].strip end end |
#get_selection ⇒ Object
It seems RubyTk doesn’t support the the getSelected method for Text widgets. So here’s a method of our own to get the selection.
347 348 349 350 351 352 353 |
# File 'lib/tkri.rb', line 347 def get_selection begin @info.get('sel.first', 'sel.last') rescue '' end end |
#get_word(position) ⇒ Object
Get the “topic” at a certain postion.
The ‘position’ paramter is an expression that can be, e.g., “insert” for the current caret position; or “@x,y” for the mouse poisition.
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 |
# File 'lib/tkri.rb', line 468 def get_word(position) line = @info.get(position + ' linestart', position + ' lineend') pos = @info.get(position + ' linestart', position).length line = ' ' + line + ' ' pos += 1 if line[pos,1] == ' ' # If the user clicks a space between words, or after end of line, abort. return nil end a = pos a -= 1 while line[a-1,1] !~ /[ (]/ z = pos z += 1 while line[z+1,1] !~ /[ ()]/ word = line[a..z] # Get rid of English punctuation. word.gsub!(/[,.:;]$/, '') # Get rid of italic, bold, and code markup. if word =~ /^(_|\*|\+).*\1$/ word = word[1...-1] a += 1 end a -= 1 # Undo the `line = ' ' + line` we did previously. @info.tag_add('keyword', '%s linestart + %d chars' % [ position, a ], '%s linestart + %d chars' % [ position, a+word.length ]) word.strip! return nil if word.empty? return nil if word =~ /^-+$/ # A special case: a line of '-----' if word =~ /^#/ # Sometimes there's just "#method". word = @topic + word end case get_previous_header(position) when 'Instance methods:' word = topic + '#' + word when 'Class methods:' word = topic + '::' + word when 'Includes:' word = get_previous_class(position) + '#' + word if not word =~ /^[A-Z]/ end return word end |
#go(topic = nil) ⇒ Object
Navigates to some topic.
573 574 575 576 577 578 579 580 581 582 583 |
# File 'lib/tkri.rb', line 573 def go(topic=nil) topic = (topic || @address.get).strip return if topic.empty? @topic = fixup_topic(topic) # First, save the cursor position in the current history entry. store_in_history # Next, add a new entry to the history. @history.add HistoryEntry.new(@topic, nil, nil) # Finally, load the topic. _load_topic @topic end |
#go_caret_word(newtab = false) ⇒ Object
Navigate to the topic mentioned under the caret.
439 440 441 |
# File 'lib/tkri.rb', line 439 def go_caret_word(newtab=false) go_word('insert', newtab) end |
#go_word(position, newtab = false) ⇒ Object
443 444 445 446 447 |
# File 'lib/tkri.rb', line 443 def go_word(position, newtab=false) if (word = get_word(position)) @app.go word, newtab end end |
#go_xy_word(x, y, newtab = false) ⇒ Object
Navigate to the topic mentioned under the mouse cursor (given by x,y coordinates)
428 429 430 431 432 433 434 435 436 |
# File 'lib/tkri.rb', line 428 def go_xy_word(x, y, newtab=false) if not newtab and not @info.tag_ranges('sel').empty? # We don't want to prohibit selecting text, so we don't trigger # navigation if some text is selected. (Remember, this method is called # upon releasing the mouse button.) return end go_word('@' + x.to_s + ',' + y.to_s, newtab) end |
#hide ⇒ Object
657 658 659 |
# File 'lib/tkri.rb', line 657 def hide pack_forget end |
#highlight_word(word) ⇒ Object
Highlights a word in the text. Used by the search methods.
404 405 406 407 408 |
# File 'lib/tkri.rb', line 404 def highlight_word(word) return if word.empty? @info.tag_remove('search', '1.0', 'end') _highlight_word(word.downcase, @info.get('1.0', 'end').downcase, 'search') end |
#interactive_focus_address(e) ⇒ Object
363 364 365 |
# File 'lib/tkri.rb', line 363 def interactive_focus_address e focus_address end |
#interactive_go_up(e) ⇒ Object
Go “up”. That is, if we’re browsing a method, go to the class.
420 421 422 423 424 |
# File 'lib/tkri.rb', line 420 def interactive_go_up e if topic and topic =~ /(.*)(::|#|\.)/ @app.go $1 end end |
#interactive_goto_topic_in_addressbox(e) ⇒ Object
325 326 327 |
# File 'lib/tkri.rb', line 325 def interactive_goto_topic_in_addressbox e go end |
#interactive_goto_topic_under_caret_or_selected(e) ⇒ Object
337 338 339 340 341 342 343 |
# File 'lib/tkri.rb', line 337 def interactive_goto_topic_under_caret_or_selected e if get_selection.length > 0 go get_selection else go_caret_word() end end |
#interactive_goto_topic_under_mouse(e) ⇒ Object
329 330 331 |
# File 'lib/tkri.rb', line 329 def interactive_goto_topic_under_mouse e go_xy_word(e.x, e.y) end |
#interactive_goto_topic_under_mouse_in_new_tab(e) ⇒ Object
333 334 335 |
# File 'lib/tkri.rb', line 333 def interactive_goto_topic_under_mouse_in_new_tab e go_xy_word(e.x, e.y, true) end |
#interactive_history_back(e) ⇒ Object
Navigate to the previous topic in history.
626 627 628 629 630 631 632 |
# File 'lib/tkri.rb', line 626 def interactive_history_back e if not @history.at_beginning store_in_history @history.back restore_from_history end end |
#interactive_history_forward(e) ⇒ Object
Navigate to the next topic in history.
635 636 637 638 639 640 641 |
# File 'lib/tkri.rb', line 635 def interactive_history_forward e if not @history.at_end store_in_history @history.foreward restore_from_history end end |
#new? ⇒ Boolean
649 650 651 |
# File 'lib/tkri.rb', line 649 def new? not @topic end |
#restore_from_history ⇒ Object
Call this method after moving fack and forth in the history. This method restores the topic and cursor position recorded in the current history entry.
597 598 599 600 601 602 603 604 605 |
# File 'lib/tkri.rb', line 597 def restore_from_history if current = @history.current @topic = current.topic _load_topic(topic) do @info.yview_moveto current.yview set_cursor current.cursor end end end |
#search_next_word(word) ⇒ Object
Finds the next occurrence of a word.
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/tkri.rb', line 368 def search_next_word(word) @info.focus highlight_word word cursor = @info.index('insert') pos = @info.search_with_length(Regexp.new(Regexp::quote(word), Regexp::IGNORECASE), cursor + ' 1 chars')[0] if pos.empty? @app.status = 'Cannot find "%s"' % word else set_cursor(pos) if @info.compare(cursor, '>=', pos) @app.status = 'Continuing search at top' else @app.status = '' end end end |
#search_prev_word(word) ⇒ Object
Finds the previous occurrence of a word.
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/tkri.rb', line 386 def search_prev_word(word) @info.focus highlight_word word cursor = @info.index('insert') pos = @info.rsearch_with_length(Regexp.new(Regexp::quote(word), Regexp::IGNORECASE), cursor)[0] if pos.empty? @app.status = 'Cannot find "%s"' % word else set_cursor(pos) if @info.compare(cursor, '<=', pos) @app.status = 'Continuing search at bottom' else @app.status = '' end end end |
#set_ansi_text(text) ⇒ Object
Sets the text of the @info box, converting ANSI escape sequences to Tk tags.
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
# File 'lib/tkri.rb', line 522 def set_ansi_text(text) text = text.dup = { # The following possibilities were taken from /usr/lib/ruby/1.8/rdoc/ri/ri_formatter.rb '1' => 'bold', '33' => 'italic', '36' => 'code', '4;32' => 'header2', '32' => 'header3', } ranges = [] while text =~ /\x1b\[([\d;]+)m ([^\x1b]*) \x1b\[0?m/x start = $`.length length = $2.length raw_length = $&.length text[start, raw_length] = $2 ranges << { :start => start, :length => length, :tag => [$1] } end @info.delete('1.0', 'end') @info.insert('end', text) ranges.each do |range| if range[:tag] @info.tag_add(range[:tag], '1.0 + %d chars' % range[:start], '1.0 + %d chars' % (range[:start] + range[:length])) end end # Hide any remaining sequences. This may happen because our previous regexp # (or any regexp) can't handle nested sequences. _highlight_word(/\x1b\[([\d;]*)m/, text, 'hidden') end |
#set_cursor(pos) ⇒ Object
Sets @info’s caret position. Scroll the view if needed.
644 645 646 647 |
# File 'lib/tkri.rb', line 644 def set_cursor(pos) @info.mark_set('insert', pos) @info.see(pos) end |
#show ⇒ Object
653 654 655 |
# File 'lib/tkri.rb', line 653 def show pack :fill => 'both', :expand => true end |
#store_in_history ⇒ Object
Call this method before switching to another topic. This method saves the cursor position in the history.
587 588 589 590 591 592 |
# File 'lib/tkri.rb', line 587 def store_in_history if current = @history.current current.cursor = @info.index('insert') current.yview = @info.yview[0] end end |