Class: S7::S7Cli::EntrySearchCommand

Inherits:
Command
  • Object
show all
Includes:
EntryCommandUtils
Defined in:
lib/s7/s7cli/entry_command.rb

Overview

機密情報を検索するコマンドを表現する。

Constant Summary collapse

SORT_KEYS =

ソート対象の属性の配列。

[:id, :name, :tags, :rate]

Constants included from EntryCommandUtils

S7::S7Cli::EntryCommandUtils::EDITING_USAGE

Instance Attribute Summary

Attributes inherited from Command

#config, #options, #world

Instance Method Summary collapse

Methods included from EntryCommandUtils

#apply_entry_changes, #command_loop, #dispatch_command, #display_entry, #input_attribute_name, #input_attribute_type, #input_secret, #input_tags, #input_value

Methods included from GetText

#N_, #_, bindtextdomain, included

Methods inherited from Command

#aliases, create_instance, #description, #help, #name, #option_parser, split_name_and_argv, #usage

Constructor Details

#initialize(*args) ⇒ EntrySearchCommand

Returns a new instance of EntrySearchCommand.



501
502
503
504
505
506
507
508
509
510
511
# File 'lib/s7/s7cli/entry_command.rb', line 501

def initialize(*args)
  super
  @config["query"] = ""
  @config["tags"] = []
  @config["num"] = 10
  @config["ignore-case"] = false
  @options.push(StringOption.new("query", _("Query.")), 
                ArrayOption.new("tags", _("Tags.")),
                IntOption.new("n", "num", _("Number of entries.")),
                BoolOption.new("i", "ignore_case", _("Ignore case.")))
end

Instance Method Details

#list_entries(entries, sort_key, page_no, per_page) ⇒ Object



671
672
673
674
675
676
677
678
679
680
681
682
# File 'lib/s7/s7cli/entry_command.rb', line 671

def list_entries(entries, sort_key, page_no, per_page)
  sort_marks = [" ", " ", " ", " "]
  sort_marks[SORT_KEYS.index(sort_key)] = ">"
  puts(_("%sID |%sName                                            |%sTags(s)            |%sRate") % sort_marks)
  sorted_entries = entries.sort_by { |e| e.send(sort_key) }
  sorted_entries[((page_no - 1) * per_page), per_page].each do |entry|
    puts([truncate_or_add_space(entry.id.to_s, 4, false),
          truncate_or_add_space(entry.name, 49),
          truncate_or_add_space(entry.tags.join(","), 20),
          truncate_or_add_space(entry.rate.to_s, 5, false)].join("|"))
  end
end

#next_sort_key(current) ⇒ Object



627
628
629
# File 'lib/s7/s7cli/entry_command.rb', line 627

def next_sort_key(current)
  return SORT_KEYS[(SORT_KEYS.index(current) + 1) % SORT_KEYS.length]
end

#run(argv) ⇒ Object

コマンドを実行する。



544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
# File 'lib/s7/s7cli/entry_command.rb', line 544

def run(argv)
  option_parser.parse!(argv)
  if argv.length > 0
    config["query"].concat(" " + argv.join(" "))
  end
  words = config["query"].split
  entries = search(world.entry_collection.entries,
                   words, config["tags"], config["ignore_case"])
  if entries.empty?
    puts(_("No entry."))
  else
    sort_key = :id
    page_no = 1
    per_page = ENV["LINES"].to_i
    if per_page <= 3
      per_page = 25 - 3
    else
      per_page -= 3
    end
    current_mode = :next

    begin
      loop do
        begin
          if words.length > 0
            print(_("Search result of '%s', %d entries.") %
                  [words.join(" "), entries.length])
          else
            print(_("List of %d entries.") % entries.length)
          end
          num_pages = (entries.length.to_f / per_page).ceil
          puts(_(" [page %d/%d]") % [page_no, num_pages])
          
          list_entries(entries, sort_key, page_no, per_page)

          if num_pages == 1
            raise Interrupt
          end

          prompt = _("Command (p:prev, n:next, s:sort, q:quit): ")
          input = S7Cli.input_string(prompt)
          if input.nil?
            raise Interrupt
          end
          begin
            case input
            when /\A(n|next)\z/i
              page_no += 1
              current_mode = :next
            when /\A(p|prev)\z/i
              page_no -= 1
              current_mode = :prev
            when /\A(s|sort)\z/i
              sort_key = next_sort_key(sort_key)
            when /\A(q|quit)/i
              break
            else
              if current_mode == :next
                page_no += 1
              else
                page_no -= 1
              end
            end
            if page_no < 1
              page_no = 1
            elsif page_no >= num_pages
              page_no = num_pages
            end
          end
        rescue ApplicationError => e
          puts(e.message)
        end
      end
    rescue Interrupt
      puts("\n")
    end
  end
  return true
end

#search(entries, words, tags, ignore_case) ⇒ Object



513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/s7/s7cli/entry_command.rb', line 513

def search(entries, words, tags, ignore_case)
  if words.empty?
    matched_entries = entries
  else
    matched_entries = entries.select { |entry|
      s = entry.attributes.collect { |attr|
        attr.value.to_s
      }.join("\n")
      res = true
      if ignore_case
        s.downcase!
        words.each(&:downcase!)
      end
      words.each do |word|
        if !s.include?(word)
          res = false
          break
        end
      end
      res
    }
  end
  if tags.length > 0
    matched_entries = matched_entries.select { |entry|
      tags == (entry.tags & tags)
    }
  end
  return matched_entries
end

#truncate_or_add_space(str, width, left = true) ⇒ Object

指定した文字列 str の表示幅が width よりも長い場合は切り詰める。 width よりも短い場合、left が true だと右部分にスペースをつめ、 left が false だと、左部分にスペースをつめる。



634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
# File 'lib/s7/s7cli/entry_command.rb', line 634

def truncate_or_add_space(str, width, left = true)
  len = 0
  truncate_index = nil
  truncate_with_space = false
  str.chars.each_with_index do |chr, i|
    case UnicodeData.east_asian_width(chr)
    when :H, :N
      n = 1
    else
      n = 2
    end
    len += n
    if truncate_index.nil? && len >= width
      truncate_index = i
      if len > width
        truncate_with_space = true
      end
    end
  end
  if len < width
    space = " " * (width - len)
    if left
      res = str + space
    else
      res = space + str
    end
  elsif len == width
    res = str
  else
    res = str[0..truncate_index]
    if truncate_with_space
      res[-1] = " "
    end
  end
  return res
end