[meld/pathlabel] iohelpers: Break out path formatting helper from pathlabel



commit dd7c4013f94d7f9862af46eb7d084964fcab931f
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Wed Jan 13 07:05:15 2021 +1000

    iohelpers: Break out path formatting helper from pathlabel

 meld/iohelpers.py    | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 meld/ui/pathlabel.py | 67 ++-------------------------------------------
 2 files changed, 80 insertions(+), 64 deletions(-)
---
diff --git a/meld/iohelpers.py b/meld/iohelpers.py
index 773241d8..33a8ef5c 100644
--- a/meld/iohelpers.py
+++ b/meld/iohelpers.py
@@ -1,4 +1,5 @@
 
+import pathlib
 from typing import Optional, Sequence
 
 from gi.repository import Gio, GLib, Gtk
@@ -145,3 +146,79 @@ def find_shared_parent_path(
     # a valid common parent path, or we've fallen through, in which
     # case the path return is None.
     return current_parent
+
+
+def format_parent_relative_path(parent: Gio.File, descendant: Gio.File) -> str:
+    """Format shortened child paths using a common parent
+
+    This is a helper for shortening sets of paths using their common
+    parent as a guide for what is required to distinguish the paths
+    from one another. The helper operates on every path individually,
+    so that this work can be done in individual widgets using only the
+    path being displayed (`descendent` here) and the common parent
+    (`parent` here).
+    """
+
+    # When thinking about the segmentation we do here, there are
+    # four path components that we care about:
+    #
+    #  * any path components above the non-common parent
+    #  * the earliest non-common parent
+    #  * any path components between the actual filename and the
+    #    earliest non-common parent
+    #  * the actual filename
+    #
+    # This is easiest to think about with an example of comparing
+    # two files in a parallel repository structure (or similar).
+    # Let's say that you have two copies of Meld at
+    # /home/foo/checkouts/meld and /home/foo/checkouts/meld-new,
+    # and you're comparing meld/filediff.py within those checkouts.
+    # The components we want would then be (left to right):
+    #
+    #  ---------------------------------------------
+    #  | /home/foo/checkouts | /home/foo/checkouts |
+    #  | meld                | meld-new            |
+    #  | meld                | meld                |
+    #  | filediff.py         | filediff.py         |
+    #  ---------------------------------------------
+    #
+    # Of all of these, the first (the first common parent) is the
+    # *only* one that's actually guaranteed to be the same. The
+    # second will *always* be different (or won't exist if e.g.,
+    # you're comparing files in the same folder or similar). The
+    # third component can be basically anything. The fourth
+    # components will often be the same but that's not guaranteed.
+
+    base_path_str = None
+    elided_path = None
+
+    descendant_parent = descendant.get_parent()
+    if descendant_parent is None:
+        raise ValueError(f'Path {descendant.get_path()} has no parent')
+
+    relative_path_str = parent.get_relative_path(descendant_parent)
+
+    if relative_path_str:
+        relative_path = pathlib.Path(relative_path_str)
+
+        base_path_str = relative_path.parts[0]
+        if len(relative_path.parts) == 1:
+            # No directory components, so we have no elided path
+            # segment
+            elided_path = None
+        else:
+            base_path_gfile = parent.get_child(base_path_str)
+            elided_path = base_path_gfile.get_relative_path(
+                descendant_parent)
+
+    show_parent = not parent.has_parent()
+    label_segments = [
+        '…' if not show_parent else None,
+        base_path_str,
+        '…' if elided_path else None,
+        descendant.get_basename(),
+    ]
+    label_text = parent.get_parse_name() if show_parent else ''
+    label_text += GLib.build_filenamev([s for s in label_segments if s])
+
+    return label_text
diff --git a/meld/ui/pathlabel.py b/meld/ui/pathlabel.py
index 301a0fb3..6484e20e 100644
--- a/meld/ui/pathlabel.py
+++ b/meld/ui/pathlabel.py
@@ -14,11 +14,11 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import logging
-import pathlib
 
-from gi.repository import Gdk, Gio, GLib, GObject, Gtk
+from gi.repository import Gdk, Gio, GObject, Gtk
 
 from meld.conf import _
+from meld.iohelpers import format_parent_relative_path
 from meld.melddoc import open_files_external
 
 log = logging.getLogger(__name__)
@@ -173,68 +173,7 @@ class PathLabel(Gtk.MenuButton):
         self._parent_gfile = parent
         self._gfile = descendant
 
-        # When thinking about the segmentation we do here, there are
-        # four path components that we care about:
-        #
-        #  * any path components above the non-common parent
-        #  * the earliest non-common parent
-        #  * any path components between the actual filename and the
-        #    earliest non-common parent
-        #  * the actual filename
-        #
-        # This is easiest to think about with an example of comparing
-        # two files in a parallel repository structure (or similar).
-        # Let's say that you have two copies of Meld at
-        # /home/foo/checkouts/meld and /home/foo/checkouts/meld-new,
-        # and you're comparing meld/filediff.py within those checkouts.
-        # The components we want would then be (left to right):
-        #
-        #  ---------------------------------------------
-        #  | /home/foo/checkouts | /home/foo/checkouts |
-        #  | meld                | meld-new            |
-        #  | meld                | meld                |
-        #  | filediff.py         | filediff.py         |
-        #  ---------------------------------------------
-        #
-        # Of all of these, the first (the first common parent) is the
-        # *only* one that's actually guaranteed to be the same. The
-        # second will *always* be different (or won't exist if e.g.,
-        # you're comparing files in the same folder or similar). The
-        # third component can be basically anything. The fourth
-        # components will often be the same but that's not guaranteed.
-
-        base_path_str = None
-        elided_path = None
-
-        # FIXME: move all of this (and above) path segmenting logic into a
-        # unit-testable helper
-
-        relative_path_str = parent.get_relative_path(descendant_parent)
-
-        if relative_path_str:
-            relative_path = pathlib.Path(relative_path_str)
-
-            base_path_str = relative_path.parts[0]
-            if len(relative_path.parts) == 1:
-                # No directory components, so we have no elided path
-                # segment
-                elided_path = None
-            else:
-                base_path_gfile = parent.get_child(base_path_str)
-                elided_path = base_path_gfile.get_relative_path(
-                    descendant_parent)
-
-        show_parent = not parent.has_parent()
-        label_segments = [
-            '…' if not show_parent else None,
-            base_path_str,
-            '…' if elided_path else None,
-            descendant.get_basename(),
-        ]
-        label_text = parent.get_parse_name() if show_parent else ''
-        label_text += GLib.build_filenamev([s for s in label_segments if s])
-
-        self._path_label = label_text
+        self._path_label = format_parent_relative_path(parent, descendant)
         self.notify('path_label')
 
     def action_copy_full_path(self, *args):


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]