243
243
--- @field parts string[] path parts excluding separators
244
244
---
245
245
--- @field filename string
246
+ --- @field cwd string
246
247
--- @field private _absolute string ? lazy eval ' ed fully resolved absolute path
247
248
local Path = { path = path }
248
249
@@ -256,6 +257,26 @@ Path.__index = function(t, k)
256
257
t .filename = t :_filename ()
257
258
return t .filename
258
259
end
260
+
261
+ if k == " cwd" then
262
+ t .cwd = vim .fn .getcwd ()
263
+ return t .cwd
264
+ end
265
+ end
266
+
267
+ Path .__div = function (self , other )
268
+ assert (Path .is_path (self ))
269
+ assert (Path .is_path (other ) or type (other ) == " string" )
270
+
271
+ return self :joinpath (other )
272
+ end
273
+
274
+ Path .__tostring = function (self )
275
+ return self .filename
276
+ end
277
+
278
+ Path .__concat = function (self , other )
279
+ return self .filename .. other
259
280
end
260
281
261
282
--- @alias plenary.Path2Args string | plenary.Path2 | (string | plenary.Path2 )[]
@@ -310,18 +331,17 @@ function Path:new(...)
310
331
end
311
332
error " 'Path' object is read-only"
312
333
end ,
334
+ -- stylua: ignore start
335
+ __div = function (t , other ) return Path .__div (t , other ) end ,
336
+ __concat = function (t , other ) return Path .__concat (t , other ) end ,
337
+ __tostring = function (t ) return Path .__tostring (t ) end ,
313
338
__metatable = Path ,
339
+ -- stylua: ignore end
314
340
})
315
341
316
342
return obj
317
343
end
318
344
319
- --- @param x any
320
- --- @return boolean
321
- function Path .is_path (x )
322
- return getmetatable (x ) == Path
323
- end
324
-
325
345
--- @private
326
346
--- @param drv string ?
327
347
--- @param root string ?
@@ -344,6 +364,12 @@ function Path:_filename(drv, root, parts)
344
364
return drv .. root .. relparts
345
365
end
346
366
367
+ --- @param x any
368
+ --- @return boolean
369
+ function Path .is_path (x )
370
+ return getmetatable (x ) == Path
371
+ end
372
+
347
373
--- @return boolean
348
374
function Path :is_absolute ()
349
375
if self .root == " " then
@@ -353,6 +379,16 @@ function Path:is_absolute()
353
379
return self ._path .has_drv and self .drv ~= " "
354
380
end
355
381
382
+ --- if path doesn't exists, returns false
383
+ --- @return boolean
384
+ function Path :is_dir ()
385
+ local stat = uv .fs_stat (self :absolute ())
386
+ if stat then
387
+ return stat .type == " directory"
388
+ end
389
+ return false
390
+ end
391
+
356
392
--- @param parts string[] path parts
357
393
--- @return string[]
358
394
local function resolve_dots (parts )
@@ -373,6 +409,10 @@ local function resolve_dots(parts)
373
409
end
374
410
375
411
--- normalized and resolved absolute path
412
+ ---
413
+ --- if given path doesn't exists and isn't already an absolute path, creates
414
+ --- one using the cwd
415
+ ---
376
416
--- respects 'shellslash' on Windows
377
417
--- @return string
378
418
function Path :absolute ()
@@ -381,16 +421,17 @@ function Path:absolute()
381
421
end
382
422
383
423
local parts = resolve_dots (self .parts )
384
- local filename = self :_filename (self .drv , self .root , parts )
385
424
if self :is_absolute () then
386
- self ._absolute = filename
425
+ self ._absolute = self : _filename ( nil , nil , parts )
387
426
else
388
427
-- using fs_realpath over fnamemodify
389
428
-- fs_realpath resolves symlinks whereas fnamemodify doesn't but we're
390
429
-- resolving/normalizing the path anyways for reasons of compat with old Path
391
- self . _absolute = uv .fs_realpath (self :_filename ())
430
+ local p = uv .fs_realpath (self :_filename ()) or Path : new ({ self . cwd , self }): absolute ( )
392
431
if self .path .isshellslash then
393
- self ._absolute = self ._absolute :gsub (" \\ " , path .sep )
432
+ self ._absolute = p :gsub (" \\ " , path .sep )
433
+ else
434
+ self ._absolute = p
394
435
end
395
436
end
396
437
return self ._absolute
0 commit comments