这是如何在Lua工作中解除功能的

时间:2013-07-31 18:47:18

标签: tabs lua spaces

-- Converts tabs to spaces
function detab(text)
    local tab_width = 4
    local function rep(match)
        local spaces = -match:len()
        print("match:"..match)
        while spaces<1 do spaces = spaces + tab_width end
        print("Found "..spaces.." spaces")
        return match .. string.rep(" ", spaces)
    end
    text = text:gsub("([^\n]-)\t", rep)
    return text
end


str='   thisisa string'
--thiis is a      string

print("length: "..str:len())
print(detab(str))
print(str:gsub("\t","    "))

我有来自markdown.lua的这段代码,它将标签转换为空格(顾名思义)。我设法弄清楚它是从头开始搜索的 字符串,直到找到一个制表符并将匹配的子字符串传递给'rep'函数。它会反复执行,直到没有更多匹配为止 我的问题是试图找出rep函数正在做什么,特别是在 while循环。
为什么循环停在1
为什么它会计数?
令人惊讶的是,它计算了弦乐中的空格数量,究竟是多么神秘 如果将其输出与上一个gsub替换的输出进行比较,您会发现它们不同。
Detab维持 gsub替换时没有对齐字符。 为什么会这样?
加分问题。当我在Scite中打开空白时,我可以看到't'之前的标签比第三个's'之前的标签长。 为什么他们不同?

2 个答案:

答案 0 :(得分:4)

通过分析rep函数,这就是它似乎正在做的事情。首先,它接受传入的匹配字符串的长度并使其为负(例如,将其乘以-1)。在while循环中,它会不断增加空间直到它变为正数。

使用数字行可能更容易将其可视化:

<--|----|-------|----|----|----|----|----|----|----|----|--->
  -n      -spaces             -2   -1    0    1    2    n

本质上,循环试图计算在“溢出”之前有多少“tab_widths”可以适应空格。这里使用从0到1的转换作为截止点。在循环之后,spaces将会溢出多少。

实际上,while循环模仿了一个你可能知道为模数的数学运算。换句话说,内部rep函数可以重写为:

local function rep(match)
  local spaces = tab_width - match:len() % tab_width

  return match .. string.rep(" ", spaces)
end

这与外部str:gsub("\t", " ")不同,其中不加选择地用4个空格替换所有制表符。 OTOH,在detab函数中,替换制表符的空格数取决于匹配捕获的长度。

eg.
matching length is 1, replace tab with 3 spaces
matching length is 2, replace tab with 2 spaces
matching length is 3, replace tab with 1 space
matching length is n, replace tab with tab_width - (n % tab_width) spaces
etc.

答案 1 :(得分:1)

回答红利问题: 制表符对齐tabstops。一个tabstop是八个字符。第一个标签从第六列开始,因此需要填充三个空格。第二个选项卡从第16列开始,因此它只需要一个空格宽。

当空格变为正数时,循环停止,因为循环一直以“缩进”增量添加空格,直到它有足够的空格比匹配的文本更长。然后,当它将该数量的空格与匹配的文本组合时,它构造了一个填充到正确的tabstop的字符串。

这也是gsub不同的原因。 gsub不将制表符视为tabstop字符,而是将其视为四个空格。所以第二个标签不会填充到tabstop,而是扩展到四个空格。