Repository: nvim-lua/plenary.nvim
Pull request #144 (2021-04-20 19:14:20)

Change log location to cache to align with NeoVim.
Following this in Neovim https://github.com/neovim/neovim/pull/13739 it
probably makes sense to follow suit. I know this may change location for
some that are already using this, but it does seem logical to move this
here since other log files are also being placed here.


Patch:
diff --git a/lua/plenary/log.lua b/lua/plenary/log.lua
index e10e963..48798f3 100644
--- a/lua/plenary/log.lua
+++ b/lua/plenary/log.lua
@@ -51,7 +51,7 @@ local unpack = unpack or table.unpack
 log.new = function(config, standalone)
   config = vim.tbl_deep_extend("force", default_config, config)
 
-  local outfile = string.format('%s/%s.log', vim.api.nvim_call_function('stdpath', {'data'}), config.plugin)
+  local outfile = string.format('%s/%s.log', vim.api.nvim_call_function('stdpath', {'cache'}), config.plugin)
 
   local obj
   if standalone then
diff --git a/lua/plenary/path.lua b/lua/plenary/path.lua
index 1478008..2de31c2 100644
--- a/lua/plenary/path.lua
+++ b/lua/plenary/path.lua
@@ -7,8 +7,6 @@ local uv = vim.loop
 
 local F = require('plenary.functional')
 
-
-
 local S_IF = {
   -- S_IFDIR  = 0o040000  # directory
   DIR = 0x4000,
@@ -88,7 +86,7 @@ local function _normalize_path(filename)
           idx = idx + 1
       until idx > #parts
 
-      out_file = table.concat(parts, path.sep)
+      out_file = path.root(filename) .. table.concat(parts, path.sep)
   end
 
   return out_file
@@ -305,8 +303,29 @@ function Path:normalize(cwd)
   return _normalize_path(self.filename)
 end
 
+local function shorten_len(filename, len)
+  local final_match
+  local final_path_components = {}
+  for match in (filename..path.sep):gmatch("(.-)"..path.sep) do
+    if #match > len then
+      table.insert(final_path_components, string.sub(match, 1, len))
+    else
+      table.insert(final_path_components, match)
+    end
+    table.insert(final_path_components, path.sep)
+    final_match = match
+  end
+
+  local l = #final_path_components -- so that we don't need to keep calculating length
+  table.remove(final_path_components, l) -- remove final slash
+  table.remove(final_path_components, l-1) -- remvove shortened final component
+  table.insert(final_path_components, final_match) -- insert full final component
+
+  return table.concat(final_path_components)
+end
+
 local shorten = (function()
-  if jit then
+  if jit and path.sep ~= '\\' then
     local ffi = require('ffi') ffi.cdef [[
     typedef unsigned char char_u;
     char_u *shorten_dir(char_u *str);
@@ -322,11 +341,15 @@ local shorten = (function()
     end
   end
   return function(filename)
-    return filename
+    shorten_len(filename, 1)
   end
 end)()
 
-function Path:shorten()
+function Path:shorten(len)
+  assert(len ~= 0, 'len must be at least 1')
+  if len and len > 1 then
+    return shorten_len(self.filename, len)
+  end
   return shorten(self.filename)
 end
 
diff --git a/lua/plenary/tbl.lua b/lua/plenary/tbl.lua
index d1f018c..44de295 100644
--- a/lua/plenary/tbl.lua
+++ b/lua/plenary/tbl.lua
@@ -24,5 +24,17 @@ function tbl.unpack(t, i, j)
   return unpack(t, i or 1, j or t.n or #t)
 end
 
+---Freeze a table. A frozen table is not able to be modified.
+---http://lua-users.org/wiki/ReadOnlyTables
+---@param t table
+---@return table
+function tbl.freeze(t)
+  return setmetatable({}, {
+    __index = t,
+    __newindex = function()
+      error("Attempt to modify frozen table")
+    end
+  })
+end
 
 return tbl


Test patch:
diff --git a/tests/plenary/path_spec.lua b/tests/plenary/path_spec.lua
index 9f0750e..571d89f 100644
--- a/tests/plenary/path_spec.lua
+++ b/tests/plenary/path_spec.lua
@@ -158,22 +158,48 @@ describe('Path', function()
 
   describe(':normalize', function()
     it('can take paths with double separators change them to single separators', function()
-      local orig = 'lua//plenary/path.lua'
+      local orig = '/lua//plenary/path.lua'
       local final = Path:new(orig):normalize()
-      assert.are.same(final, 'lua/plenary/path.lua')
+      assert.are.same(final, '/lua/plenary/path.lua')
     end)
     -- this may be redundant since normalize just calls make_relative which is tested above
     it('can take absolute paths with double seps'
       .. 'and make them relative with single seps', function()
-      local orig = vim.loop.cwd() .. '/lua//plenary/path.lua'
+      local orig = '/lua//plenary/path.lua'
       local final = Path:new(orig):normalize()
-      assert.are.same(final, 'lua/plenary/path.lua')
+      assert.are.same(final, '/lua/plenary/path.lua')
     end)
 
     it('can remove the .. in paths', function()
-      local orig = 'lua//plenary/path.lua/foo/bar/../..'
+      local orig = '/lua//plenary/path.lua/foo/bar/../..'
       local final = Path:new(orig):normalize()
-      assert.are.same(final, 'lua/plenary/path.lua')
+      assert.are.same(final, '/lua/plenary/path.lua')
+    end)
+  end)
+
+  describe(':shorten', function()
+    it('can shorten a path', function()
+      local long_path = '/this/is/a/long/path'
+      local short_path = Path:new(long_path):shorten()
+      assert.are.same(short_path, '/t/i/a/l/path')
+    end)
+  end)
+
+  describe(':shorten', function()
+    it('can shorten a path components to a given length', function()
+      local long_path = '/this/is/a/long/path'
+      local short_path = Path:new(long_path):shorten(2)
+      assert.are.same(short_path, '/th/is/a/lo/path')
+
+      -- without the leading /
+      long_path = 'this/is/a/long/path'
+      short_path = Path:new(long_path):shorten(3)
+      assert.are.same(short_path, 'thi/is/a/lon/path')
+
+      -- where len is greater than the length of the final component
+      long_path = 'this/is/an/extremely/long/path'
+      short_path = Path:new(long_path):shorten(5)
+      assert.are.same(short_path, 'this/is/an/extre/long/path')
     end)
   end)
 
diff --git a/tests/plenary/tbl_spec.lua b/tests/plenary/tbl_spec.lua
new file mode 100644
index 0000000..60faa18
--- /dev/null
+++ b/tests/plenary/tbl_spec.lua
@@ -0,0 +1,27 @@
+local tbl = require('plenary.tbl')
+
+local function should_fail(fun)
+  local stat = pcall(fun)
+  assert(not stat, "Function should have errored")
+end
+
+describe('tbl utilities', function()
+  it('should be able to freeze a table', function()
+    local t = {1, 2, 3}
+    local frozen = tbl.freeze(t)
+    assert(t[1] == frozen[1])
+    assert(t[2] == frozen[2])
+    assert(t[3] == frozen[3])
+
+    should_fail(function()
+      frozen[4] = "thisthis"
+    end)
+
+    should_fail(function()
+      frozen.hello = "asdfasdf"
+    end)
+
+    assert(not frozen[5])
+    assert(not frozen.hello)
+  end)
+end)