module Cygnus

Constants

CLEAR
CONFIG_FILE
CURMARK
CURSOR_COLOR

REVERSE = “e[7m”

GIGA_SIZE

code related to long listing of files

GMARK

CONSTANTS

KILO_SIZE
MEGA_SIZE
MSCROLL
ON_BLUE

CLEAR = “e[0m” BOLD = “e[1m” BOLD_OFF = “e[22m” RED = “e[31m” ON_RED = “e[41m” GREEN = “e[32m” YELLOW = “e[33m” BLUE = “e[1;34m”

SPACE
VERSION

Public Instance Methods

TODOpost_cd() click to toggle source

TODO

# File lib/cygnus.rb, line 733
def TODOpost_cd
  $patt=nil
  $sta = $cursor = 0
  $title = nil
  if $selected_files.size > 0
    $selected_files = []
  end
  $visual_block_start = nil
  $stact = 0
  screen_settings
  # i think this will screw with the dir_pos since it is not filename based.
  enhance_file_list
  revert_dir_pos
end
ack() click to toggle source
# File lib/cygnus.rb, line 1200
def ack
  pattern = get_line "Enter a pattern to search (ack): "
  return if pattern.nil? || pattern == ""
  $title = "Files found using 'ack' #{pattern}"
  #system("ack #{pattern}")
  #pause
  files = `ack -l #{pattern}`.split("\n")
  if files.size == 0
    perror "No files found."
  else
    $files = files
    show_list
  end
end
ask_hint(text, deflt=nil) click to toggle source

prompt user for file shortcut and return file or nil

# File lib/cygnus.rb, line 1007
def ask_hint text, deflt=nil
  f = nil
  
  #ch = get_char
  ch = get_single text
  if ch == "ENTER" 
    return deflt
  end
  ix = get_index(ch, $viewport.size)
  f = $viewport[ix] if ix
  return f
end
bindkey_ext_command() click to toggle source

bind a key to an external command wich can be then be used for files

# File lib/cygnus.rb, line 1159
def bindkey_ext_command
  #print
  #pbold "Bind a capital letter to an external command"
  ch = get_single "Enter a capital letter to bind: "
  #ch = get_char
  return if ch == "Q"
  if ch =~ /^[A-Z]$/
    print "Enter an external command to bind to #{ch}: "
    com = gets().chomp
    if com != ""
      print "Enter prompt for command (blank if same as command): "
      pro = gets().chomp
      pro = com if pro == ""
    end
    print "Pause after output [y/n]: "
    yn = get_char
    $bindings[ch] = "command_file #{pro} #{yn} #{com}"
  end
end
c_refresh() click to toggle source
refresh listing after some change like option change, or toggle

I think NCurses has a refresh which when called internally results in this chap getting called since both are included. or maybe App or somehting has a refresh

# File lib/cygnus.rb, line 358
def c_refresh
  $filterstr ||= "M"
  #$files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}#{$filterstr})'`.split("\n")
  $patt=nil
  $title = nil
  display_dir
end
c_system(command) click to toggle source
# File lib/cygnus.rb, line 333
def c_system command
  w = @window || @form.window
  w.hide
  Ncurses.endwin
  ret = system command
  Ncurses.refresh
  w.show
  return ret
end
child_dirs() click to toggle source
# File lib/cygnus.rb, line 878
def child_dirs
  $title = "Child directories"
  $files = `zsh -c 'print -rl -- *(/#{$sorto}#{$hidden}M)'`.split("\n")
end
column_next(dir=0) click to toggle source
moves column offset so we can reach unindexed columns or entries

0 forward and any other back/prev

# File lib/cygnus.rb, line 1034
def column_next dir=0
  if dir == 0
    $stact += $grows
    $stact = 0 if $stact >= $viewport.size
  else
    $stact -= $grows
    $stact = 0 if $stact < 0
  end
end
columnate(ary, sz) click to toggle source

print in columns ary - array of data sz - lines in one column This is the original which did not format or color, but since we cannot truncate unless we have unformatted data i need to mix the functionality into columnate_with_indexing

# File lib/cygnus.rb, line 194
def columnate ary, sz
  buff=Array.new
  return buff if ary.nil? || ary.size == 0
  
  # ix refers to the index in the complete file list, wherease we only show 60 at a time
  ix=0
  while true
    ## ctr refers to the index in the column
    ctr=0
    while ctr < sz

      f = ary[ix]
      # deleted truncate and pad part since we expect cols to be sized same

      if buff[ctr]
        buff[ctr] += f
      else
        buff[ctr] = f
      end

      ctr+=1
      ix+=1
      break if ix >= ary.size
    end
    break if ix >= ary.size
  end
  return buff
end
columnate_with_indexing(ary, sz) click to toggle source

print in columns ary - array of data sz - lines in one column

# File lib/cygnus.rb, line 95
def columnate_with_indexing ary, sz
  buff=Array.new
  $log.warn "columnate_with_indexing got nil list " unless ary
  return buff if ary.nil? || ary.size == 0
  
  # determine width based on number of files to show
  # if less than sz then 1 col and full width
  #
  wid = 30
  ars = ary.size
  ars = [$pagesize, ary.size].min
  # 2 maybe for borders also
  d = 0
  if ars <= sz
    wid = $gcols - d
  else
    tmp = (ars * 1.000/ sz).ceil
    wid = $gcols / tmp - d
  end

  # ix refers to the index in the complete file list, wherease we only show 60 at a time
  ix=0
  while true
    ## ctr refers to the index in the column
    ctr=0
    while ctr < sz

      cur=SPACE
      cur = CURMARK if ix + $sta == $cursor
      f = ary[ix]

      if $long_listing
        begin
          # one of zsh's flags adds not just / but @ * and a space, so the a FNF error comes
          unless File.exist? f
            last = f[-1]
            if last == " " || last == "@" || last == '*'
              stat = File.stat(f.chop)
            end
          else
            stat = File.stat(f)
          end
          f = "%10s  %s  %s" % [readable_file_size(stat.size,1), date_format(stat.mtime), f]
        rescue Exception => e
          f = "%10s  %s  %s" % ["?", "??????????", f]
        end
      end

      # be careful of modifying f or original array gets modified XXX
      k = get_shortcut ix
      isdir = f[-1] == "/"
      fsz = f.size + k.to_s.size + 0
      fsz = f.size + 1
      if fsz > wid
        # truncated since longer
        f = f[0, wid-2]+"$ "
        ## we do the coloring after trunc so ANSI escpe seq does not get get
        #if ix + $sta == $cursor
          #f = "#{CURSOR_COLOR}#{f}#{CLEAR}"
        #end
      else
        ## we do the coloring before padding so the entire line does not get padded, only file name
        #if ix + $sta == $cursor
          #f = "#{CURSOR_COLOR}#{f}#{CLEAR}"
        #end
        f = f.ljust(wid)
        # pad with spaces
        #f << " " * (wid-fsz)
        #f = f + " " * (wid-fsz)
      end
      # now we add the shortcut with the coloring (we need to adjust the space of the shortcut)
      #
      colr = "white"
      colr = "blue, bold" if isdir
      # this directly modified the damned index resulting in searches failing
      #k << " " if k.length == 1
      k = k + " " if k.length == 1

      f = "#{cur}#[fg=yellow, bold]#{k}#[end] #[fg=#{colr}]#{f}#[end]" 

      if buff[ctr]
        buff[ctr] += f
      else
        buff[ctr] = f
      end

      ctr+=1
      ix+=1
      break if ix >= ary.size
    end
    break if ix >= ary.size
  end
  return buff
end
columns_incdec(howmany) click to toggle source
# File lib/cygnus.rb, line 1151
def columns_incdec howmany
  $gviscols += howmany.to_i
  $gviscols = 1 if $gviscols < 1
  $gviscols = 6 if $gviscols > 6
  $pagesize = $grows * $gviscols
end
command_file(prompt, *command) click to toggle source

generic external command program prompt is the user friendly text of command such as list for ls, or extract for dtrx, page for less pauseyn is whether to pause after command as in file or ls

# File lib/cygnus.rb, line 983
def command_file prompt, *command
  pauseyn = command.shift
  command = command.join " "
    #print "[#{prompt}] Choose a file [#{$view[$cursor]}]: "
    t = "[#{prompt}] Choose a file [#{$view[$cursor]}]: "
    file = ask_hint t, $view[$cursor]
  #print "#{prompt} :: Enter file shortcut: "
  #file = ask_hint
  perror "Command Cancelled" unless file
  return unless file
  file = File.expand_path(file)
  if File.exists? file
    file = Shellwords.escape(file)
    pbold "#{command} #{file} (press a key)"
    c_system "#{command} #{file}"
    pause if pauseyn == "y"
    c_refresh
  else
    perror "File #{file} not found"
  end
end
command_menu() click to toggle source
# File lib/cygnus.rb, line 596
def command_menu
  ##
  #  since these involve full paths, we need more space, like only one column
  #
  ## in these cases, getting back to the earlier dir, back to earlier listing
  # since we've basically overlaid the old listing
  #
  # should be able to sort THIS listing and not rerun command. But for that I'd need to use
  # xargs ls -t etc rather than the zsh sort order. But we can run a filter using |.
  #
  h = { :t => :today, :D => :default_command , :R => :remove_from_list}
  if $editor_mode 
    h[:e] = :pager_mode
  else
    h[:e] = :editor_mode
  end
  ch, menu_text = menu "Command Menu", h
  case menu_text
  when :pager_mode
    $editor_mode = false
    $default_command = ENV['MANPAGER'] || ENV['PAGER']
  when :editor_mode
    $editor_mode = true
    $default_command = nil
  when :ffind
    ffind
  when :locate
    locate
  when :today
    $files = `zsh -c 'print -rl -- *(#{$hidden}Mm0)'`.split("\n")
    $title = "Today's files"
  when :default_command
    print "Selecting a file usually invokes $EDITOR, what command do you want to use repeatedly on selected files: "
    $default_command = gets().chomp
    if $default_command != ""
      print "Second part of command (maybe blank): "
      $default_command2 = gets().chomp
    else
      print "Cleared default command, will default to $EDITOR"
      $default_command2 = nil
      $default_command = nil
    end
  end
end
command_mode() click to toggle source

toggle command mode

# File lib/cygnus.rb, line 421
def command_mode
  if $mode == 'COM'
    $mode = nil
    return
  end
  $mode = 'COM'
end
config_read() click to toggle source

read dirs and files and bookmarks from file

# File lib/cygnus.rb, line 749
def config_read
  #f =  File.expand_path("~/.zfminfo")
  f =  File.expand_path(CONFIG_FILE)
  if File.readable? f
    load f
    # maybe we should check for these existing else crash will happen.
    $used_dirs.push(*(DIRS.split ":"))
    $used_dirs.concat get_env_paths
    $visited_files.push(*(FILES.split ":"))
    #$bookmarks.push(*bookmarks) if bookmarks
    chars = ('A'..'Z').to_a
    chars.concat( ('0'..'9').to_a )
    chars.each do |ch|
      if Kernel.const_defined? "BM_#{ch}"
        $bookmarks[ch] = Kernel.const_get "BM_#{ch}"
      end
    end
  end
end
config_write() click to toggle source

save dirs and files and bookmarks to a file

# File lib/cygnus.rb, line 782
def config_write
  # Putting it in a format that zfm can also read and write
  f1 =  File.expand_path("~/.cygnusinfo")
  #f1 =  File.expand_path(CONFIG_FILE)
  d = $used_dirs.join ":"
  f = $visited_files.join ":"
  File.open(f1, 'w+') do |f2|  
    # use "\n" for two lines of text
    f2.puts "DIRS=\"#{d}\""
    f2.puts "FILES=\"#{f}\""
    $bookmarks.each_pair { |k, val| 
      f2.puts "BM_#{k}=\"#{val}\""
      #f2.puts "BOOKMARKS[\"#{k}\"]=\"#{val}\""
    }
  end
  $writing = $modified = false
end
create_bookmark() click to toggle source

accept a character to save this dir as a bookmark

# File lib/cygnus.rb, line 801
def create_bookmark
  ch = get_single "Enter A to Z or 0-9 for bookmark: "
  #ch = get_char
  if ch =~ /^[0-9A-Z]$/
    #$bookmarks[ch] = "#{Dir.pwd}:#{$cursor}"
    #
    # The significance of putting a : and not a / is that with a
    # : the dir will be opened with cursor on same object it was on, and not
    # go into the dir. e.g, If bookmark is created with cursor on a dir, we don't want
    # it to go into the dir.
    $bookmarks[ch] = "#{Dir.pwd}:#{$view[$cursor]}"
    $modified = true
  else
    perror "Bookmark must be upper-case character or number."
  end
end
cursor_dn() click to toggle source
# File lib/cygnus.rb, line 1257
def cursor_dn
  moveto(pos() + 1)
end
cursor_scroll_dn() click to toggle source

some cursor movement functions

# File lib/cygnus.rb, line 1251
def cursor_scroll_dn
  moveto(pos() + MSCROLL)
end
cursor_scroll_up() click to toggle source
# File lib/cygnus.rb, line 1254
def cursor_scroll_up
  moveto(pos() - MSCROLL)
end
cursor_up() click to toggle source
# File lib/cygnus.rb, line 1260
def cursor_up
  moveto(pos() - 1)
end
date_format(t) click to toggle source

format date for file given stat

# File lib/cygnus.rb, line 86
def date_format t
  t.strftime "%Y/%m/%d"
end
delete_file() click to toggle source
# File lib/cygnus.rb, line 975
def delete_file
  file_actions :delete
end
dirtree() click to toggle source
# File lib/cygnus.rb, line 882
def dirtree
  $title = "Child directories"
  $files = `zsh -c 'print -rl -- **/*(/#{$sorto}#{$hidden}M)'`.split("\n")
end
enhance_file_list() click to toggle source

If there’s a short file list, take recently mod and accessed folders and put latest files from there and insert it here. I take both since recent mod can be binaries / object files and gems created by a process, and not actually edited files. Recent accessed gives latest source, but in some cases even this can be misleading since running a program accesses include files.

# File lib/cygnus.rb, line 1433
def enhance_file_list
  return unless $enhanced_mode
  # if only one entry and its a dir
  # get its children and maybe the recent mod files a few
  
  # zsh gives errors which stick on stdscr and don't get off!
  # Rather than using N I'll try to convert to ruby, but then we lose
  # similarity to cetus and its tough to redo all the sorting stuff.
  if $files.size == 1
    # its a dir, let give the next level at least
    if $files.first[-1] == "/"
      d = $files.first
      #f = `zsh -c 'print -rl -- #{d}*(omM)'`.split("\n")
      f = get_file_list d
      if f && f.size > 0
        $files.concat f
        $files.concat get_important_files(d)
        return
      end
    else
      # just a file, not dirs here
      return
    end
  end
  #
  # check if a ruby project dir, although it could be a backup file too,
  # if so , expand lib and maby bin, put a couple recent files
  #
  if $files.index("Gemfile") || $files.grep(/\.gemspec/).size > 0
    # usually the lib dir has only one file and one dir
    flg = false
    $files.concat get_important_files(Dir.pwd)
    if $files.index("lib/")
      f = `zsh -c 'print -rl -- lib/*(om[1,5]MN)'`.split("\n")
      if f && f.size() > 0
        insert_into_list("lib/", f)
        flg = true
      end
      dd = File.basename(Dir.pwd)
      if f.index("lib/#{dd}/")
        f = `zsh -c 'print -rl -- lib/#{dd}/*(om[1,5]MN)'`.split("\n")
        if f && f.size() > 0
          insert_into_list("lib/#{dd}/", f)
          flg = true
        end
      end
    end
    if $files.index("bin/")
      f = `zsh -c 'print -rl -- bin/*(om[1,5]MN)'`.split("\n")
      insert_into_list("bin/", f) if f && f.size() > 0
      flg = true
    end
    return if flg

    # lib has a dir in it with the gem name

  end
  return if $files.size > 15

  ## first check accessed else modified will change accessed
  moda = `zsh -c 'print -rn -- *(/oa[1]MN)'`
  if moda && moda != ""
    modf = `zsh -c 'print -rn -- #{moda}*(oa[1]MN)'`
    if modf && modf != ""
      insert_into_list moda, modf
    end
    modm = `zsh -c 'print -rn -- #{moda}*(om[1]MN)'`
    if modm && modm != "" && modm != modf
      insert_into_list moda, modm
    end
  end
  ## get last modified dir
  modm = `zsh -c 'print -rn -- *(/om[1]MN)'`
  if modm != moda
    modmf = `zsh -c 'print -rn -- #{modm}*(oa[1]MN)'`
    insert_into_list modm, modmf
    modmf1 = `zsh -c 'print -rn -- #{modm}*(om[1]MN)'`
    insert_into_list(modm, modmf1) if modmf1 != modmf
  else
    # if both are same then our options get reduced so we need to get something more
    # If you access the latest mod dir, then come back you get only one, since mod and accessed
    # are the same dir, so we need to find the second modified dir
  end
end
enter_regex() click to toggle source

take regex from user, to run on files on screen, user can filter file names

# File lib/cygnus.rb, line 446
def enter_regex
  patt = get_line "Enter (regex) pattern: "
  #$patt = gets().chomp
  #$patt = Readline::readline('>', true)
  $patt = patt
  return patt
end
escape() click to toggle source

clear sort order and refresh listing, used typically if you are in some view such as visited dirs or files

# File lib/cygnus.rb, line 345
def escape
  $sorto = nil
  $sorto = $default_sort_order
  $viewctr = 0
  $title = nil
  $filterstr = "M"
  visual_block_clear
  c_refresh
end
extras() click to toggle source
# File lib/cygnus.rb, line 640
def extras
  h = { "1" => :one_column, "2" => :multi_column, :c => :columns, :r => :config_read , :w => :config_write}
  ch, menu_text = menu "Extras Menu", h
  case menu_text
  when :one_column
    $pagesize = $grows
  when :multi_column
    #$pagesize = 60
    $pagesize = $grows * $gviscols
  when :columns
    ch = get_single "How many columns to show: 1-6 [current #{$gviscols}]? "
    #ch = get_char
    ch = ch.to_i
    if ch > 0 && ch < 7
      $gviscols = ch.to_i
      $pagesize = $grows * $gviscols
    end
  end
end
ffind() click to toggle source
# File lib/cygnus.rb, line 1214
def ffind
  pattern = get_line "Enter a file name pattern to find: "
  return if pattern.nil? || pattern == ""
  $title = "Files found using 'find' #{pattern}"
  files = `find . -name '#{pattern}'`.split("\n")
  if files.size == 0
    perror "No files found."
  else
    $files = files
    show_list
  end
end
file_actions(action=nil) click to toggle source

currently i am only passing the action in from the list there as a key I should be able to pass in new actions that are external commands

# File lib/cygnus.rb, line 1045
def file_actions action=nil
  h = { :d => :delete, :m => :move, :r => :rename, :v => ENV["EDITOR"] || :vim,
    :c => :copy, :C => :chdir,
    :l => :less, :s => :most , :f => :file , :o => :open, :x => :dtrx, :z => :zip }
  #acttext = h[action.to_sym] || action
  acttext = action || ""
  file = nil

  sct = $selected_files.size
  if sct > 0
    text = "#{sct} files"
    file = $selected_files
  else
    #print "[#{acttext}] Choose a file [#{$view[$cursor]}]: "
    t = "[#{acttext}] Choose a file [#{$view[$cursor]}]: "
    file = ask_hint t, $view[$cursor]
    return unless file
    text = file
  end

  case file
  when Array
    # escape the contents and create a string
    files = Shellwords.join(file)
  when String
    files = Shellwords.escape(file)
  end


  ch = nil
  if action
      menu_text = action
  else
    ch, menu_text = menu "File Menu for #{text}", h
    menu_text = :quit if ch == "q"
  end
  return unless menu_text
  case menu_text.to_sym
  when :quit
  when :delete
    ch = get_single "rmtrash #{files} ?[yn]: "
    #print "rmtrash #{files} ?[yn]: "
    #ch = get_char
    return if ch != "y"
    c_system "rmtrash #{files}"
    c_refresh
  when :move
    #print "move #{text} to : "
    #target = gets().chomp
    #target = Readline::readline('>', true)
    target = get_line "move #{text} to : "
    text=File.expand_path(text)
    return if target.nil? || target == ""
    if File.directory? target
      FileUtils.mv text, target
      c_refresh
    else
      perror "Target not a dir"
    end
  when :copy
    target = get_line "copy #{text} to : "
    #target = Readline::readline('>', true)
    return if target.nil? || target == ""
    text=File.expand_path(text)
    target = File.basename(text) if target == "."
    if File.exists? target
      perror "Target (#{target}) exists"
    else
      FileUtils.cp text, target
      c_refresh
    end
  when :chdir
    change_dir File.dirname(text)
  when :zip
    target = get_line "Archive name: "
    #target = gets().chomp
    #target = Readline::readline('>', true)
    return if target.nil? || target == ""
    # don't want a blank space or something screwing up
    if target && target.size > 3
      if File.exists? target
        perror "Target (#{target}) exists"
      else
        c_system "tar zcvf #{target} #{files}"
        c_refresh
      end
    end
  when :rename
  when :most, :less, :vim, ENV['EDITOR']
    c_system "#{menu_text} #{files}"
  else
    return unless menu_text
    $log.debug "XXX:  menu_text #{menu_text.to_sym}"
    get_single "#{menu_text} #{files}"
    #pause
    #print
    c_system "#{menu_text} #{files}"
    pause
    c_refresh
  end
  # remove non-existent files from select list due to move or delete or rename or whatever
  if sct > 0
    $selected_files.reject! {|x| x = File.expand_path(x); !File.exists?(x) }
  end
end
file_matching?(file, patt) click to toggle source
# File lib/cygnus.rb, line 1302
def file_matching? file, patt
  file =~ /#{patt}/
end
filetype(f) click to toggle source
# File lib/cygnus.rb, line 1333
def filetype f
  return nil unless f
  f = Shellwords.escape(f)
  s = `file #{f}`
  if s.index "text"
    return :text
  elsif s.index(/[Zz]ip/)
    return :zip
  elsif s.index("archive")
    return :zip
  elsif s.index "image"
    return :image
  elsif s.index "data"
    return :text
  else
    return :directory if File.directory? f
  end
  return :unknown
end
filter_menu() click to toggle source
# File lib/cygnus.rb, line 659
def filter_menu
  h = { :d => :dirs, :f => :files, :e => :emptydirs , "0" => :emptyfiles}
  ch, menu_text = menu "Filter Menu", h
  files = nil
  case menu_text
  when :dirs
    $filterstr = "/M"
    files = `zsh -c 'print -rl -- *(#{$sorto}/M)'`.split("\n")
    $title = "Filter: directories only"
  when :files
    $filterstr = "."
    files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}.)'`.split("\n")
    $title = "Filter: files only"
  when :emptydirs
    $filterstr = "/D^F"
    files = `zsh -c 'print -rl -- *(#{$sorto}/D^F)'`.split("\n")
    $title = "Filter: empty directories"
  when :emptyfiles
    $filterstr = ".L0"
    files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}.L0)'`.split("\n")
    $title = "Filter: empty files"
  end
  if files
    $files = files
    show_list
    $stact = 0
  end
end
format(ary) click to toggle source

formats the data with number, mark and details

# File lib/cygnus.rb, line 223
def format ary
  alert "deprecated, can be removed if not called"
  #buff = Array.new
  buff = Array.new(ary.size)
  return buff if ary.nil? || ary.size == 0

  # determine width based on number of files to show
  # if less than sz then 1 col and full width
  #
  # ix refers to the index in the complete file list, wherease we only show 60 at a time
  ix=0
  ctr=0
  ary.each do |f|
    ## ctr refers to the index in the column
    ind = get_shortcut(ix)
    mark=SPACE
    cur=SPACE
    cur = CURMARK if ix + $sta == $cursor
    mark=GMARK if $selected_files.index(ary[ix])

    if $long_listing
      begin
        unless File.exist? f
          last = f[-1]
          if last == " " || last == "@" || last == '*'
            stat = File.stat(f.chop)
          end
        else
          stat = File.stat(f)
        end
        f = "%10s  %s  %s" % [readable_file_size(stat.size,1), date_format(stat.mtime), f]
      rescue Exception => e
        f = "%10s  %s  %s" % ["?", "??????????", f]
      end
    end

    s = "#{ind}#{mark}#{cur}#{f}"
    # I cannot color the current line since format does the chopping
    # so not only does the next lines alignment get skeweed, but also if the line is truncated
    # then the color overflows.
    #if ix + $sta == $cursor
      #s = "#{RED}#{s}#{CLEAR}"
    #end

    buff[ctr] = s

    ctr+=1
    ix+=1
  end
  return buff
end
get_char() click to toggle source

I thin we need to make this like the command line one TODO

# File lib/cygnus.rb, line 910
def get_char
  c = @window.getchar
  case c
  when 13,10
    return "ENTER"
  when 32
    return "SPACE"
  when 127
    return "BACKSPACE"
  when 27
    return "ESCAPE"
  end
  keycode_tos c
#  if c > 32 && c < 127
    #return c.chr
  #end
  ## use keycode_tos from Utils.
end
get_env_paths() click to toggle source
# File lib/cygnus.rb, line 768
def get_env_paths
  files = []
  %w{ GEM_HOME PYTHONHOME}.each do |p|
    d = ENV[p]
    files.push d if d
  end
  %w{ RUBYLIB RUBYPATH GEM_PATH PYTHONPATH }.each do |p|
    d = ENV[p]
    files.concat d.split(":") if d
  end
  return files
end
get_important_files(dir) click to toggle source

checks various lists like visited_files and bookmarks to see if files from this dir or below are in it. More to be used in a dir with few files.

# File lib/cygnus.rb, line 1529
def get_important_files dir
  list = []
  l = dir.size + 1
  s = nil
  ($visited_files + $bookmarks.values).each do |e|
    if e.index(dir) == 0
      #list << e[l..-1]
      s =  e[l..-1]
      next unless s
      if s.index ":"
        s = s[0, s.index(":")] + "/"
      end
      # only insert if the file is in a deeper dir, otherwise we'll be duplicating files from this folder
      list << s if s.index "/"
    end
  end
  # bookmarks have : which needs to be removed
  #list1 = $bookmarks.values.select do |e|
    #e.index(dir) == 0
  #end
  #list.concat list1
  return list
end
get_index(key, vsz=999) click to toggle source
returns the integer offset in view (file array based on a-y za-zz and Za - Zz

Called when user types a key

should we even ask for a second key if there are not enough rows
What if we want to also trap z with numbers for other purposes
# File lib/cygnus.rb, line 958
def get_index key, vsz=999
  i = $IDX.index(key)
  return i+$stact if i
  #sz = $IDX.size
  zch = nil
  if vsz > 25
    if key == "z" || key == "Z"
      #print key
      zch = get_char
      #print zch
      i = $IDX.index("#{key}#{zch}")
      return i+$stact if i
    end
  end
  return nil
end
get_line(text, config={}) click to toggle source

identical to get_string but does not show as a popup with buttons, just ENTER This is required if there are multiple inputs required and having several get_strings one after the other seems really odd due to multiple popups Unlike, get_string this does not return a nil if C-c pressed. Either returns a string if ENTER pressed or a blank if C-c or Double Escape. So only blank to be checked

# File lib/cygnus.rb, line 1578
def get_line text, config={}
  begin
    w = one_line_window
    form = RubyCurses::Form.new w

    f = Field.new form, :label => text, :row => 0, :col => 1
    form.repaint
    w.wrefresh
    while((ch = w.getchar()) != FFI::NCurses::KEY_F10 )
      break if ch == 13
      if ch == 3 || ch == 27 || ch == 2727
        return ""
      end
      begin
        form.handle_key(ch)
        w.wrefresh
      rescue => err
        $log.debug( err) if err
        $log.debug(err.backtrace.join("\n")) if err
        textdialog ["Error in Messagebox: #{err} ", *err.backtrace], :title => "Exception"
        w.refresh # otherwise the window keeps showing (new FFI-ncurses issue)
        $error_message.value = ""
      ensure
      end
    end # while loop

  ensure
    w.destroy
    w = nil 
  end
  return f.text
end
get_shortcut(ix) click to toggle source
return shortcut for an index (offset in file array)

use 2 more arrays to make this faster

if z or Z take another key if there are those many in view
Also, display ROWS * COLS so now we are not limited to 60.
# File lib/cygnus.rb, line 947
def get_shortcut ix
  return "<" if ix < $stact
  ix -= $stact
  i = $IDX[ix]
  return i if i
  return "->"
end
get_single(text, config={}) click to toggle source

prints a prompt at bottom of screen, takes a character and returns textual representation of character (as per get_char) and not the int that window.getchar returns. It uses a window, so underlying text is not touched.

# File lib/cygnus.rb, line 1557
def get_single text, config={}
  w = one_line_window
  x = y = 0
  color = config[:color_pair] || $datacolor
  color=Ncurses.COLOR_PAIR(color);
  w.attron(color);
  w.mvprintw(x, y, "%s" % text);
  w.attroff(color);
  w.wrefresh
  Ncurses::Panel.update_panels
  chr = get_char
  w.destroy
  w = nil 
  return chr
end
goto_dir() click to toggle source

accept dir to goto and change to that ( can be a file too)

# File lib/cygnus.rb, line 378
def goto_dir
  begin
    path = get_line "Enter path: "
    return if path.nil? || path == ""
  rescue Exception => ex
    perror "Cancelled cd, press a key"
    return
  end
  f = File.expand_path(path)
  unless File.directory? f
    ## check for env variable
    tmp = ENV[path]
    if tmp.nil? || !File.directory?( tmp )
      ## check for dir in home
      tmp = File.expand_path("~/#{path}")
      if File.directory? tmp
        f = tmp
      end
    else
      f = tmp
    end
  end

  open_file f
end
goto_entry_starting_with(fc=nil) click to toggle source

This actually filters, in zfm it goes to that entry since we have a cursor there

# File lib/cygnus.rb, line 433
def goto_entry_starting_with fc=nil
  unless fc
    fc = get_single "Entries starting with: "
    #fc = get_char
  end
  return if fc.size != 1
  ## this is wrong and duplicates the functionality of /
  #  It shoud go to cursor of item starting with fc
  $patt = "^#{fc}"
end
goto_line(pos) click to toggle source

position cursor on a specific line which could be on a nother page therefore calculate the correct start offset of the display also.

# File lib/cygnus.rb, line 1325
def goto_line pos
  pages = ((pos * 1.00)/$pagesize).ceil
  pages -= 1
  #$sta = pages * $pagesize + 1
  $sta = pages * $pagesize + 0
  $cursor = pos
  #$log.debug "XXX: GOTO_LINE #{$sta} :: #{$cursor}"
end
goto_parent_dir() click to toggle source
# File lib/cygnus.rb, line 428
def goto_parent_dir
  change_dir ".."
end
insert_into_list(dir, file) click to toggle source
# File lib/cygnus.rb, line 1517
def insert_into_list dir, file
  ## earlier we were inserting these files at helpful points (before the dirs), but they are touch to find.
  # I think it;s better to put at end
  #ix = $files.index(dir)
  #raise "something wrong can find #{dir}." unless ix
  #$files.insert ix, *file
  $files.push *file 
end
locate() click to toggle source
# File lib/cygnus.rb, line 1226
def locate
  pattern = get_line "Enter a file name pattern to locate: "
  return if pattern.nil? || pattern == ""
  $title = "Files found using 'locate' #{pattern}"
  files = `locate #{pattern}`.split("\n")
  files.reject! {|x| x = File.expand_path(x); !File.exists?(x) }
  if files.size == 0
    perror "No files found."
  else
    $files = files
    show_list
  end
end
main_menu() click to toggle source

MENU MAIN – keep consistent with zfm

moveto(pos) click to toggle source
# File lib/cygnus.rb, line 1267
def moveto pos
  orig = $cursor
  $cursor = pos
  $cursor = [$cursor, $view.size - 1].min
  $cursor = [$cursor, 0].max
  star = [orig, $cursor].min
  fin = [orig, $cursor].max
  if $visual_mode
    # PWD has to be there in selction
    if $selected_files.index $view[$cursor]
      # this depends on the direction
      $selected_files = $selected_files - $view[star..fin]
      ## current row remains in selection always.
      $selected_files.push $view[$cursor]
    else
      $selected_files.concat $view[star..fin]
    end
  end
end
newdir() click to toggle source
# File lib/cygnus.rb, line 1368
def newdir
  #print
  #print "Enter directory name: "
  #str = Readline::readline('>', true)
  str = get_line "Enter directory name: "
  return if str.nil? || str == ""
  if File.exists? str
    perror "#{str} exists."
    return
  end
  begin
    FileUtils.mkdir str
    $used_dirs.insert(0, str) if File.exists?(str)
    c_refresh
  rescue Exception => ex
    perror "Error in newdir: #{ex}"
  end
end
newfile() click to toggle source
# File lib/cygnus.rb, line 1386
def newfile
  #print
  str = get_line "Enter file name: "
  #str = Readline::readline('>', true)
  return if str.nil? || str == ""
  c_system "$EDITOR #{str}"
  $visited_files.insert(0, str) if File.exists?(str)
  c_refresh
end
next_page() click to toggle source
# File lib/cygnus.rb, line 453
def next_page
  # FIXME cursor position, take logic from zfm page calc
  $sta += $pagesize
  $cursor = $sta if $cursor < $sta
end
pause(text=" Press a key ...") click to toggle source
# File lib/cygnus.rb, line 939
def pause text=" Press a key ..."
  get_single text
  #get_char
end
pbold(text) click to toggle source
# File lib/cygnus.rb, line 929
def pbold text
  #puts "#{BOLD}#{text}#{BOLD_OFF}"
  get_single text, :color_pair => $reversecolor
end
perror(text) click to toggle source
# File lib/cygnus.rb, line 933
def perror text
  ##puts "#{RED}#{text}#{CLEAR}"
  #get_char
  #alert text
  get_single text + "  Press a key...", :color_pair => $errorcolor
end
pop_dir() click to toggle source

part copied and changed from change_dir since we don’t dir going back on top or we’ll be stuck in a cycle

# File lib/cygnus.rb, line 714
def pop_dir
  # the first time we pop, we need to put the current on stack
  if !$visited_dirs.index(Dir.pwd)
    $visited_dirs.push Dir.pwd
  end
  ## XXX make sure thre is something to pop
  d = $visited_dirs.delete_at 0
  ## XXX make sure the dir exists, cuold have been deleted. can be an error or crash otherwise
  $visited_dirs.push d
  Dir.chdir d
  display_dir

  return
  # old stuff with zsh
  $filterstr ||= "M"
  $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}#{$filterstr})'`.split("\n")
  post_cd
end
pos() click to toggle source
# File lib/cygnus.rb, line 1263
def pos
  $cursor
end
prev_page() click to toggle source
# File lib/cygnus.rb, line 458
def prev_page
  # FIXME cursor position, take logic from zfm page calc
  $sta -= $pagesize
  $cursor = $sta
end
print_help() click to toggle source
push_used_dirs(d=Dir.pwd) click to toggle source

create a list of dirs in which some action has happened, for saving

# File lib/cygnus.rb, line 906
def push_used_dirs d=Dir.pwd
  $used_dirs.index(d) || $used_dirs.push(d)
end
quit_command() click to toggle source
# File lib/cygnus.rb, line 853
def quit_command
  if $modified
    s = ""
    s << "Press w to save bookmarks before quitting. " if $modified
    s << "Press another q to quit "
    ch = get_single s
    #ch = get_char
  else
    $quitting = true
  end
  $quitting = true if ch == "q"
  $quitting = $writing = true if ch == "w"
end
readable_file_size(size, precision) click to toggle source

Return the file size with a readable style.

# File lib/cygnus.rb, line 76
def readable_file_size(size, precision)
  case
    #when size == 1 : "1 B"
  when size < KILO_SIZE then "%d B" % size
  when size < MEGA_SIZE then "%.#{precision}f K" % (size / KILO_SIZE)
  when size < GIGA_SIZE then "%.#{precision}f M" % (size / MEGA_SIZE)
  else "%.#{precision}f G" % (size / GIGA_SIZE)
  end
end
recent_files() click to toggle source
# File lib/cygnus.rb, line 894
def recent_files
  # print -rl -- **/*(Dom[1,10])
  $title = "Recent files"
  $files = `zsh -c 'print -rl -- **/*(Dom[1,15])'`.split("\n")
end
remove_from_list() click to toggle source

Editing of the User Dir List. remove current entry from used dirs list, since we may not want some entries being there

# File lib/cygnus.rb, line 1400
def remove_from_list
  if $selected_files.size > 0
    sz = $selected_files.size
    ch = get_single "Remove #{sz} files from used list (y)?: "
    #ch = get_char
    return if ch != "y"
    $used_dirs = $used_dirs - $selected_files
    $visited_files = $visited_files - $selected_files
    unselect_all
    $modified = true
    return
  end
  #print
  ## what if selected some rows
  file = $view[$cursor]
  ch = get_single "Remove #{file} from used list (y)?: "
  #ch = get_char
  return if ch != "y"
  file = File.expand_path(file)
  if File.directory? file
    $used_dirs.delete(file)
  else
    $visited_files.delete(file)
  end
  c_refresh
  $modified = true
end
return_next_match(binding, *args) click to toggle source

generic method to take cursor to next position for a given condition

# File lib/cygnus.rb, line 1307
def return_next_match binding, *args
  first = nil
  ix = 0
  $view.each_with_index do |elem,ii|
    if binding.call(elem, *args)
      first ||= ii
      if ii > $cursor 
        ix = ii
        break
      end
    end
  end
  return first if ix == 0
  return ix
end
revert_dir_pos() click to toggle source
# File lib/cygnus.rb, line 1357
def revert_dir_pos
  $sta = 0
  $cursor = 0
  a = $dir_position[Dir.pwd]
  if a
    $sta = a.first
    $cursor = a[1]
    raise "sta is nil for #{Dir.pwd} : #{$dir_position[Dir.pwd]}" unless $sta
    raise "cursor is nil" unless $cursor
  end
end
run_command(f) click to toggle source

run command on given file/s

Accepts command from user
After putting readline in place of gets, pressing a C-c has a delayed effect. It goes intot
exception bloack after executing other commands and still does not do the return !
# File lib/cygnus.rb, line 308
def run_command f
  files=nil
  case f
  when Array
    # escape the contents and create a string
    files = Shellwords.join(f)
  when String
    files = Shellwords.escape(f)
  end
  begin
    # TODO put all this get_line stuff into field history
    command = get_line "Run a command on #{files}: "
    return if command.size == 0
    command2 = get_line "Second part of command: "
    # FIXME we may need to go into cooked mode and all that for this
    # cat and most mess with the output using system
    c_system "#{command} #{files} #{command2}"
  rescue Exception => ex
    perror "Canceled command, (#{ex}) press a key"
    return
  end

  c_refresh
  push_used_dirs Dir.pwd
end
save_dir_pos() click to toggle source
# File lib/cygnus.rb, line 1353
def save_dir_pos 
  return if $sta == 0 && $cursor == 0
  $dir_position[Dir.pwd] = [$sta, $cursor]
end
screen_settings() click to toggle source

check screen size and accordingly adjust some variables

# File lib/cygnus.rb, line 1022
def screen_settings
  # TODO these need to become part of our new full_indexer class, not hang about separately.
  $glines=%x(tput lines).to_i
  $gcols=%x(tput cols).to_i
  # this depends now on textpad size not screen size TODO FIXME
  $grows = $glines - 1
  $pagesize = 60
  #$gviscols = 3
  $pagesize = $grows * $gviscols
end
select_all() click to toggle source

select all files

# File lib/cygnus.rb, line 373
def select_all
  $selected_files = $view.dup
end
select_bookmarks() click to toggle source
# File lib/cygnus.rb, line 699
def select_bookmarks
  $title = "Bookmarks"
  $files = $bookmarks.values.collect do |x| 
    if x.include? ":"
      ix = x.index ":"
      x[0,ix]
    else
      x
    end
  end
  #show_list files
end
select_current() click to toggle source
# File lib/cygnus.rb, line 899
def select_current
  ## vp is local there, so i can do $vp[0]
  #open_file $view[$sta] if $view[$sta]
  open_file $view[$cursor] if $view[$cursor]
end
select_hint(view, ch) click to toggle source

select file based on key pressed

# File lib/cygnus.rb, line 275
def select_hint view, ch
  # a to y is direct
  # if z or Z take a key IF there are those many
  #
  ix = get_index(ch, view.size)
  if ix
    f = view[ix]
    return unless f
    $cursor = $sta + ix

    if $mode == 'SEL'
      toggle_select f
    elsif $mode == 'COM'
      run_command f
    else
      open_file f
    end
    #selectedix=ix
  end
end
select_used_dirs() click to toggle source
# File lib/cygnus.rb, line 687
def select_used_dirs
  $title = "Used Directories"
  $files = $used_dirs.uniq
  #show_list
end
select_visited_files() click to toggle source
# File lib/cygnus.rb, line 692
def select_visited_files
  # not yet a unique list, needs to be unique and have latest pushed to top
  $title = "Visited Files"
  files = $visited_files.uniq
  show_list files
  $title = nil
end
selection_mode_toggle() click to toggle source

toggle mode to selection or not In selection, pressed hotkey selects a file without opening, one can keep selecting (or deselecting).

# File lib/cygnus.rb, line 408
def selection_mode_toggle
  if $mode == 'SEL'
    # we seem to be coming out of select mode with some files
    if $selected_files.size > 0
      run_command $selected_files
    end
    $mode = nil
  else
    #$selection_mode = !$selection_mode
    $mode = 'SEL'
  end
end
show_marks() click to toggle source
# File lib/cygnus.rb, line 463
def show_marks
  list = []
  $bookmarks.each_pair { |k, v| list << " #[fg=yellow, bold]#{k}#[/end] #[fg=green]#{v}#[/end]" }
  #  s="#[fg=green]hello there#[fg=yellow, bg=black, dim]"
  config = {}
  longestval = $bookmarks.values.max_by(&:length)
  config[:title] = "Bookmarks"
  config[:width] = [longestval.length + 5, FFI::NCurses.COLS - 5].min
  $log.debug "XXX:  LONGEST #{longestval}, #{longestval.length}"
  ch = padpopup list, config
  return unless ch
  #$bookmarks.each_pair { |k, v| puts "#{k.ljust(7)}  =>  #{v}" }
  #puts
  #print "Enter bookmark to goto: "
  #ch = get_char
  goto_bookmark(ch) if ch =~ /^[0-9A-Z]$/
end
sort_menu() click to toggle source
# File lib/cygnus.rb, line 564
def sort_menu
  lo = nil
  h = { :n => :newest, :a => :accessed, :o => :oldest, 
    :l => :largest, :s => :smallest , :m => :name , :r => :rname, :d => :dirs, :c => :clear }
  ch, menu_text = menu "Sort Menu", h
  case menu_text
  when :newest
    lo="om"
  when :accessed
    lo="oa"
  when :oldest
    lo="Om"
  when :largest
    lo="OL"
  when :smallest
    lo="oL"
  when :name
    lo="on"
  when :rname
    lo="On"
  when :dirs
    lo="/"
  when :clear
    lo=""
  end
  ## This needs to persist and be a part of all listings, put in change_dir.
  $sorto = lo
  $files = `zsh -c 'print -rl -- *(#{lo}#{$hidden}M)'`.split("\n") if lo
  $title = nil
  #$files =$(eval "print -rl -- ${pattern}(${MFM_LISTORDER}$filterstr)")
end
subcommand() click to toggle source
# File lib/cygnus.rb, line 817
def subcommand
  begin
    command = get_line "Enter command: "
    #command = gets().chomp
    #command = Readline::readline('>', true)
    return if command == ""
  rescue Exception => ex
    return
  end
  if command == "q"
    if $modified
      ch = get_single "Do you want to save bookmarks? (y/n): "
      #ch = get_char
      if ch == "y"
        $writing = true
        $quitting = true
      elsif ch == "n"
        $quitting = true
        print "Quitting without saving bookmarks"
      else
        perror "No action taken."
      end
    else
      $quitting = true
    end
  elsif command == "wq"
    $quitting = true
    $writing = true
  elsif command == "x"
    $quitting = true
    $writing = true if $modified
  elsif command == "p"
    c_system "echo $PWD | pbcopy"
    get_single "Stored PWD in clipboard (using pbcopy)"
  end
end
toggle_menu() click to toggle source
# File lib/cygnus.rb, line 523
def toggle_menu
  h = { :h => :toggle_hidden, :c => :toggle_case, :l => :toggle_long_list , "1" => :toggle_columns, 
  :p => :toggle_pager_mode, :e => :toggle_enhanced_list}
  ch, menu_text = menu "Toggle Menu", h
  case menu_text
  when :toggle_hidden
    #$hidden = $hidden ? nil : "D"
    $hidden = !$hidden 
    c_refresh
  when :toggle_case
    #$ignorecase = $ignorecase ? "" : "i"
    $ignorecase = !$ignorecase
    c_refresh
  when :toggle_columns
    $gviscols = 3 if $gviscols == 1
    #$long_listing = false if $gviscols > 1
    x = $grows * $gviscols
    $pagesize = $pagesize==x ? $grows : x
  when :toggle_pager_mode
    $editor_mode = !$editor_mode
    if $editor_mode
      $default_command = nil
    else
      $default_command = ENV['MANPAGER'] || ENV['PAGER']
    end
  when :toggle_enhanced_list
    $enhanced_mode = !$enhanced_mode

  when :toggle_long_list
    $long_listing = !$long_listing
    if $long_listing
      $gviscols = 1
      $pagesize = $grows
    else
      x = $grows * $gviscols
      $pagesize = $pagesize==x ? $grows : x
    end
    c_refresh
  end
end
toggle_select(f) click to toggle source

toggle selection state of file

# File lib/cygnus.rb, line 296
def toggle_select f
  if $selected_files.index f
    $selected_files.delete f
  else
    $selected_files.push f
  end
end
tree() click to toggle source

Get a full recursive listing of what’s in this dir - useful for small projects with more structure than files.

# File lib/cygnus.rb, line 889
def tree
  # Caution: use only for small projects, don't use in root.
  $title = "Full Tree"
  $files = `zsh -c 'print -rl -- **/*(#{$sorto}#{$hidden}M)'`.split("\n")
end
unselect_all() click to toggle source

unselect all files

# File lib/cygnus.rb, line 367
def unselect_all
  $selected_files = []
  $visual_mode = nil
end
views() click to toggle source
# File lib/cygnus.rb, line 867
def views
  views=%w[/ om oa Om OL oL On on]
  viewlabels=%w[Dirs Newest Accessed Oldest Largest Smallest Reverse Name]
  $sorto = views[$viewctr]
  $title = viewlabels[$viewctr]
  $viewctr += 1
  $viewctr = 0 if $viewctr > views.size

  $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}M)'`.split("\n")

end
viminfo() click to toggle source
# File lib/cygnus.rb, line 1178
def viminfo
  file = File.expand_path("~/.viminfo")
  if File.exists? file
    $title = "Files from ~/.viminfo"
    #$files = `grep '^>' ~/.viminfo | cut -d ' ' -f 2- | sed "s#~#$HOME#g"`.split("\n")
    $files = `grep '^>' ~/.viminfo | cut -d ' ' -f 2- `.split("\n")
    $files.reject! {|x| x = File.expand_path(x); !File.exists?(x) }
    show_list
  end
end
visual_block_clear() click to toggle source
# File lib/cygnus.rb, line 1293
def visual_block_clear
  if $visual_block_start
    star = [$visual_block_start, $cursor].min
    fin = [$visual_block_start, $cursor].max
    $selected_files = $selected_files - $view[star..fin]
  end
  $visual_block_start = nil
  $visual_mode = nil
end
visual_mode_toggle() click to toggle source
# File lib/cygnus.rb, line 1286
def visual_mode_toggle
  $visual_mode = !$visual_mode
  if $visual_mode
    $visual_block_start = $cursor
    $selected_files.push $view[$cursor]
  end
end
z_interface() click to toggle source
# File lib/cygnus.rb, line 1188
def z_interface
  file = File.expand_path("~/.z")
  if File.exists? file
    $title = "Directories from ~/.z"
    $files = `sort -rn -k2 -t '|' ~/.z | cut -f1 -d '|'`.split("\n")
    home = ENV['HOME']
    $files.collect! do |f| 
      f.sub(/#{home}/,"~")
    end
    show_list
  end
end