17
17
--- things like `path.filename = 'foo'` but now explicitly adding some barrier
18
18
--- to this. Allows us to compute `filename` from "metadata" parsed once on
19
19
--- instantiation.
20
-
21
- --- TODO: rework `_filename` according to `_format_parsed_parts`
20
+ ---
21
+ --- - FIX: `Path:make_relative` throws error if you try to make a path relative
22
+ --- to another path that is not in the same subpath.
23
+ ---
24
+ --- eg. `Path:new("foo/bar_baz"):make_relative("foo/bar")` => errors as you
25
+ --- can't get to "foo/bar_baz" from "foo/bar" without going up in directory.
26
+ --- This would previously return "foo/bar_baz" which is wrong.
27
+ ---
28
+ --- Adds an option to walk up path to compensate.
29
+ ---
30
+ --- eg. `Path:new("foo/bar_baz"):make_relative("foo/bar", true)` => returns
31
+ --- "../bar_baz"
22
32
23
33
local uv = vim .loop
24
34
local iswin = uv .os_uname ().sysname == " Windows_NT"
@@ -609,8 +619,21 @@ function Path:is_relative(to)
609
619
end
610
620
--- @cast to plenary.Path2
611
621
622
+ if to == self then
623
+ return true
624
+ end
625
+
626
+ -- NOTE: could probably be optimized by letting _WindowsPath/_WindowsPath
627
+ -- handle this.
628
+
612
629
local to_abs = to :absolute ()
613
- return self :absolute ():sub (1 , # to_abs ) == to_abs
630
+ for parent in self :iter_parents () do
631
+ if to_abs == parent then
632
+ return true
633
+ end
634
+ end
635
+
636
+ return false
614
637
end
615
638
616
639
--- makes a path relative to another (by default the cwd).
620
643
--- @param walk_up boolean ? walk up to the provided path using ' ..' (default : ` false ` )
621
644
--- @return string
622
645
function Path :make_relative (to , walk_up )
646
+ -- NOTE: could probably take some shortcuts and avoid some `Path:new` calls
647
+ -- by allowing _WindowsPath/_PosixPath handle this individually.
648
+ -- As always, Windows root complicates things, so generating a new Path often
649
+ -- easier/less error prone than manual string manipulate but at the cost of
650
+ -- perf.
623
651
walk_up = vim .F .if_nil (walk_up , false )
624
652
625
653
if to == nil then
@@ -649,7 +677,6 @@ function Path:make_relative(to, walk_up)
649
677
local common_path
650
678
for parent in to :iter_parents () do
651
679
table.insert (steps , " .." )
652
- print (parent , abs )
653
680
if abs :sub (1 , # parent ) == parent then
654
681
common_path = parent
655
682
break
@@ -660,18 +687,9 @@ function Path:make_relative(to, walk_up)
660
687
error (string.format (" '%s' and '%s' have different anchors" , self , to ))
661
688
end
662
689
663
- local res_path = abs :sub (# common_path + 1 )
664
- return table.concat (steps , self .sep ) .. res_path
690
+ local res_path = abs :sub (# common_path + 1 ):gsub (" ^" .. self .sep , " " )
691
+ table.insert (steps , res_path )
692
+ return Path :new (steps ).filename
665
693
end
666
694
667
- -- vim.o.shellslash = false
668
-
669
- local root = " C:/"
670
- local p = Path :new (Path .path .root (vim .fn .getcwd ()))
671
- vim .print (" p parent" , p .filename , p :parents (), p :parent ().filename )
672
- -- local absolute = p:absolute()
673
- -- local relative = Path:new(absolute):make_relative(Path:new "C:/Windows", true)
674
- -- print(p.filename, absolute, relative)
675
- vim .o .shellslash = true
676
-
677
695
return Path
0 commit comments