2 # -*- coding: utf-8 -*-
4 # Copyright (C) 2001-7 Iñigo Serna
5 # Time-stamp: <2007-09-03 23:18:41 inigo>
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 Copyright (C) 2001-7, Iñigo Serna <inigoserna@telefonica.net>.
25 This software has been realised under the GPL License, see the COPYING
26 file that comes with this package. There is NO WARRANTY.
28 'pyview' is a simple pager (viewer) to be used with Last File Manager.
38 import curses
, curses
.ascii
40 from __init__
import *
44 ########################################################################
45 ##### module variables
47 LOG_FILE
= os
.path
.join(os
.getcwd(), 'pyview.log')
50 ########################################################################
53 """Read from stdin with 1 sec. timeout. Returns text"""
55 from select
import select
58 fd
= select([sys
.stdin
], [], [], 0.5)[0][0]
59 stdin
= ''.join(fd
.readlines())
60 # close stdin (pipe) and open terminal for reading
62 sys
.stdin
= open(os
.ttyname(1), 'r')
68 def create_temp_for_stdin(buf
):
69 """Copy stdin in a temporary file. Returns file name"""
71 from tempfile
import mkstemp
73 filename
= mkstemp()[1]
74 f
= open(filename
, 'w')
80 ##################################################
82 ##################################################
84 """Internal View class"""
86 def __init__(self
, title
, buf
, center
= 1):
88 self
.__validate
_buf
(buf
, center
)
92 def __validate_buf(self
, buf
, center
):
93 buf
= [(l
[0][:app
.maxw
-2], l
[1] ) for l
in buf
]
94 buf2
= [l
[0] for l
in buf
]
95 self
.nlines
= len(buf2
)
96 if self
.nlines
> app
.maxh
- 2:
101 self
.y0
= int(((app
.maxh
-2) - self
.nlines
)/2)
104 col_max
= max(map(len, buf2
))
105 self
.x0
= int((app
.maxw
-col_max
)/2)
108 self
.y0
= not self
.large
112 def init_curses(self
):
117 self
.win_title
= curses
.newwin(1, 0, 0, 0)
118 self
.win_body
= curses
.newwin(app
.maxh
-2, 0, 1, 0) # h, w, y, x
119 self
.win_status
= curses
.newwin(1, 0, app
.maxh
-1, 0)
121 print 'Can\'t create windows'
124 if curses
.has_colors():
125 self
.win_title
.bkgd(curses
.color_pair(1),
126 curses
.color_pair(1) | curses
.A_BOLD
)
127 self
.win_body
.bkgd(curses
.color_pair(2))
128 self
.win_status
.bkgd(curses
.color_pair(1))
129 self
.win_body
.keypad(1)
131 self
.win_title
.erase()
132 self
.win_status
.erase()
134 if len(title
) - 4 > app
.maxw
:
135 title
= title
[:app
.maxw
-12] + '~' + title
[-7:]
136 self
.win_title
.addstr(0, int((app
.maxw
-len(title
))/2), title
)
140 status
= 'Press a key to continue'
141 self
.win_status
.addstr(0, int((app
.maxw
-len(status
))/2), status
)
143 self
.win_title
.refresh()
144 self
.win_status
.refresh()
148 """show title, file and status bar"""
150 self
.win_body
.erase()
152 buf
= self
.buf
[self
.y
:self
.y
+app
.maxh
-2]
155 for i
, (l
, c
) in enumerate(buf
):
156 self
.win_body
.addstr(self
.y0
+i
, self
.x0
, l
, curses
.color_pair(c
))
157 self
.win_body
.refresh()
166 ch
= self
.win_body
.getch()
167 if ch
in (ord('k'), ord('K'), curses
.KEY_UP
):
168 self
.y
= max(self
.y
-1, 0)
169 if ch
in (ord('j'), ord('J'), curses
.KEY_DOWN
):
170 self
. y
= min(self
.y
+1, self
.nlines
-1)
171 elif ch
in (curses
.KEY_HOME
, 0x01):
173 elif ch
in (curses
.KEY_END
, 0x05):
174 self
.y
= self
.nlines
- 1
175 elif ch
in (curses
.KEY_PPAGE
, 0x08, 0x02, curses
.KEY_BACKSPACE
):
176 self
.y
= max(self
.y
-app
.maxh
-2, 0)
177 elif ch
in (curses
.KEY_NPAGE
, ord(' '), 0x06):
178 self
. y
= min(self
.y
+app
.maxh
-2, self
.nlines
-1)
179 elif ch
in (0x1B, ord('q'), ord('Q'), ord('x'), ord('X'),
180 curses
.KEY_F3
, curses
.KEY_F10
):
183 while not self
.win_body
.getch():
187 ##################################################
189 ##################################################
191 """Main application class"""
193 def __init__(self
, win
, filename
, line
, mode
, stdin_flag
):
196 self
.win
= win
# root window, need for resizing
200 self
.stdin_flag
= stdin_flag
202 self
.pos
, self
.col
= 0, 0
205 self
.__get
_file
_info
(filename
)
206 except (IOError, os
.error
), (errno
, strerror
):
207 messages
.error('%s' % PYVIEW_NAME
,
208 '%s (%s)' % (strerror
, errno
), filename
)
211 messages
.error('View \'%s\'' % filename
, 'File is empty')
213 self
.fd
= open(filename
)
216 if mode
== MODE_TEXT
:
217 self
.__move
_lines
((line
or 1) - 1)
219 self
.pos
= min(line
, self
.nbytes
)
225 self
.bookmarks
= [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
228 def __get_file_info(self
, filename
):
229 """get size and number of lines of the file"""
231 self
.nbytes
= os
.path
.getsize(filename
)
232 self
.lines_pos
= [0L]
236 for nlines
, l
in enumerate(f
.readlines()):
238 self
.lines_pos
.append(pos
)
240 self
.nlines
= nlines
+ 1
243 def init_curses(self
):
244 """initialize curses stuff: windows, colors, ..."""
246 self
.maxh
, self
.maxw
= self
.win
.getmaxyx()
251 self
.win_title
= curses
.newwin(1, 0, 0, 0)
252 self
.win_file
= curses
.newwin(self
.maxh
-2, 0, 1, 0) # h, w, y, x
253 self
.win_status
= curses
.newwin(1, 0, self
.maxh
-1, 0)
255 print 'Can\'t create windows'
259 if curses
.has_colors():
260 curses
.init_pair(1, curses
.COLOR_YELLOW
, curses
.COLOR_BLUE
) # title
261 curses
.init_pair(2, curses
.COLOR_WHITE
, curses
.COLOR_BLACK
) # files
262 curses
.init_pair(3, curses
.COLOR_BLUE
, curses
.COLOR_CYAN
) # current file
263 curses
.init_pair(4, curses
.COLOR_MAGENTA
, curses
.COLOR_CYAN
) # messages
264 curses
.init_pair(5, curses
.COLOR_GREEN
, curses
.COLOR_BLACK
) # help
265 curses
.init_pair(6, curses
.COLOR_RED
, curses
.COLOR_BLACK
) # file info
266 curses
.init_pair(7, curses
.COLOR_WHITE
, curses
.COLOR_RED
) # error messages
267 curses
.init_pair(8, curses
.COLOR_BLACK
, curses
.COLOR_RED
) # error messages
268 curses
.init_pair(9, curses
.COLOR_YELLOW
, curses
.COLOR_RED
) # button in dialog
269 curses
.init_pair(10, curses
.COLOR_YELLOW
, curses
.COLOR_BLACK
) # file selected
270 curses
.init_pair(11, curses
.COLOR_YELLOW
, curses
.COLOR_CYAN
) # file selected and current
271 self
.win_title
.bkgd(curses
.color_pair(1),
272 curses
.color_pair(1) | curses
.A_BOLD
)
273 self
.win_file
.bkgdset(curses
.color_pair(2))
274 self
.win_status
.bkgdset(curses
.color_pair(1))
275 self
.win_file
.keypad(1)
278 def resize_window(self
):
279 h
, w
= self
.win
.getmaxyx()
280 self
.maxh
, self
.maxw
= h
, w
283 self
.win
.resize(h
, w
)
284 self
.win_title
.resize(1, w
)
285 self
.win_file
.resize(h
-2, w
)
286 self
.win_status
.resize(1, w
)
287 self
.win_status
.mvwin(h
-1, 0)
291 def __move_lines(self
, lines
):
293 self
.line
= min(self
.line
+lines
, self
.nlines
-1)
294 # # Code that don't show blank lines when in last lines of file
296 # if self.line + lines > self.nlines - 1 - (curses.LINES-2):
297 # # get last (curses.LINES -2 ) lines
298 # pos = self.lines_pos[self.nlines - 1 - (curses.LINES-2)]
301 # for i in xrange(curses.LINES-2):
302 # l = self.fd.readline().rstrip().replace('\t', ' ' * 4)
305 # # calculate lines that fit in screen
308 # while lno < curses.LINES-2:
309 # lno += int(len(lines[i])/curses.COLS) + 1
311 # # calculate horizontal scrolling if needed
312 # self.col = curses.COLS * (lno - (curses.LINES-2))
313 # self.line = self.nlines - 1 - i
317 # if self.line + lines > self.nlines - 1 - (curses.LINES-2):
318 # self.line = self.nlines - 1 - (curses.LINES-2)
322 self
.line
= max(0, self
.line
+lines
)
323 self
.pos
= self
.lines_pos
[self
.line
]
324 self
.fd
.seek(self
.lines_pos
[self
.line
], 0)
327 def __get_lines_text(self
):
329 for i
in xrange(self
.maxh
-2):
330 l
= self
.fd
.readline().rstrip().replace('\t', ' ' * 4)
332 self
.fd
.seek(self
.pos
)
333 self
.col_max
= max(map(len, lines
))
337 def __get_prev_lines_text(self
):
340 for i
in xrange(self
.maxh
-2):
341 line_i
= self
.line
- 1 - i
344 self
.fd
.seek(self
.lines_pos
[line_i
])
345 lines
.append(self
.fd
.readline().rstrip().replace('\t', ' ' * 4))
346 self
.fd
.seek(self
.pos
)
350 def __get_line_length(self
):
351 return len(self
.__get
_1line
())
354 def __get_1line(self
):
355 line
= self
.fd
.readline().rstrip().replace('\t', ' ' * 4)
356 self
.fd
.seek(self
.pos
)
360 def show_chr(self
, w
, c
):
361 if curses
.ascii
.iscntrl(c
) or ord(c
) in xrange(0x7F, 0xA0):
363 elif curses
.ascii
.isascii(c
):
364 w
.addch(curses
.ascii
.ascii(c
))
365 elif curses
.ascii
.ismeta(c
):
371 def show_str(self
, w
, line
):
372 for i
in xrange(len(line
)):
374 if ord(c
) == ord('\r'):
379 def show_text_nowrap(self
):
380 lines
= self
.__get
_lines
_text
()
381 self
.win_file
.refresh()
382 for y
, l
in enumerate(lines
):
383 lwin
= curses
.newpad(1, self
.maxw
+1)
385 if len(l
) - self
.col
> self
.maxw
:
389 buf
= l
[self
.col
:self
.col
+self
.maxw
]
390 self
.show_str(lwin
, buf
)
391 lwin
.refresh(0, 0, y
+1, 0, y
+1, self
.maxw
-1)
393 lwin2
= curses
.newpad(1, 2)
395 lwin2
.addch('>', curses
.color_pair(2) | curses
.A_BOLD
)
396 lwin2
.refresh(0, 0, y
+1, self
.maxw
-1, y
+1, self
.maxw
-1)
399 self
.win_file
.refresh()
402 def show_text_wrap(self
):
403 lines
= self
.__get
_lines
_text
()
404 lines
[0] = lines
[0][self
.col
:] # show remaining chars of 1st line
405 self
.win_file
.refresh()
408 if y
> self
.maxh
- 2:
410 if len(l
) <= self
.maxw
:
411 lwin
= curses
.newpad(1, self
.maxw
+1)
413 self
.show_str(lwin
, l
)
414 lwin
.refresh(0, 0, y
+1, 0, y
+1, self
.maxw
-1)
419 lwin
= curses
.newpad(1, self
.maxw
+1)
421 self
.show_str(lwin
, l
[:self
.maxw
])
422 lwin
.refresh(0, 0, y
+1, 0, y
+1, self
.maxw
-1)
425 if y
> self
.maxh
- 2:
428 self
.win_file
.refresh()
431 def __move_hex(self
, lines
):
432 self
.pos
= self
.pos
& 0xFFFFFFF0L
434 self
.pos
= min(self
.pos
+lines
*16, self
.nbytes
-1)
436 self
.pos
= max(0, self
.pos
+lines
*16)
437 self
.fd
.seek(self
.pos
, 0)
438 for i
in xrange(len(self
.lines_pos
)):
439 ls
= self
.lines_pos
[i
]
441 self
.line
= max(0, i
-1)
447 def __get_lines_hex(self
, chars_per_line
=16):
449 lines
= self
.fd
.read(chars_per_line
* (self
.maxh
-2))
451 if le
!= chars_per_line
* (self
.maxh
-2):
452 for i
in xrange(chars_per_line
* (self
.maxh
-2) - le
):
454 self
.fd
.seek(self
.pos
)
461 elif self
.maxw
>= 134:
463 elif self
.maxw
>= 116:
465 elif self
.maxw
>= 98:
467 elif self
.maxw
>= 80:
469 elif self
.maxw
>= 62:
471 elif self
.maxw
>= 44:
473 elif self
.maxw
>= 26:
477 lines
= self
.__get
_lines
_hex
(chars_per_line
)
478 self
.win_file
.erase()
479 self
.win_file
.refresh()
480 for y
in xrange(self
.maxh
-2):
481 lwin
= curses
.newpad(1, self
.maxw
+1)
483 attr
= curses
.color_pair(2) | curses
.A_BOLD
484 lwin
.addstr(0, 0, '%8.8X ' % (self
.pos
+chars_per_line
*y
), attr
)
485 for i
in xrange(chars_per_line
/4):
486 buf
= ''.join(['%2.2X ' % (ord(lines
[y
*chars_per_line
+4*i
+j
]) & 0xFF) \
489 if i
!= chars_per_line
/4 - 1:
490 lwin
.addch(curses
.ACS_VLINE
)
492 for i
in xrange(chars_per_line
):
493 c
= lines
[y
*chars_per_line
+i
]
494 self
.show_chr(lwin
, c
)
495 lwin
.refresh(0, 0, y
+1, 0, y
+1, self
.maxw
-1)
496 self
.win_file
.refresh()
499 def show_title(self
):
504 title
= os
.path
.basename(self
.file)
505 if len(title
) > self
.maxw
-52:
506 title
= title
[:self
.maxw
-58] + '~' + title
[-5:]
507 self
.win_title
.addstr('File: %s' % title
)
509 if self
.col
!= 0 or self
.wrap
:
510 self
.win_title
.addstr(0, int(self
.maxw
/2)-14, 'Col: %d' % self
.col
)
511 buf
= 'Bytes: %d/%d' % (self
.pos
, self
.nbytes
)
512 self
.win_title
.addstr(0, int(self
.maxw
/2)-5, buf
)
513 buf
= 'Lines: %d/%d' % (self
.line
+1, self
.nlines
)
514 self
.win_title
.addstr(0, int(self
.maxw
*3/4)-4, buf
)
516 self
.win_title
.addstr(0, self
.maxw
-5,
517 '%3d%%' % (int(self
.pos
*100/self
.nbytes
)))
520 def show_status(self
):
525 path
= os
.path
.dirname(self
.file)
526 if not path
or path
[0] != os
.sep
:
527 path
= os
.path
.join(os
.getcwd(), path
)
528 if len(path
) > self
.maxw
- 37:
529 path
= '~' + path
[-(self
.maxw
-38):]
530 self
.win_status
.addstr('Path: %s' % path
)
532 if self
.mode
== MODE_TEXT
:
536 self
.win_status
.addstr(0, self
.maxw
-30, 'View mode: %s' % mode
)
541 if self
.mode
== MODE_TEXT
:
542 self
.win_status
.addstr(0, self
.maxw
-10, 'Wrap: %s' % wrap
)
546 """show title, file and status bar"""
548 self
.win_title
.erase()
549 self
.win_file
.erase()
550 self
.win_status
.erase()
558 if self
.mode
== MODE_TEXT
:
560 self
.show_text_wrap()
562 self
.show_text_nowrap()
568 self
.win_title
.refresh()
569 self
.win_file
.refresh()
570 self
.win_status
.refresh()
573 def __find(self
, title
):
574 self
.pattern
= messages
.Entry(title
, 'Type search string', '', 1, 0).run()
575 if self
.pattern
== None or self
.pattern
== '':
578 filename
= os
.path
.abspath(self
.file)
579 mode
= (self
.mode
== MODE_TEXT
) and 'n' or 'b'
581 i
, o
, e
= os
.popen3('%s -i%c \"%s\" \"%s\"' % \
582 (sysprogs
['grep'], mode
, self
.pattern
,
586 err
= e
.read().strip()
590 messages
.error('Find Error', 'Can\'t popen file')
594 messages
.error('Find Error', err
)
600 self
.matches
= [int(l
.split(':')[0]) for l
in buf
.split('\n') if l
]
601 except (ValueError, TypeError):
606 def __find_next(self
):
607 pos
= (self
.mode
== MODE_TEXT
) and self
.line
or self
.pos
+16
608 for next
in self
.matches
:
615 messages
.error('Find', 'No more matches <%s>' % self
.pattern
)
618 if self
.mode
== MODE_TEXT
:
627 def __find_previous(self
):
628 pos
= (self
.mode
== MODE_TEXT
) and self
.line
or self
.pos
629 rev_matches
= [l
for l
in self
.matches
]
630 rev_matches
.reverse()
631 for prev
in rev_matches
:
638 messages
.error('Find',
639 'No more matches <%s>' % self
.pattern
)
642 if self
.mode
== MODE_TEXT
:
652 """run application, manage keys, etc"""
656 ch
= self
.win_file
.getch()
659 if ch
in (ord('k'), ord('K'), curses
.KEY_UP
):
660 if self
.mode
== MODE_TEXT
:
662 if self
.col
== 0 and self
.line
> 0:
663 self
.__move
_lines
(-1)
664 self
.col
= int(self
.__get
_line
_length
()/self
.maxw
)*self
.maxw
666 self
.col
-= self
.maxw
668 self
.__move
_lines
(-1)
673 elif ch
in (ord('j'), ord('J'), curses
.KEY_DOWN
):
674 if self
.mode
== MODE_TEXT
:
676 if self
.line
>= self
.nlines
- 1 and \
677 self
.__get
_line
_length
() < self
.maxw
*(self
.maxh
-2):
680 self
.col
+= self
.maxw
681 if self
.col
>= self
.__get
_line
_length
():
690 elif ch
in (curses
.KEY_PPAGE
, curses
.KEY_BACKSPACE
,
691 0x08, 0x02): # BackSpace, Ctrl-
692 if self
.mode
== MODE_TEXT
:
694 lines
= self
.__get
_prev
_lines
_text
()
695 if self
.col
: # if we aren't at 1st char of line
696 line0
= self
.__get
_1line
()[:self
.col
]
697 lines
.insert(0, line0
)
702 for i
, l
in enumerate(lines
):
707 while len2
> self
.maxw
:
711 dy
= int(lenz
/self
.maxw
) + 1 - dy
722 self
.__move
_lines
(-i
)
724 self
.col
= (dy
-1) * self
.maxw
726 self
.col
= dy
* self
.maxw
728 self
.__move
_lines
(-(self
.maxh
-2))
731 self
.__move
_lines
(-(self
.maxh
-2))
733 self
.__move
_hex
(-(self
.maxh
-2))
736 elif ch
in (curses
.KEY_NPAGE
, ord(' '), 0x06): # Ctrl-F
737 if self
.mode
== MODE_TEXT
:
739 lines
= self
.__get
_lines
_text
()
740 lines
[0] = lines
[0][self
.col
:]
743 for i
, l
in enumerate(lines
):
745 if y
> self
.maxh
- 2:
748 while len2
> self
.maxw
:
750 if y
> self
.maxh
- 2:
760 self
.col
+= dy
* self
.maxw
762 self
.col
= dy
* self
.maxw
764 self
.__move
_lines
(self
.maxh
-2)
766 self
.__move
_hex
(self
.maxh
-2)
769 elif ch
in (curses
.KEY_HOME
, 0x01): # home
770 if self
.mode
== MODE_TEXT
:
771 self
.__move
_lines
(-self
.nlines
)
773 self
.__move
_hex
(-self
.nbytes
)
777 elif ch
in (curses
.KEY_END
, 0x05): # end
778 if self
.mode
== MODE_TEXT
:
779 self
.__move
_lines
(self
.nlines
)
781 self
.__move
_hex
(self
.nbytes
)
786 elif ch
== curses
.KEY_LEFT
:
787 if self
.mode
== MODE_HEX
or self
.wrap
:
793 elif ch
== curses
.KEY_RIGHT
:
794 if self
.mode
== MODE_HEX
or self
.wrap
:
796 if self
.col
+self
.maxw
< self
.col_max
+ 2:
801 elif ch
in (ord('w'), ord('W'), curses
.KEY_F2
):
802 if self
.mode
== MODE_HEX
:
804 self
. wrap
= not self
.wrap
809 # text / hexadecimal mode
810 elif ch
in (ord('m'), ord('M'), curses
.KEY_F4
):
811 if self
.mode
== MODE_TEXT
:
815 self
.mode
= MODE_TEXT
820 elif ch
in (ord('g'), ord('G'), curses
.KEY_F5
):
822 if self
.mode
== MODE_TEXT
:
824 help = 'Type line number'
827 help = 'Type byte offset'
828 n
= messages
.Entry(title
, help, '', 1, 0).run()
829 if n
== None or n
== '':
832 if n
[0] in ('+', '-'):
835 if n
[rel
:rel
+2] == '0x':
837 n
= long(n
[0] + str(int(n
[1:], 16)))
844 if self
.mode
== MODE_TEXT
:
848 messages
.error('Goto %s' % mode
,
849 'Invalid byte number <%s>' % n
)
855 if self
.mode
== MODE_TEXT
:
860 self
.line
= min(self
.line
, self
.nlines
-1)
867 self
.pos
= min(self
.pos
, self
.nbytes
)
873 if self
.__find
('Find') == -1:
877 elif ch
== curses
.KEY_F6
:
879 if self
.__find
('Find Previous') == -1:
881 self
.__find
_previous
()
883 elif ch
== curses
.KEY_F7
:
885 if self
.__find
('Find Next') == -1:
890 elif 0x30 <= ch
<= 0x39:
891 bk
= self
.bookmarks
[ch
-0x30]
898 elif ch
in (ord('b'), ord('B')):
900 ch
= messages
.get_a_key('Set bookmark',
901 'Press 0-9 to save bookmark, Ctrl-C to quit')
902 if 0x30 <= ch
<= 0x39:
903 self
.bookmarks
[ch
-0x30] = self
.line
910 elif ch
== 0x0F: # Ctrl-O
915 os
.system('cd \"%s\"; sh' % os
.path
.dirname(self
.file))
920 elif ch
in (ord('h'), ord('H'), curses
.KEY_F1
):
922 buf
.append(('%s v%s (C) %s, by %s' % \
923 (PYVIEW_NAME
, VERSION
, DATE
, AUTHOR
), 5))
924 text
= PYVIEW_README
.split('\n')
927 InternalView('Help for %s' % PYVIEW_NAME
, buf
).run()
931 elif ch
== curses
.KEY_RESIZE
:
935 elif ch
in (0x1B, 0x11, ord('q'), ord('Q'), ord('x'), ord('X'), # Ctrl-Q
936 curses
.KEY_F3
, curses
.KEY_F10
):
941 ##################################################
943 ##################################################
944 def usage(prog
, msg
= ""):
945 prog
= os
.path
.basename(prog
)
947 print '%s:\t%s\n' % (prog
, msg
)
949 %s v%s - (C) %s, by %s
951 A simple pager (viewer) to be used with Last File Manager.
952 Released under GNU Public License, read COPYING for more details.
954 Usage:\t%s\t[-h | --help]
956 \t\t[-m text|hex | --mode=text|hex]
960 -m, --mode\t\tstart in text or hexadecimal mode
961 -d, --debug\t\tcreate debug file
962 -h, --help\t\tshow help
963 +n\t\t\tstart at line (text mode) or byte (hex mode),
964 \t\t\tif n starts with '0x' is considered hexadecimal
965 pathtofile\t\tfile to view
966 """ % (PYVIEW_NAME
, VERSION
, DATE
, AUTHOR
, prog
)
969 def main(win
, filename
, line
, mode
, stdin_flag
):
970 app
= FileView(win
, filename
, line
, mode
, stdin_flag
)
985 opts
, args
= getopt
.getopt(sysargs
[1:], 'dhm:',
986 ['debug', 'help', 'mode='])
987 except getopt
.GetoptError
:
988 usage(sysargs
[0], 'Bad argument(s)')
991 if o
in ('-d', '--debug'):
993 elif o
in ('-h', '--help'):
996 elif o
in ('-m', '--mode'):
1002 usage(sysargs
[0], '<%s> is not a valid mode' % a
)
1005 stdin
= read_stdin()
1012 usage(sysargs
[0], 'Incorrect number of arguments')
1020 if line
[:2] == '0x':
1021 line
= int(line
, 16)
1025 usage(sysargs
[0], '<%s> is not a valid line number' % line
)
1031 if filename
== '' and not stdin_flag
:
1032 usage(sysargs
[0], 'File is missing')
1035 filename
= create_temp_for_stdin(stdin
)
1037 if not os
.path
.isfile(filename
):
1038 usage(sysargs
[0], '<%s> is not a valid file' % file)
1043 log_file
= os
.path
.join(os
.path
.abspath('.'), LOG_FILE
)
1044 logging
.basicConfig(level
=logging
.DEBUG
,
1045 format
='%(asctime)s %(levelname)s\t%(message)s',
1046 datefmt
='%Y-%m-%d %H:%M:%S ',
1049 logging
.info('Starting PyView...')
1052 logging
.info('Main application call')
1053 curses
.wrapper(main
, filename
, line
, mode
, stdin_flag
)
1060 if __name__
== '__main__':