Monday, October 24, 2011

Hello, this is my second post in this blog. Same as my previous post, I still give some example code about Ruby. But, in this occasion I want to tell you how to make a text editor using Ruby programming language, which now is using function and array.

In this program, first it will ask the user what to do. User can choose to type a new document, open an existing document, or exit the program. If user choose to type a new document, the program will loops while get the input from user and save it in a variable 'text' until user input ':eof:'. After that, the program ask the user where to save the file by opening a save dialog (a function). Then, it will ask the user the file name. Finally, write the variable 'text' to the specified file.

If user choose to open an existing document, the program ask the user where is the file located by opening an open dialog (a function). After that, the program will loops while get the input from the file and save it in an array named 'linecontent' until the end of the file. After reading, the program will show two option to edit the file. The first one is to replace whole selected line. The second one is to find some string and replace all occurrence of that string with the string inputted by user. Both action will use or modify the array 'linecontent' before. After each finished action, it will saved to the file automatically.

Now about the dialog function, it will ask one parameter 'type'. The function will show the current directory path and the content of that directory. User can also change the current directory by using command menu or enter a directory number (see previous post for detail). If the type is open, user must choose one file, and the function will return that file path. But if the type is save, user must choose a directory, and the function will return the current directory path.

Here's the output if you're having difficulty in imagining what I tell you before:

CONSOLE TEXT EDITOR
-------------------

1. New
2. Open
3. Exit

What do you want to do?
> 1

Start typing your document now. Enter ":eof:" if you has finished typing.

LINE 1      |   Hello! Hello,
LINE 2      |   world...
LINE 3      |   
LINE 4      |   - Ruby
LINE 5      |   :eof:

Specify the folder where you want to save the new document!

Current directory: C:/Documents and Settings/Admin/Desktop/RubyApp1/lib
Directory content: 
  1. a.txt                                                 0.02 KiB
  2. editor.rb                                             5.03 KiB
  3. fileinfogetter.rb                                     2.44 KiB
  4. productmanager.rb                                     2.92 KiB

Available Commands:
U: To Upper    R: To Root     G: Go to       D: Save in this directory

Type your selected item number, or command letter
> g
Go to what directory?
> d:\

Current directory: D:/
Directory content: 
  1. [Directory] $AVG                                              
  2. [Directory] System Volume Information                         
  3. Thumbs.db                                            10.50 KiB

Available Commands:
U: To Upper    R: To Root     G: Go to       D: Save in this directory

Type your selected item number, or command letter
> d

Selected folder: D:/
Now specify the file name!
> Hello.txt

File saved.



CONSOLE TEXT EDITOR
-------------------

1. New
2. Open
3. Exit

What do you want to do?
> 2
Current directory: D:/
Directory content: 
  1. [Directory] $AVG                                              
  2. [Directory] System Volume Information                         
  3. Hello.txt                                             0.03 KiB
  4. Thumbs.db                                            10.50 KiB

Available Commands:
U: To Upper    R: To Root     G: Go to       C: Cancel      

Type your selected item number, or command letter
> 3

-- [BEGINNING OF FILE] --
LINE 1      |   Hello! Hello,
LINE 2      |   world...
LINE 3      |   
LINE 4      |   - Ruby
-- [END OF FILE] --

1. Replace line
2. Replace string
3. Exit editing

What do you want to do?
> 1
Replace line : 2
Selected line: world...
Replace with : Earth...
File saved.

1. Replace line
2. Replace string
3. Exit editing

What do you want to do?
> 2
Replace what: e
Replace with: a
File saved.

1. Replace line
2. Replace string
3. Exit editing

What do you want to do?
> 3



CONSOLE TEXT EDITOR
-------------------

1. New
2. Open
3. Exit

What do you want to do?
> 2
Current directory: D:/
Directory content: 
  1. [Directory] $AVG                                              
  2. [Directory] System Volume Information                         
  3. Hello.txt                                             0.03 KiB
  4. Thumbs.db                                            10.50 KiB

Available Commands:
U: To Upper    R: To Root     G: Go to       C: Cancel      

Type your selected item number, or command letter
> 3

-- [BEGINNING OF FILE] --
LINE 1      |   Hallo! Hallo,
LINE 2      |   world...
LINE 3      |   
LINE 4      |   - Ruby
-- [END OF FILE] --

1. Replace line
2. Replace string
3. Exit editing

What do you want to do?
> 3


CONSOLE TEXT EDITOR
-------------------

1. New
2. Open
3. Exit

What do you want to do?
> 3

I originally typed the code in NetBeans, but you can try to run it using another IDE or interpreter. So, here's the code. If you don't understand some part of it, you can ask it through the comment in this post.

def dialog (type)
  begin
      no = 0
      item = Array.new

      puts 'Current directory: ' << Dir.pwd
      puts 'Directory content: '

      for x in Dir.entries(Dir.pwd)
        if File::directory?(x) == true and x!='.' and x!='..' and no < 1000
          no += 1
          item[no] = x
          puts no.to_s.rjust(3)<<'. [Directory] '<<item[no][0..49].ljust(50)
        end
      end

      for x in Dir.entries(Dir.pwd)
        if File::directory?(x) == false and no < 1000
          no += 1
          item[no] = x
          print no.to_s.rjust(3) << '. ' << item[no][0..47].ljust(48)
          begin
            filesize = (File::size?(x)/1024.0)
            printf "%10.2f KiB", filesize
          rescue
            print '     (N/A) KiB'
          end
          puts
        end
      end

      puts
      puts  'Available Commands:'
      print 'U: To Upper'.ljust(15)<<'R: To Root'.ljust(15)
      print 'G: Go to'.ljust(15)
      puts  'C: Cancel'.ljust(15) if type=='open'
      puts  'D: Save in this directory'.ljust(15) if type=='save'

      puts
      puts 'Type your selected item number, or command letter'
      print '> '
      input = gets.chomp.downcase

      case input
      when 'u'
        Dir.chdir('..')
      when 'r'
        Dir.chdir(Dir.pwd[0..2])
      when 'g'
        puts 'Go to what directory?'
        print '> '
        foldergoto = gets.chomp.downcase
        begin
          Dir.chdir(foldergoto)
        rescue Exception => e
          puts e.message
          gets
        end
      when 'c'
        return if type=='open'
      when 'd'
        return Dir.pwd if type=='save'
      else
        inputint = input.to_i
        if inputint < 1 or inputint > item.length - 1
          puts 'Invalid input. Max. value is ' << (item.length - 1).to_s
          gets
        else
          if File::directory?(item[inputint]) == true
            begin
              Dir.chdir(item[inputint])
            rescue Exception => e
              puts e.message
              gets
            end
          else
            return item[inputint]
          end
        end
      end
  end until input == 'c'
end

#Dir.chdir("D:/")

begin
  puts "\n" * 25
  puts 'CONSOLE TEXT EDITOR'
  puts '-------------------'
  puts

  puts '1. New'
  puts '2. Open'
  puts '3. Exit'

  puts
  puts 'What do you want to do?'
  print '> '
  inputmain = gets.to_i

  case inputmain
  when 1 #New
    puts
    print 'Start typing your document now. '
    puts 'Enter ":eof:" if you has finished typing.'
    puts
    text = ''
    line = 1
    begin
      print 'LINE '<<line.to_s.ljust(4)<<'   |   '
      thisline = gets
      text += thisline if thisline.chomp != ':eof:'
      line += 1
    end until thisline.chomp == ':eof:'

    puts
    puts 'Specify the folder where you want to save the new document!'
    gets
    namafolder = dialog 'save'
    puts
    puts 'Selected folder: ' << namafolder
    puts 'Now specify the file name!'
    print '> '
    namafile = gets.chomp

    file = File.new(namafolder<<"/"<<namafile, 'w')
    file.print text
    file.close()

    puts 'File saved.'

  when 2 #Open
    line = 1
    linecontent = Array.new
    namafile = dialog 'open'

    puts
    puts '-- [BEGINNING OF FILE] --'
    file = File.new(namafile, 'r')
    file.each {|thisline|
      puts 'LINE '<<line.to_s.ljust(4)<<'   |   '<<thisline.chomp
      linecontent[line] = thisline
      if line % 20 == 0
        puts 'Press Enter to continue.'
        gets
      end
      line += 1
    }
    file.close()
    puts '-- [END OF FILE] --'
    puts
    
    begin
      puts '1. Replace line'
      puts '2. Replace string'
      puts '3. Exit editing'

      puts
      puts 'What do you want to do?'
      print '> '
      input2 = gets.to_i
      
      case input2
      when 1
        print 'Replace line : '
        whichline = gets.to_i
        if whichline < 1 or whichline > linecontent.length-1
          puts 'Invalid input. Max. value is '<<(linecontent.length-1).to_s
        else
            puts  'Selected line: ' << linecontent[whichline]
            print 'Replace with : '
            replacewith = gets

            file2 = File.new(namafile, 'w')
            linew = 1

            while linew < linecontent.length
              file2.print replacewith if linew == whichline
              file2.print linecontent[linew] if linew != whichline
              linew += 1
            end
            file2.close()

            puts 'File saved.'
         end
      when 2
        print 'Replace what: '
        replacewhat = gets.chomp
        print 'Replace with: '
        replacewith = gets.chomp

        file2 = File.new(namafile, 'w')
        linew = 1

        while linew < linecontent.length
          linecontent[linew]=linecontent[linew].tr(replacewhat,replacewith)
          file2.print linecontent[linew]
          linew += 1
        end
        file2.close()

        puts 'File saved.'
      when 3
        print ''
      else
        puts 'Invalid input.'
      end
      gets
    end until input2 == 3

  when 3 #Exit
    print ''
  else
    puts 'Invalid input'
  end
  gets
end until inputmain == 3
#

I think that's all for now. I hope this article can made you understand how to access file and directory, file reading, editing, and writing in Ruby. See you in the next post.