diff options
author | hut <hut@lepus.uberspace.de> | 2014-12-05 01:46:11 +0100 |
---|---|---|
committer | hut <hut@lepus.uberspace.de> | 2014-12-05 01:46:11 +0100 |
commit | 807402c260afede5822c6c5edcf6b9f40d11ef86 (patch) | |
tree | f4b372a378007f46a6a94598395c70b87dbc4741 | |
parent | 5c97716aa0e260ec2b0cd6cffee1ea74fd9ff8f8 (diff) | |
parent | 8e0e465774d541181f27cd9e92a79ed01c84d115 (diff) | |
download | ranger-807402c260afede5822c6c5edcf6b9f40d11ef86.tar.gz |
Merge branch 'linemode'
-rw-r--r-- | doc/ranger.1 | 61 | ||||
-rw-r--r-- | doc/ranger.pod | 66 | ||||
-rw-r--r-- | ranger/config/commands.py | 122 | ||||
-rw-r--r-- | ranger/config/rc.conf | 10 | ||||
-rw-r--r-- | ranger/container/directory.py | 4 | ||||
-rw-r--r-- | ranger/container/file.py | 2 | ||||
-rw-r--r-- | ranger/container/fsobject.py | 38 | ||||
-rw-r--r-- | ranger/container/settings.py | 1 | ||||
-rw-r--r-- | ranger/core/actions.py | 47 | ||||
-rw-r--r-- | ranger/core/fm.py | 6 | ||||
-rw-r--r-- | ranger/ext/papermanager.py | 171 | ||||
-rw-r--r-- | ranger/gui/widgets/browsercolumn.py | 46 |
12 files changed, 566 insertions, 8 deletions
diff --git a/doc/ranger.1 b/doc/ranger.1 index 9aa4e318..27de2aa9 100644 --- a/doc/ranger.1 +++ b/doc/ranger.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RANGER 1" -.TH RANGER 1 "ranger-1.6.1" "10/31/2014" "ranger manual" +.TH RANGER 1 "ranger-1.6.1" "12/05/2014" "ranger manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -539,6 +539,11 @@ Go to the next or previous tab. You can also use \s-1TAB\s0 and \s-1SHIFT+TAB\s0 .IP "gc, ^W" 14 .IX Item "gc, ^W" Close the current tab. The last tab cannot be closed this way. +.IP "M" 14 +.IX Item "M" +A key chain that allows you to quickly change the line mode of all the files of +the current directory. For a more permanent solution, use the command +\&\*(L"default_linemode\*(R" in your rc.conf. .SS "READLINE-LIKE \s-1BINDINGS IN THE CONSOLE\s0" .IX Subsection "READLINE-LIKE BINDINGS IN THE CONSOLE" .IP "^B, ^F" 14 @@ -684,6 +689,11 @@ How many directory changes should be kept in history? .IP "mouse_enabled [bool] <zm>" 4 .IX Item "mouse_enabled [bool] <zm>" Enable mouse input? +.IP "papermanager_deep_search [bool]" 4 +.IX Item "papermanager_deep_search [bool]" +When the paper manager module looks for metadata, should it only look for a +\&\*(L".paperinfo\*(R" file in the current directory, or do a deep search and check all +directories above the current one as well? .IP "padding_right [bool]" 4 .IX Item "padding_right [bool]" When collapse_preview is on and there is no preview, should there remain a @@ -798,18 +808,25 @@ ranger. For your convenience, this is a list of the \*(L"public\*(R" commands i \& copypmap key newkey [newkey2...] \& copytmap key newkey [newkey2...] \& cunmap keys... +\& default_linemode [path=regexp | tag=tags] linemodename \& delete \& edit [filename] \& eval [\-q] python_code \& filter [string] \& find pattern \& grep pattern +\& linemode linemodename \& load_copy_buffer \& map key command \& mark pattern \& mark_tag [tags] \& mkdir dirname \& open_with [application] [flags] [mode] +\& paper +\& paper_authors [authors] +\& paper_title [title] +\& paper_url [url] +\& paper_year [year] \& pmap key command \& punmap keys... \& quit @@ -898,6 +915,20 @@ See \f(CW\*(C`copymap\*(C'\fR .IP "cunmap [\fIkeys...\fR]" 2 .IX Item "cunmap [keys...]" Removes key mappings of the console. Works like the \f(CW\*(C`unmap\*(C'\fR command. +.IP "default_linemode [\fIpath=regexp\fR | \fItag=tags\fR] \fIlinemodename\fR" 2 +.IX Item "default_linemode [path=regexp | tag=tags] linemodename" +Sets the default linemode. See \fIlinemode\fR command. +.Sp +Examples: +.Sp +Set the global default linemode to \*(L"permissions\*(R": + :default_linemode permissions +.Sp +Set the default linemode to \*(L"permissions\*(R" for all files tagged with \*(L"p\*(R" or \*(L"P\*(R": + :default_linemode tag=pP permissions +.Sp +Set the default linemode for all files in ~/books/ to \*(L"papertitle\*(R": + :default_linemode path=/home/.*?/books/.* papertitle .IP "delete" 2 .IX Item "delete" Destroy all files in the selection with a roundhouse kick. ranger will ask for @@ -932,6 +963,16 @@ This command is based on the \fIscout\fR command and supports all of its options .IP "grep \fIpattern\fR" 2 .IX Item "grep pattern" Looks for a string in all marked files or directories. +.IP "linemode \fIlinemodename\fR" 2 +.IX Item "linemode linemodename" +Sets the linemode of all files in the current directory. The linemode may be: +.Sp +.Vb 4 +\& "filename": display each line as "<basename>...<size>" +\& "permissions": display each line as "<permissions> <owner> <group> <basename>" +\& "papertitle": display metadata from .paperinfo files if available, fall back +\& to the "filename" linemode if no metadata was found. See :paper commands. +.Ve .IP "load_copy_buffer" 2 .IX Item "load_copy_buffer" Load the copy buffer from \fI~/.config/ranger/copy_buffer\fR. This can be used to @@ -968,6 +1009,24 @@ of applications is generated by the external file opener \*(L"rifle\*(R" and can displayed when pressing \*(L"r\*(R" in ranger. .Sp Note that if you specify an application, the mode is ignored. +.IP "paper" 2 +.IX Item "paper" +This command opens a series of commands on the console that will ask the user +to input metadata about the current file. This is used by the paper manager +module of ranger and can be later displayed in ranger, for example by setting +the option \*(L"linemode\*(R" to \*(L"papertitle\*(R". +.IP "paper_authors \fIauthors\fR" 2 +.IX Item "paper_authors authors" +Tells the paper manager to set/update the authors of the current file +.IP "paper_title \fItitle\fR" 2 +.IX Item "paper_title title" +Tells the paper manager to set/update the title of the current file +.IP "paper_url \fIurl\fR" 2 +.IX Item "paper_url url" +Tells the paper manager to set/update the url of the current file +.IP "paper_year \fIyear\fR" 2 +.IX Item "paper_year year" +Tells the paper manager to set/update the year of the current file .IP "pmap \fIkey\fR \fIcommand\fR" 2 .IX Item "pmap key command" Binds keys for the pager. Works like the \f(CW\*(C`map\*(C'\fR command. diff --git a/doc/ranger.pod b/doc/ranger.pod index 370bbb85..7a6de447 100644 --- a/doc/ranger.pod +++ b/doc/ranger.pod @@ -490,6 +490,12 @@ Go to the next or previous tab. You can also use TAB and SHIFT+TAB instead. Close the current tab. The last tab cannot be closed this way. +=item M + +A key chain that allows you to quickly change the line mode of all the files of +the current directory. For a more permanent solution, use the command +"default_linemode" in your rc.conf. + =back =head2 READLINE-LIKE BINDINGS IN THE CONSOLE @@ -674,6 +680,12 @@ How many directory changes should be kept in history? Enable mouse input? +=item papermanager_deep_search [bool] + +When the paper manager module looks for metadata, should it only look for a +".paperinfo" file in the current directory, or do a deep search and check all +directories above the current one as well? + =item padding_right [bool] When collapse_preview is on and there is no preview, should there remain a @@ -813,18 +825,25 @@ ranger. For your convenience, this is a list of the "public" commands including copypmap key newkey [newkey2...] copytmap key newkey [newkey2...] cunmap keys... + default_linemode [path=regexp | tag=tags] linemodename delete edit [filename] eval [-q] python_code filter [string] find pattern grep pattern + linemode linemodename load_copy_buffer map key command mark pattern mark_tag [tags] mkdir dirname open_with [application] [flags] [mode] + paper + paper_authors [authors] + paper_title [title] + paper_url [url] + paper_year [year] pmap key command punmap keys... quit @@ -927,6 +946,21 @@ See C<copymap> Removes key mappings of the console. Works like the C<unmap> command. +=item default_linemode [I<path=regexp> | I<tag=tags>] I<linemodename> + +Sets the default linemode. See I<linemode> command. + +Examples: + +Set the global default linemode to "permissions": + :default_linemode permissions + +Set the default linemode to "permissions" for all files tagged with "p" or "P": + :default_linemode tag=pP permissions + +Set the default linemode for all files in ~/books/ to "papertitle": + :default_linemode path=/home/.*?/books/.* papertitle + =item delete Destroy all files in the selection with a roundhouse kick. ranger will ask for @@ -967,6 +1001,15 @@ This command is based on the I<scout> command and supports all of its options. Looks for a string in all marked files or directories. +=item linemode I<linemodename> + +Sets the linemode of all files in the current directory. The linemode may be: + + "filename": display each line as "<basename>...<size>" + "permissions": display each line as "<permissions> <owner> <group> <basename>" + "papertitle": display metadata from .paperinfo files if available, fall back + to the "filename" linemode if no metadata was found. See :paper commands. + =item load_copy_buffer Load the copy buffer from F<~/.config/ranger/copy_buffer>. This can be used to @@ -1009,6 +1052,29 @@ displayed when pressing "r" in ranger. Note that if you specify an application, the mode is ignored. +=item paper + +This command opens a series of commands on the console that will ask the user +to input metadata about the current file. This is used by the paper manager +module of ranger and can be later displayed in ranger, for example by setting +the option "linemode" to "papertitle". + +=item paper_authors I<authors> + +Tells the paper manager to set/update the authors of the current file + +=item paper_title I<title> + +Tells the paper manager to set/update the title of the current file + +=item paper_url I<url> + +Tells the paper manager to set/update the url of the current file + +=item paper_year I<year> + +Tells the paper manager to set/update the year of the current file + =item pmap I<key> I<command> Binds keys for the pager. Works like the C<map> command. diff --git a/ranger/config/commands.py b/ranger/config/commands.py index 953e2cc3..49d8f213 100644 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -381,6 +381,43 @@ class setintag(setlocal): self.fm.set_option_from_string(name, value, tags=tags) +class default_linemode(Command): + def execute(self): + import re + from ranger.container.fsobject import POSSIBLE_LINEMODES + + if len(self.args) < 2: + self.fm.notify("Usage: default_linemode [path=<regexp> | tag=<tag(s)>] <linemode>", bad=True) + + # Extract options like "path=..." or "tag=..." from the command line + arg1 = self.arg(1) + method = "always" + argument = None + if arg1.startswith("path="): + method = "path" + argument = re.compile(arg1[5:]) + self.shift() + elif arg1.startswith("tag="): + method = "tag" + argument = arg1[4:] + self.shift() + + # Extract and validate the line mode from the command line + linemode = self.rest(1) + if linemode not in POSSIBLE_LINEMODES: + self.fm.notify("Invalid linemode: %s; should be %s" % + (linemode, "/".join(POSSIBLE_LINEMODES)), bad=True) + + # Add the prepared entry to the fm.default_linemodes + entry = [method, argument, linemode] + self.fm.default_linemodes.appendleft(entry) + + # Redraw the columns + if hasattr(self.fm.ui, "browser"): + for col in self.fm.ui.browser.columns: + col.need_redraw = True + + class quit(Command): """:quit @@ -1281,3 +1318,88 @@ class flat(Command): self.fm.thisdir.flat = level self.fm.thisdir.load_content() + +# Papermanager commands +# -------------------------------- +class paper(Command): + """ + :paper + + This command opens a series of commands on the console that will ask the + user to input metadata about the current file. This is used by the paper + manager module of ranger and can be later displayed in ranger, for example + by setting the option "linemode" to "papertitle". + """ + _paper_console_chain = None + def execute(self): + # TODO: This sets a pseudo-global variable containing a stack of + # commands that should be opened in the console next. It's a + # work-around for ranger's lack of inherent console command chaining + # and will hopefully be implemented properly in the future. + paper._paper_console_chain = ["url", "year", "authors", "title"] + + self._process_command_stack() + + def _process_command_stack(self): + if paper._paper_console_chain: + key = paper._paper_console_chain.pop() + self._paper_fill_console(key) + else: + for col in self.fm.ui.browser.columns: + col.need_redraw = True + + def _paper_fill_console(self, key): + paperinfo = self.fm.papermanager.get_paper_info(self.fm.thisfile.path) + if key in paperinfo and paperinfo[key]: + existing_value = paperinfo[key] + else: + existing_value = "" + text = "paper_%s %s" % (key, existing_value) + self.fm.open_console(text, position=len(text)) + + +class paper_title(paper): + """ + :paper_title <title> + + Tells the paper manager to set/update the title of the current file + """ + _key = "title" + + def execute(self): + update_dict = dict() + update_dict[self._key] = self.rest(1) + self.fm.papermanager.set_paper_info(self.fm.thisfile.path, update_dict) + self._process_command_stack() + + def tab(self): + paperinfo = self.fm.papermanager.get_paper_info(self.fm.thisfile.path) + if paperinfo[self._key]: + return self.arg(0) + " " + paperinfo[self._key] + + +class paper_authors(paper_title): + """ + :paper_authors <authors> + + Tells the paper manager to set/update the authors of the current file + """ + _key = "authors" + + +class paper_url(paper_title): + """ + :paper_url <authors> + + Tells the paper manager to set/update the url of the current file + """ + _key = "url" + + +class paper_year(paper_title): + """ + :paper_year <authors> + + Tells the paper manager to set/update the year of the current file + """ + _key = "year" diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf index 23cd2e10..12fd2a32 100644 --- a/ranger/config/rc.conf +++ b/ranger/config/rc.conf @@ -174,6 +174,11 @@ set show_selection_in_titlebar true # increases CPU load. set idle_delay 2000 +# When the paper manager module looks for metadata, should it only look for a +# ".paperinfo" file in the current directory, or do a deep search and check all +# directories above the current one as well? +set papermanager_deep_search false + # =================================================================== # == Local Options # =================================================================== @@ -232,6 +237,11 @@ map r chain draw_possible_programs; console open_with map f console find map cd console cd +# Change the line mode +map Mf linemode filename +map Mp linemode permissions +map Mt linemode papertitle + # Tagging / Marking map t tag_toggle map ut tag_remove diff --git a/ranger/container/directory.py b/ranger/container/directory.py index c6987a76..c331053a 100644 --- a/ranger/container/directory.py +++ b/ranger/container/directory.py @@ -567,6 +567,10 @@ class Directory(FileSystemObject, Accumulator, Loadable): """Is the directory empty?""" return self.files is None or len(self.files) == 0 + def _set_linemode_of_children(self, mode): + for f in self.files: + f._set_linemode(mode) + def __nonzero__(self): """Always True""" return True diff --git a/ranger/container/file.py b/ranger/container/file.py index ab677125..7297dc30 100644 --- a/ranger/container/file.py +++ b/ranger/container/file.py @@ -43,6 +43,8 @@ class File(FileSystemObject): preview_known = False preview_loading = False + _linemode = "filename" + @property def firstbytes(self): try: diff --git a/ranger/container/fsobject.py b/ranger/container/fsobject.py index 6f206d0d..59e23f6b 100644 --- a/ranger/container/fsobject.py +++ b/ranger/container/fsobject.py @@ -12,9 +12,14 @@ DOCUMENT_BASENAMES = ('bugs', 'bugs', 'changelog', 'copying', 'credits', BAD_INFO = '?' +POSSIBLE_LINEMODES = ("filename", "papertitle", "permissions") +DEFAULT_LINEMODE = "filename" + import re +from grp import getgrgid from os import lstat, stat, getcwd from os.path import abspath, basename, dirname, realpath, splitext, extsep, relpath +from pwd import getpwuid from ranger.core.shared import FileManagerAware, SettingsAware from ranger.ext.shell_escape import shell_escape from ranger.ext.spawn import spawn @@ -80,6 +85,8 @@ class FileSystemObject(FileManagerAware, SettingsAware): basename_is_rel = False + _linemode = DEFAULT_LINEMODE + def __init__(self, path, preload=None, path_is_abs=False, basename_is_rel=False): if not path_is_abs: path = abspath(path) @@ -101,6 +108,21 @@ class FileSystemObject(FileManagerAware, SettingsAware): except ValueError: self.extension = None + # Set the line mode from fm.default_linemodes + for method, argument, linemode in self.fm.default_linemodes: + if linemode in POSSIBLE_LINEMODES: + if method == "always": + self._linemode = linemode + break + if method == "path" and argument.search(path): + self._linemode = linemode + break + if method == "tag" and self.realpath in self.fm.tags and \ + self.fm.tags.marker(self.realpath) in argument: + self._linemode = linemode + break + + def __repr__(self): return "<{0} {1}>".format(self.__class__.__name__, self.path) @@ -129,6 +151,19 @@ class FileSystemObject(FileManagerAware, SettingsAware): def safe_basename(self): return self.basename.translate(_safe_string_table) + @lazy_property + def user(self): + try: + return getpwuid(self.stat.st_uid)[0] + except: + return str(self.stat.st_uid) + + @lazy_property + def group(self): + try: + return getgrgid(self.stat.st_gid)[0] + except: + return str(self.stat.st_gid) for attr in ('video', 'audio', 'image', 'media', 'document', 'container'): exec("%s = lazy_property(" @@ -373,3 +408,6 @@ class FileSystemObject(FileManagerAware, SettingsAware): self.vcs_outdated = True return True return False + + def _set_linemode(self, mode): + self._linemode = mode diff --git a/ranger/container/settings.py b/ranger/container/settings.py index f75c274f..ad42b13f 100644 --- a/ranger/container/settings.py +++ b/ranger/container/settings.py @@ -31,6 +31,7 @@ ALLOWED_SETTINGS = { 'mouse_enabled': bool, 'open_all_images': bool, 'padding_right': bool, + 'papermanager_deep_search': bool, 'preview_directories': bool, 'preview_files': bool, 'preview_images': bool, diff --git a/ranger/core/actions.py b/ranger/core/actions.py index ba6b3658..879d1f68 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -27,6 +27,7 @@ from ranger.core.tab import Tab from ranger.container.file import File from ranger.core.loader import CommandLoader, CopyLoader from ranger.container.settings import ALLOWED_SETTINGS +from ranger.container.fsobject import POSSIBLE_LINEMODES, DEFAULT_LINEMODE MACRO_FAIL = "<\x01\x01MACRO_HAS_NO_VALUE\x01\01>" @@ -51,6 +52,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): self.garbage_collect(-1) self.enter_dir(old_path) self.change_mode('normal') + if self.papermanager: + self.papermanager.reset() def change_mode(self, mode): if mode == self.mode: @@ -151,6 +154,50 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): """Redraw the window""" self.ui.redraw_window() + def linemode(self, mode, directory=None, depth=0): + """ + Change what is displayed as a filename. + + - "mode" may be: "filename", "permissions", "papertitle", the mode "normal" + is mapped to "filename". + - "directory" specifies the directory. None means the current directory + - "depth" specifies the recursion depth + """ + + assert mode == "normal" or mode in POSSIBLE_LINEMODES + + if mode == "normal": + mode = DEFAULT_LINEMODE + + if directory is None: + directory = self.fm.thisdir + + directories = set([directory]) + bucket = set() + + current_depth = 0 + + while True: + if current_depth >= depth: + for direct in directories: + direct._set_linemode_of_children(mode) + break + + else: + for direct in directories: + direct._set_linemode_of_children(mode) + for file_ in direct.files: + if file_.is_directory: + bucket.add(file_) + + directories, bucket = bucket, directories + bucket.clear() + current_depth += 1 + + # Ask the browsercolumns to redraw + for col in self.ui.browser.columns: + col.need_redraw = True + def open_console(self, string='', prompt=None, position=None): """Open the console""" self.change_mode('normal') diff --git a/ranger/core/fm.py b/ranger/core/fm.py index d567bf24..3497f20c 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -20,6 +20,7 @@ from ranger.gui.ui import UI from ranger.container.bookmarks import Bookmarks from ranger.core.runner import Runner from ranger.ext.img_display import ImageDisplayer +from ranger.ext.papermanager import PaperManager from ranger.ext.rifle import Rifle from ranger.container.directory import Directory from ranger.ext.signals import SignalDispatcher @@ -56,9 +57,14 @@ class FM(Actions, SignalDispatcher): self.restorable_tabs = deque([], ranger.MAX_RESTORABLE_TABS) self.py3 = sys.version_info >= (3, ) self.previews = {} + self.default_linemodes = deque() self.loader = Loader() self.copy_buffer = set() self.do_cut = False + self.papermanager = PaperManager() + self.settings.signal_bind('setopt.papermanager_deep_search', + lambda signal: setattr(signal.fm.papermanager, 'deep_search', + signal.value)) try: self.username = pwd.getpwuid(os.geteuid()).pw_name diff --git a/ranger/ext/papermanager.py b/ranger/ext/papermanager.py new file mode 100644 index 00000000..a6292c49 --- /dev/null +++ b/ranger/ext/papermanager.py @@ -0,0 +1,171 @@ +# Copyright (C) 2014 Roman Zimbelmann <hut@lepus.uberspace.de> +# This software is distributed under the terms of the GNU GPL version 3. + +""" +A Paper Manager that reads metadata information about papers from a file. + +The file is named .paperinfo and is formatted as comma-separated values. + +The columns are: +1. Filename +2. Date +3. Title +4. Authors +5. URL +""" + +PAPERINFO_FILE_NAME = ".paperinfo" +DEEP_SEARCH_DEFAULT = False + +import csv +from os.path import join, dirname, exists, basename + +from ranger.ext.openstruct import OpenStruct + +class PaperManager(object): + def __init__(self): + self.metadata_cache = dict() + self.metafile_cache = dict() + self.deep_search = DEEP_SEARCH_DEFAULT + + def reset(self): + self.metadata_cache.clear() + self.metafile_cache.clear() + + def get_paper_info(self, filename): + try: + return self.metadata_cache[filename] + except KeyError: + result = OpenStruct(filename=filename, title=None, year=None, + authors=None, url=None) + + valid = (filename, basename(filename)) + for metafile in self._get_metafile_names(filename): + for entry in self._get_metafile_content(metafile): + if entry[0] in valid: + self._fill_ostruct_with_data(result, entry) + self.metadata_cache[filename] = result + return result + + # Cache the value + self.metadata_cache[filename] = result + return result + + def set_paper_info(self, filename, update_dict): + result = None + found = False + valid = (filename, basename(filename)) + first_metafile = None + + if not self.deep_search: + metafile = next(self._get_metafile_names(filename)) + return self._set_paper_info_raw(filename, update_dict, metafile) + + for i, metafile in enumerate(self._get_metafile_names(filename)): + if i == 0: + first_metafile = metafile + + csvfile = None + try: + csvfile = open(metafile, "r") + except: + # .paperinfo file doesn't exist... look for another one. + pass + else: + reader = csv.reader(csvfile, skipinitialspace=True) + for row in reader: + name, year, title, authors, url = row + if name in valid: + return self._set_paper_info_raw(filename, update_dict, + metafile) + self.metadata_cache[filename] = result + finally: + if csvfile: + csvfile.close() + + # No .paperinfo file found, so let's create a new one in the same path + # as the given file. + if first_metafile: + return self._set_paper_info_raw(filename, update_dict, first_metafile) + + def _set_paper_info_raw(self, filename, update_dict, metafile): + valid = (filename, basename(filename)) + paperinfo = OpenStruct(filename=filename, title=None, year=None, + authors=None, url=None) + + try: + with open(metafile, "r") as infile: + reader = csv.reader(infile, skipinitialspace=True) + rows = list(reader) + except IOError: + rows = [] + + with open(metafile, "w") as outfile: + writer = csv.writer(outfile) + found = False + + # Iterate through all rows and write them back to the file. + for row in rows: + if not found and row[0] in valid: + # When finding the row that corresponds to the given filename, + # update the items with the information from update_dict. + self._fill_row_with_ostruct(row, update_dict) + self._fill_ostruct_with_data(paperinfo, row) + self.metadata_cache[filename] = paperinfo + found = True + writer.writerow(row) + + # If the row was never found, create a new one. + if not found: + row = [basename(filename), None, None, None, None] + self._fill_row_with_ostruct(row, update_dict) + self._fill_ostruct_with_data(paperinfo, row) + self.metadata_cache[filename] = paperinfo + writer.writerow(row) + + def _get_metafile_content(self, metafile): + if metafile in self.metafile_cache: + return self.metafile_cache[metafile] + else: + if exists(metafile): + reader = csv.reader(open(metafile, "r"), skipinitialspace=True) + + entries = list(entry for entry in reader if len(entry) == 5) + self.metafile_cache[metafile] = entries + return entries + else: + return [] + + def _get_metafile_names(self, path): + # Iterates through the paths of all .paperinfo files that could + # influence the metadata of the given file. + # When deep_search is deactivated, this only yields the .paperinfo file + # in the same directory as the given file. + + base = dirname(path) + yield join(base, PAPERINFO_FILE_NAME) + if self.deep_search: + dirs = base.split("/")[1:] + for i in reversed(range(len(dirs))): + yield join("/" + "/".join(dirs[0:i]), PAPERINFO_FILE_NAME) + + def _fill_ostruct_with_data(self, ostruct, dataset): + # Copy data from a CSV row to a dict/ostruct + + filename, year, title, authors, url = dataset + if year: ostruct['year'] = year + if title: ostruct['title'] = title + if authors: ostruct['authors'] = authors + if url: ostruct['url'] = url + + def _fill_row_with_ostruct(self, row, update_dict): + # Copy data from a dict/ostruct into a CSV row + for key, value in update_dict.items(): + if key == "year": + row[1] = value + elif key == "title": + row[2] = value + elif key == "authors": + row[3] = value + elif key == "url": + row[4] = value diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index 0edb9c8d..b2159339 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -248,16 +248,38 @@ class BrowserColumn(Pager): else: tagged_marker = " " + # Extract linemode-related information from the drawn object + paperinfo = None + use_linemode = drawn._linemode + if use_linemode == "papertitle": + paperinfo = self.fm.papermanager.get_paper_info(drawn.path) + if not paperinfo.title: + use_linemode = "filename" + key = (self.wid, selected_i == i, drawn.marked, self.main_column, drawn.path in copied, tagged_marker, drawn.infostring, - drawn.vcsfilestatus, drawn.vcsremotestatus, self.fm.do_cut) + drawn.vcsfilestatus, drawn.vcsremotestatus, self.fm.do_cut, + use_linemode) if key in drawn.display_data: self.execute_curses_batch(line, drawn.display_data[key]) self.color_reset() continue - text = drawn.basename + + # Deal with the line mode + if use_linemode == "papertitle": + if paperinfo.year: + text = "%s - %s" % (paperinfo.year, paperinfo.title) + else: + text = paperinfo.title + if use_linemode == "filename": + text = drawn.basename + elif use_linemode == "permissions": + text = "%s %s %s %s" % (drawn.get_permission_string(), + drawn.user, drawn.group, drawn.basename) + + if drawn.marked and (self.main_column or \ self.settings.display_tags_in_all_columns): text = " " + text @@ -285,11 +307,21 @@ class BrowserColumn(Pager): space -= vcsstringlen # info string - infostring = self._draw_infostring_display(drawn, space) - infostringlen = self._total_len(infostring) - if space - infostringlen > 2: - predisplay_right = infostring + predisplay_right - space -= infostringlen + infostring = [] + infostringlen = 0 + if use_linemode == "filename": + infostring = self._draw_infostring_display(drawn, space) + elif use_linemode == "papertitle": + if paperinfo and paperinfo.authors: + authorstring = paperinfo.authors + if ',' in authorstring: + authorstring = authorstring[0:authorstring.find(",")] + infostring.append([" " + authorstring + " ", ["infostring"]]) + if infostring: + infostringlen = self._total_len(infostring) + if space - infostringlen > 2: + predisplay_right = infostring + predisplay_right + space -= infostringlen textstring = self._draw_text_display(text, space) textstringlen = self._total_len(textstring) |