Class: Patman

Inherits:
Object
  • Object
show all
Defined in:
lib/patman.rb,
lib/version.rb

Overview

Patman (Patch Manipulator) is a library for text file patching. It can also be used to extract information from files.

Defined Under Namespace

Classes: PatmanError, PatmanFileError, PatmanSearchError

Constant Summary collapse

VERSION =
"0.0.4"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ Patman

Create Patman object.



45
46
47
48
49
50
51
52
53
# File 'lib/patman.rb', line 45

def initialize( file )
    @file = file
    @lines = []
    @line = 0
    @mark = nil
    @marks = {}
    @blockline = nil
    @edited = false
end

Instance Attribute Details

#marksObject

Returns the value of attribute marks



15
16
17
# File 'lib/patman.rb', line 15

def marks
  @marks
end

Class Method Details

.edit(file, &blk) ⇒ Object

Edit file and also create it if it does not exist.

If block is given, a file will be opened and block with Patman commands will be executed for it. Otherwise a Patman object is returned for further use.



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/patman.rb', line 31

def Patman.edit( file, &blk )
    p = Patman.new( file )
    if File.exist?( file )
        p.send( :read, file )
    end
    if block_given?
        p.instance_exec( &blk )
        p.send( :write )
    else
        p
    end
end

.read(file) ⇒ Object

Create editing session with file.



19
20
21
22
23
# File 'lib/patman.rb', line 19

def Patman.read( file )
    p = Patman.new( file )
    p.read
    p
end

.versionObject



3
4
5
# File 'lib/version.rb', line 3

def Patman.version
    Patman::VERSION
end

Instance Method Details

#[](range) ⇒ Object

Reference Patman content by range.



141
142
143
# File 'lib/patman.rb', line 141

def []( range )
    @lines[ range ]
end

#append(text = nil) ⇒ Object

Append after current position.



210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/patman.rb', line 210

def append( text = nil )
    @edited = true
    if text.kind_of? Array
        text.each do |txt|
            append( txt )
        end
    else
        step
        @lines.insert( @line, text )
    end
    self
end

#blocklineObject

Jump to line after block.



123
124
125
126
127
128
# File 'lib/patman.rb', line 123

def blockline
    if @blockline
        @line = @blockline
    end
    self
end

#clearObject

Clear Patman content and reset current line.



243
244
245
246
247
248
# File 'lib/patman.rb', line 243

def clear
    @edited = true
    @lines = []
    @line = 0
    self
end

#copy(file) ⇒ Object

Copy Patman content to file.



89
90
91
92
# File 'lib/patman.rb', line 89

def copy( file )
    write( file )
    self
end

#delete(count = 1) ⇒ Object

Delete current line.



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

def delete( count = 1 )
    @edited = true
    count.times do |i|
        @lines.delete_at( @line )
    end
    self
end

#do_all(&blk) ⇒ Object

Execute given block for all lines, i.e. all positions. Block parameter is Patman.



324
325
326
# File 'lib/patman.rb', line 324

def do_all( &blk )
    do_for( 1, length-1, &blk )
end

#do_for(start, count, &blk) ⇒ Object

Execute given block starting from start by count, and update position.



336
337
338
339
340
341
342
343
344
345
346
# File 'lib/patman.rb', line 336

def do_for( start, count, &blk )
    line = @line
    @line = start-1
    count.times do
        yield self
        @line += 1
    end
    @blockline = @line
    @line = line
    self
end

#do_range(start, stop, &blk) ⇒ Object

Execute given block between start and stop positions, and update position.



330
331
332
# File 'lib/patman.rb', line 330

def do_range( start, stop, &blk )
    do_for( start, (stop-start+1), &blk )
end

#editObject

Mark content modified (explicit).



279
280
281
# File 'lib/patman.rb', line 279

def edit
    @edited = true
end

#edited?Boolean

Return true if content is modified.

Returns:

  • (Boolean)


284
285
286
# File 'lib/patman.rb', line 284

def edited?
    @edited
end

#excursion(&blk) ⇒ Object

Execute block, retain current position, and return block value.



289
290
291
292
293
294
# File 'lib/patman.rb', line 289

def excursion( &blk )
    line = @line
    ret = instance_eval( &blk )
    @line = line
    ret
end

#filenameObject

Return Patman file name.



274
275
276
# File 'lib/patman.rb', line 274

def filename
    @file
end

#find(re_or_str, forward = true) ⇒ Object

Find Regexp or literal string forwards or backwards. Return true on success.



252
253
254
255
256
257
258
259
# File 'lib/patman.rb', line 252

def find( re_or_str, forward = true )
    begin
        @line = search_with_exception( re_or_str, forward )
        true
    rescue
        false
    end
end

#firstlineObject

Jump to first line.



111
112
113
114
# File 'lib/patman.rb', line 111

def firstline
    @line = 0
    self
end

#get(count = 1) ⇒ Object

Get current line or lines by count.



146
147
148
149
150
151
152
# File 'lib/patman.rb', line 146

def get( count = 1 )
    if count == 1
        @lines[ @line ]
    else
        @lines[ @line .. (@line+count-1) ]
    end
end

#get_for(start, count) ⇒ Object

Get lines starting from start by count.



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

def get_for( start, count )
    @lines[ (start-1) ... (start-1+count) ]
end

#get_range(start, stop) ⇒ Object

Get lines between start and stop positions inclusive.



349
350
351
# File 'lib/patman.rb', line 349

def get_range( start, stop )
    @lines[ (start-1) .. (stop-1) ]
end

#insert(text = nil) ⇒ Object

Insert line or lines (Array) to current position.



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

def insert( text = nil )
    @edited = true
    if text.kind_of? Array
        line = @line
        step( -1 )
        text.each do |txt|
            append( txt )
        end
        @line = line
    else
        @lines.insert( @line, text )
    end
    self
end

#insertfile(file) ⇒ Object

Insert file to current position.



233
234
235
236
237
238
239
240
# File 'lib/patman.rb', line 233

def insertfile( file )
    @edited = true
    step( -1 )
    read_clean( file ).each do |line|
        append line
    end
    self
end

#lastlineObject

Jump to last line.



117
118
119
120
# File 'lib/patman.rb', line 117

def lastline
    @line = @lines.length-1
    self
end

#lengthObject

Return line count of Patman content.



269
270
271
# File 'lib/patman.rb', line 269

def length
    @lines.length
end

#line(arg = nil) ⇒ Object

Return or set line.



95
96
97
98
99
100
101
102
# File 'lib/patman.rb', line 95

def line( arg = nil )
    if arg
        @line = (arg-1)
        self
    else
        @line+1
    end
end

#lines(arg = nil) ⇒ Object

Get or set all Patman content.



131
132
133
134
135
136
137
138
# File 'lib/patman.rb', line 131

def lines( arg = nil )
    if arg
        @edited = true
        @lines = arg
    else
        @lines
    end
end

#mark(tag = nil) ⇒ Object

Mark (store) current position to default or to named mark.



297
298
299
300
301
302
303
304
305
# File 'lib/patman.rb', line 297

def mark( tag = nil )
    if tag
        @marks[ tag ] = @line+1
        self
    else
        @mark = @line+1
        self
    end
end

#peek(count = 0) ⇒ Object

View line content around current position (by count).



359
360
361
362
# File 'lib/patman.rb', line 359

def peek( count = 0 )
    view_range( @line-count, @line+count+1 )
    nil
end

#peek_ln(count = 0) ⇒ Object

View line content with line numbers around current position (by count).



366
367
368
369
# File 'lib/patman.rb', line 366

def peek_ln( count = 0 )
    view_range( @line-count, @line+count+1, true )
    nil
end

#read(file = @file) ⇒ Object

Read file in.



56
57
58
59
60
61
62
# File 'lib/patman.rb', line 56

def read( file = @file )
    if File.exist?( file )
        @lines = read_clean( file )
    else
        raise PatmanFileError
    end
end

#ref(line = nil) ⇒ Object

Get current line or any line.



155
156
157
158
159
160
161
# File 'lib/patman.rb', line 155

def ref( line = nil )
    if line
        @lines[ line-1 ]
    else
        @lines[ @line ]
    end
end

#search(re_or_str, forward = true) ⇒ Object

Search Regexp or literal string forwards or backwards. Fail with expection (PatmanSearchError) if not found.



263
264
265
266
# File 'lib/patman.rb', line 263

def search( re_or_str, forward = true )
    @line = search_with_exception( re_or_str, forward )
    self
end

#set(text) ⇒ Object

Set current line.



164
165
166
167
168
# File 'lib/patman.rb', line 164

def set( text )
    @edited = true
    @lines[ @line ] = text
    self
end

#step(dir = 1) ⇒ Object

Step forward or backward current position.



105
106
107
108
# File 'lib/patman.rb', line 105

def step( dir = 1 )
    @line = @line + dir
    self
end

#sub(from, to) ⇒ Object

Substitution in current line.



171
172
173
174
175
# File 'lib/patman.rb', line 171

def sub( from, to )
    @edited = true
    @lines[ @line ] = @lines[ @line ].sub( from, to )
    self
end

#unmark(tag = nil) ⇒ Object

Unmark (restore) current position from default or from named mark.



309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/patman.rb', line 309

def unmark( tag = nil )
    if tag && @marks[ tag ]
        @line = @marks[ tag ]-1
        self
    elsif @mark
        @line = @mark-1
        @mark = nil
        self
    else
        self
    end
end

#update(&blk) ⇒ Object

Update current line content (i.e. get&set) with the return value of the given block. Hence last stmt should include the new line content.

Examples:

r.update do |c|
   c.sub!( /foo/, 'bar' )
   c
end


187
188
189
190
191
# File 'lib/patman.rb', line 187

def update( &blk )
    @edited = true
    set( yield( get ) )
    self
end

#view(arg1 = nil, arg2 = nil) ⇒ Object

View line content.

  • no args: view all

  • one arg: view from current onwards by count

  • two args: view given range



376
377
378
379
380
381
382
383
384
385
# File 'lib/patman.rb', line 376

def view( arg1 = nil, arg2 = nil )
    if !arg1 && !arg2
        view_range( 0, length )
    elsif arg1 && !arg2
        view_range( @line, @line+arg1 )
    elsif arg1 && arg2
        view_range( arg1-1, arg1-1+arg2 )
    end
    nil
end

#view_ln(arg1 = nil, arg2 = nil) ⇒ Object

View line content with line numbers.

  • no args: view all

  • one arg: view from current onwards by count

  • two args: view given range



392
393
394
395
396
397
398
399
400
401
# File 'lib/patman.rb', line 392

def view_ln( arg1 = nil, arg2 = nil )
    if !arg1 && !arg2
        view_range( 0, length, true )
    elsif arg1 && !arg2
        view_range( @line, @line+arg1, true )
    elsif arg1 && arg2
        view_range( arg1-1, arg1-1+arg2, true )
    end
    nil
end

#write(file = @file) ⇒ Object

Write Patman content to disk.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/patman.rb', line 65

def write( file = @file )
    return unless @edited

    file_dir = File.dirname( file )
    unless File.exist?( file_dir )
        require 'fileutils'
        FileUtils.mkdir_p( file_dir )
    end

    fh = File.open( file, 'w' )

    @lines.each do |line|
        if line
            fh.puts line
        else
            fh.puts ""
        end
    end
    fh.close
    @edited = false
    self
end