Как найти lua файлы

So far, we’ve learned a lot about working with data within a program, and how to include more Lua into a program, but not how to import and export data from a file. Lua has plenty of builtin features to handle this via the I/O Library. The I/O library works with both text and binary files.

Lua is Unicode agnostic. This means that all strings are treated effectively as binary data rather than any kind of encoding. Because of this, you rarely need to use a Unicode library except for more specific use cases.

Open and Close

Before we get into either reading or writing, we need to discuss opening and closing files. Your workflow will typically involve opening a file, doing whatever with it, then explicitly closing it. When you exit the program, the file should close as well, but that’s considered poor practice.

To open a file:

io.open( [filename] [, [mode]] )

The filename is where the file is, and the mode is listed in the table below (or following the same mode as in C for fopen). If there is no mode, r is implied.

r (Default) Open the file read only.
w Open the file to write. Overwrites contents or makes a new file.
a Append the file. Write to the end or make a new file. Repositioning operations are ignored.
r+ Open the file in read and write mode. The file must exist.
w+ Open the file to write. Clears existing contents or makes a new file.
a+ Append the file with read mode. Write to the end or make a new file. Repositioning operations affect read mode.

You can also use the b modifier at the end of the mode in order to open the file in binary mode. For example:

io.open( [file], "r+b" )

io.open returns a file handle object. When working with opening files, you should assign the file handle to a variable to do anything useful.

local filehandle = io.open( "mycontents.txt", "rb" )

Once you’re done with a file, you need to close it.

local filehandle = io.open( "mycontents.txt", "rb" )
…
filehandle:close()

Reading Files

Once you open your file, you can read it. Reading is done via:

filehandle:read( "[option]" [or: [number]] )

The options correspond to the following table for Lua 5.1 and 5.2:

*line *l Reads a single line from the file.
*all *a Reads all of the content from the file.
*number *n Reads a number from the file. This reads until the end of a valid sequence.
[number] (integer) Reads [number] characters (bytes) from the file. Does not use quotes.

Lua 5.3 is adds the following (but is backwards compatible):

a Reads all of the content from the file.
l Reads a single line from the file.
L Reads a single line from the file, but keeps the end of line character(s)
n Reads a number from the file. This reads until the end of a valid sequence.
[number] Reads [number] characters (bytes) from the file. Does not use quotes.

These basically all return nil if there isn’t a valid sequence, except for the “all” options which return an empty string as long as the file is valid.

Let’s see it all in action with test.txt:

123
line 2
123456789

(Note the new line at the end of test.txt)

Let’s try each of our options out for reading and see what we get. We’re going to start the whole file over and over again to avoid any issues.

#!/usr/bin/lua5.1

local file = io.open( "test.txt", "r" )

local contents = file:read( "*all" )
print( contents )

file:close()

This gets us:

./file1.lua 
123
line 2
123456789

Let’s see all of our options smashed together now that we’ve seen the basic structure:

#!/usr/bin/lua5.1

print( "*all" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "*all" )
print( contents )
file:close()

print()
print( "*line" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "*line" )
print( contents )
file:close()

print()
print( "*number" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "*number" )
print( contents )
file:close()

print()
print( "6" )
local file = io.open( "test.txt", "r" )
local contents = file:read( 6 )
print( contents )
file:close()

Which gets us:

./file1.lua 
*all
123
line 2
123456789


*line
123

*number
123

6
123
li

Let’s do the same with Lua 5.3:

#!/usr/bin/lua5.3

print( "a" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "a" )
print( contents )
file:close()

print()
print( "l" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "l" )
print( contents )
file:close()

print()
print( "L" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "L" )
print( contents )
file:close()

print()
print( "n" )
local file = io.open( "test.txt", "r" )
local contents = file:read( "n" )
print( contents )
file:close()

print()
print( "6" )
local file = io.open( "test.txt", "r" )
local contents = file:read( 6 )
print( contents )
file:close()

And we get:

./file1.lua 
a
123
line 2
123456789


l
123

L
123


n
123

6
123
li

Moving Around In Files

Lua offers a seek function. Seek works the same in 5.1, 5.2, and 5.3.

[file]:seek( "[start]" [, [offset]] )

This has the following starting points:

set Set to start from the beginning of the file.
cur Move from the current position the file is at.
end Move from the end of the file.

Since we start at the beginning of the file, we’d get the following with cur:

#!/usr/bin/lua5.3

print( "a" )
local file = io.open( "test.txt", "r" )
file:seek("cur", 3)
local contents = file:read( "a" )
print( contents )
file:close()

print()
print( "l" )
local file = io.open( "test.txt", "r" )
file:seek("cur", 3)
local contents = file:read( "l" )
print( contents )
file:close()

print()
print( "L" )
local file = io.open( "test.txt", "r" )
file:seek("cur", 3)
local contents = file:read( "L" )
print( contents )
file:close()

print()
print( "n" )
local file = io.open( "test.txt", "r" )
file:seek("cur", 3)
local contents = file:read( "n" )
print( contents )
file:close()

print()
print( "6" )
local file = io.open( "test.txt", "r" )
file:seek("set", 3)
local contents = file:read( 6 )
print( contents )
file:close()

Which gets us:

./file2.lua 
a

line 2
123456789


l


L



n
nil

6

line

Let’s test a few other methods:

#!/usr/bin/lua5.3

print( "a" )
local file = io.open( "test.txt", "r" )
file:seek("cur", 3)
local contents = file:read( "a" )
print( contents )

print()
print( "l" )

file:seek("set")
local contents2 = file:read( "l" )
print( contents2 )

print()
print( "n" )

file:seek("end", -3)
local contents3 = file:read( "n" )
print( contents3 )
file:close()

Which gets us:

./file3.lua 
a

line 2
123456789


l
123

n
89

[file]:seek() gets you the current position for later usage.

More File Operations

[file]:flush() syncs the data to disk for the file.

The Lua Manual has a lot more than we can include here. See these for a reference to some of the functions as written in 5.3.

Writing Files

Luckily, in Lua, writing is way easier than reading. You just use [file]:write( [contents] ) to write to the given file.

#!/usr/bin/lua5.1

local file = io.open( "testout.txt", "w" )
file:write( "here's a linen" )
file:write( "and anothern" )
file:write( "and yet anothern" )
file:close()

local file2 = io.open( "testout.txt", "r" )
local content = file2:read( "*a" )
print( content )
file2:close()

This gets you:

/file3.lua 
here's a line
and another
and yet another

(Note: the extra end line)

What happens if you don’t use /n (the newline control character)?

Making It Cleaner

We’re going to get into Lua Idioms with the assert function. This function basically makes Lua check whether the condition is going to succeed or not and gracefully fail with an error.

Assert:

assert( [condition] [, [error message]] )

Let’s see it in action:

#!/usr/bin/lua5.1

local file = assert( io.open( "testout.txt", "w" ) )
file:write( "here's a linen" )
file:write( "and anothern" )
file:write( "and yet anothern" )
file:close()

local file2 = assert( io.open( "testout-DOESNOTEXIST.txt", "r" ) )
local content = file2:read( "*a" )
print( content )
file2:close()

Where we get:

/file3.lua 
/usr/bin/lua5.1: ./file3.lua:9: testout-DOESNOTEXIST.txt: No such file or directory
stack traceback:
	[C]: in function 'assert'
	./file3.lua:9: in main chunk
	[C]: ?

We’ve now cleanly errored out of the program without trying to read a file which does not exist.

Let’s learn about io.type( [filehandle] ). This is extremely useful for checking on if a file is able to get a file handle. io.type( [filehandle] ) returns either “file” (the handle is valid), “closed file” (the handle is closed), or nil (it failed). Here’s an example:

#!/usr/bin/lua5.1

local file = assert( io.open( "testout.txt", "w" ) )
file:write( "here's a linen" )
file:write( "and anothern" )
file:write( "and yet anothern" )
file:close()

local file2 = io.open( "testout-DOESNOTEXIST.txt", "r" )
if( io.type( file2 ) == "file" ) then
	local content = file2:read( "*a" )
	print( content )
	file2:close()
else
	print( "--error--" )
end

This gets us:

./file3.lua 
--error--

Now, instead of just exiting out, we have error handling. This is far cleaner than just using assert and exiting out. The assert function still has its place for debugging, but now we’ve made our program fault resilient and graceful as long as we handle it correctly.

I have written a function getScriptDir which uses the debug information like a few other people have suggested, but this one is going to work everytime (at least in Windows). But the thing is there are quite a few lines of code as it uses another function string.cut which i have created, which separates a string every given pattern, and puts it into a table.

function string.cut(s,pattern)
  if pattern == nil then pattern = " " end
  local cutstring = {}
  local i1 = 0
  repeat
    i2 = nil
    local i2 = string.find(s,pattern,i1+1)
    if i2 == nil then i2 = string.len(s)+1 end
    table.insert(cutstring,string.sub(s,i1+1,i2-1))
    i1 = i2
  until i2 == string.len(s)+1
  return cutstring
end

function getScriptDir(source)
  if source == nil then
    source = debug.getinfo(1).source
  end
  local pwd1 = (io.popen("echo %cd%"):read("*l")):gsub("\","/")
  local pwd2 = source:sub(2):gsub("\","/")
  local pwd = ""
  if pwd2:sub(2,3) == ":/" then
    pwd = pwd2:sub(1,pwd2:find("[^/]*%.lua")-1)
  else
    local path1 = string.cut(pwd1:sub(4),"/")
    local path2 = string.cut(pwd2,"/")
    for i = 1,#path2-1 do
      if path2[i] == ".." then
        table.remove(path1)
      else
        table.insert(path1,path2[i])
      end
    end
    pwd = pwd1:sub(1,3)
    for i = 1,#path1 do
      pwd = pwd..path1[i].."/"
    end
  end
  return pwd
end

Note: if you want to use this function in another OS than Windows, you have to change the io.popen("echo %cd%") in the line 15 to whatever command gives you present working directory in your OS, e.g. io.popen("pwd") for Linux, and the pwd2:sub(2,3) == ":/" in the line 18 to whatever represents the root directory in your OS, e.g. pwd2:sub(1,1) == "/" for Linux.

Note2: if you don’t provide the source variable to the function via debug.getinfo(1).source when calling it, then it will return the path to the directory of the file containing this function. Therefore, if you want to get the directory of a file which you called via dofile or loadfile, you will have to give it the source, like this: getScriptDir(debug.getinfo(1).source).

Мне нужно прочитать с файла в функции. файл в той же папке что и код.
Я передаю так : local inputFileName = [[ts.txt]]
Но выдает ошибку:

ts.txt: No such file or directory)

задан 17 ноя 2019 в 19:43

Vova Makarovych's user avatar

7

Если вы запускаете скрипт из той же директории, всё должно рабоать.
Если вы в другой директории, то либо перейдите в неё:

$ cd /path/to/dir
$ ls
script.lua
ts.txt
$ lua ./script.lua

Либо прописывайте абсолютный путь. Путь можно прописать в переменной
окружения:

# Unix:
export FILES_PATH="/path/to/dir"
:: Windows:
SET FILES_PATH="/path/to/dir"

И получить в скрипте:

local dir = os.getenv("FILES_PATH")
path = dir .. "/" .. "ts.txt"

ответ дан 17 ноя 2019 в 21:08

Ainar-G's user avatar

Ainar-GAinar-G

15.9k3 золотых знака24 серебряных знака41 бронзовый знак

18

Если вам надо открыть файл, который лежит в той же папке, что и текущий скрипт, то вам надо сперва определить полный путь к вашему скрипту, а затем, используя его, сконструировать и передать полный путь к файлу.

Определить путь к скрипту можно несколькими способами, например вот так:

function script_path()
   local str = debug.getinfo(2, "S").source:sub(2)
   return str:match("(.*[/\])") or ".\"
end

Ну а дальше всё просто:

local inputFileName = script_path() .. "ts.txt"

ответ дан 17 ноя 2019 в 20:29

zed's user avatar

zedzed

8,8262 золотых знака19 серебряных знаков34 бронзовых знака

2

Начало работы с Lua в Neovim

Содержание

  • Введение
    • Изучение языка Lua
    • Имеющиеся туториалы по написанию плагинов на Lua для Neovim
    • Связанные плагины
  • Куда класть файлы Lua
    • init.lua
    • Другие файлы Lua
      • Предостережения
      • Советы
      • Заметка относительно пакетов
  • Использование Lua в Vimscript
    • :lua
    • :luado
    • :luafile
      • luafile vs require():
    • luaeval()
    • v:lua
      • Предостережения
    • Советы
  • Пространство имён vim
    • Советы
  • Использование Vimscript из Lua
    • vim.api.nvim_eval()
      • Предостережения
    • vim.api.nvim_exec()
    • vim.api.nvim_command()
      • Советы
  • Управление опции vim
    • Использование функций API
    • Использование мета-аксессоров
      • Предостережения
  • Управление внутренними переменными vim
    • Использование функций API
    • Использование мета-аксессоров
      • Предостережения
  • Вызов функций Vimscript
    • vim.call()
    • vim.fn.{function}()
      • Советы
      • Предостережения
  • Определение сопоставлений клавиш
  • Определение пользовательских команд
  • Определение автокоманд
  • Определение синтаксиса/подсветки
  • Общие советы и рекомендации
    • Настройка линтеров/языковых серверов
      • luacheck
      • sumneko/lua-language-server
      • coc.nvim
  • Разное
    • vim.loop
    • vim.lsp
    • vim.treesitter
    • Transpilers

Created by gh-md-toc

Введение

Интеграция Lua в Neovim в качестве языка с первоклассной поддержкой превращает её в одну из важнейших особенностей редактора. Тем не менее, количество учебных материалов по написанию плагинов на Lua значительно меньше таковых на Vimscript.
Это руководство является попыткой предоставления необходимой информации для написания плагинов на Lua.

Это руководство предполагает, что пользователь использует последнюю версию Neovim nightly build.
Так как версия 0.5 Neovim находится на стадии разработки, имейте в виду, что API, которые находятся в активной разработке нестабильны и могут быть подвержены изменениям до релиза.

Изучение Lua

Если вы незнакомы с языком, имеется большое количество материалов для изучения:

  • Ресурс Learn X in Y minutes page about Lua позволит вам пробежаться по основам языка
  • Если вы предпочитаете видеоуроки, то у Дерека Банаса (Derek Banas) имеется часовой видеоурок 1-hour tutorial on the language
  • Сайт lua-users wiki содержит большое количество полезной информации относительно Lua
  • Сайт official reference manual for Lua должен дать исчерпывающую информацию о языке

Следует заметить, что Lua является очень чистым и простым языком. Язык легко изучить, особенно если имеется опыт использования аналогичного скриптового языка наподобие Javascript. Возможно, вы разбираетесь в Lua больше, чем вы представляете!

Заметка: версия Lua, встроенное в Neovim является LuaJIT 2.1.0, что поддерживает совместимость с Lua 5.1 (с некоторыми исключениями в виде расширений версии 5.2)

Имеющиеся туториалы по написанию плагинов на Lua для Neovim

Было написано несколько туториалов, чтобы помочь людям написать плагины на Lua. Некоторые из них значительно помогли для написания этого руководства. Большое спасибо их авторам.

  • teukka.tech – From init.vim to init.lua
  • 2n.pl – How to write neovim plugins in Lua
  • 2n.pl – How to make UI for neovim plugins in Lua
  • ms-jpq – Neovim Async Tutorial

Связанные плагины

  • Vimpeccable – Плагин, помогающий написать .vimrc на Lua
  • plenary.nvim – Все функции Lua, которые я не хоче переписывать
  • popup.nvim – Имплементация API Всплывающих окон vim(vim Popup API) для Neovim
  • nvim_utils
  • nvim-luadev – REPL/дебаг консоль для плагинов Neovim, написанных на lua
  • nvim-luapad – Интерактивный Neovim скратчпад для встроенного движка Lua
  • nlua.nvim – Lua Разработка для Neovim
  • BetterLua.vim – Лучшая синтаксическая подсветка Lua в Vim/NeoVim

Куда класть файлы Lua

init.lua

Neovim поддерживает загрузку файла init.lua вместо init.vim для конфигурации.

Для справок:

  • :help config

Другие файлы Lua

Файлы Lua обычно находятся внутри папки lua/ в вашей runtimepath (для большинства пользователей это папка ~/.config/nvim/lua на *nix-овых системах и ~/AppData/Local/nvim/lua для Windows). Вы можете вызвать эти файлы с помощью require() в качестве Lua модулей.

В качестве примера возьмем следующую структуру папок:

📂 ~/.config/nvim
├── 📁 after
├── 📁 ftplugin
├── 📂 lua
│  ├── 🌑 myluamodule.lua
│  └── 📂 other_modules
│     ├── 🌑 anothermodule.lua
│     └── 🌑 init.lua
├── 📁 pack
├── 📁 plugin
├── 📁 syntax
└── 🇻 init.vim

Lua код ниже загрузит модуль myluamodule.lua:

Заметьте отсутствие расширения файла .lua.

Аналогично, загрузка other_modules/anothermodule.lua выполняется следующим образом:

require('other_modules.anothermodule')
-- or
require('other_modules/anothermodule')

Разделители путей обозначены либо точкой . либо слэшем /.

Папка содержащая файл init.lua может быть загружена напрямую без необходимости уточнять имя файла.

require('other_modules') -- загружает other_modules/init.lua

Для большей информации: :help lua-require

Предостережения

В отличие от файлов с расширением .vim, файлы с расширением .lua не загружаются автоматически, если они находятся в специальных папках runtimepath. К примеру, Neovim загрузит plugin/foo.vim, но не загрузит plugin/foo.lua.

Также смотрите:

  • Issue #12670

Советы

Некоторые Lua плагины могут имет идентичные имена файлов внутри папки lua/. Это может привести к коллизии пространств имён.

Если два плагина имеют файл lua/main.lua, То вызов require('main') неопределён: какой файл необходимо загрузить?

Поэтому это хорошая идея создать пространство имен вашей конфигурации или плагина с помощью папки в самом верхнем уровне, наподобие: lua/plugin_name/main.lua

Заметка относительно пакетов

Обновление: если вы используете последнюю ночную сборку, это [больше не проблема] (neovim/neovim#13119), и вы можете спокойно пропустить этот раздел.

Если вы используете функцию packages или основанного на ней менеджера подключаемых модулей (например, packer.nvim, minpac или vim-packager), при использовании плагинов Lua следует помнить о некоторых вещах.

Пакеты в папке start загружаются только после считывания вашего init.vim. Это означает, что пакет не добавляется в runtimepath до тех пор, пока Neovim не закончит обработку файла. Это может вызвать проблемы, если плагин ожидает, что вы загрузите(require) модуль Lua или вызовете автоматически загружаемую функцию.

Предполагая, что в пакете start/foo есть файл lua/bar.lua, выполнение кода ниже в init.vim вызовет ошибку, потому что runtimepath еще не обновлен:

Вы должны использовать команду packadd! foo перед тем как вызвать модуль через require.

packadd! foo
lua require('bar')

Добавление ! к packadd означает, что Neovim поместит пакет в runtimepath без загрузки каких-либо скриптов в его папках plugin или ftdetect.

Также смотрите:

  • :help :packadd
  • Issue #11409

Использование Lua в Vimscript

:lua

Эта команда выполняет фрагмент кода Lua.

:lua require('myluamodule')

Многострочные скрипты возможны с использованием синтаксиса heredoc:

echo "Here's a bigger chunk of Lua code"

lua << EOF
local mod = require('mymodule')
local tbl = {1, 2, 3}

for k, v in ipairs(tbl) do
    mod.method(v)
end

print(tbl)
EOF

Примечание: каждая команда :lua имеет свою собственную область видимости, и переменные, объявленные с ключевым словом local, недоступны вне команды. Это не сработает:

:lua local foo = 1
:lua print(foo)
" выводит 'nil' вместо '1'

Примечание 2: функция print() в Lua ведет себя аналогично команде :echomsg. Его вывод сохраняется в истории сообщений и может быть подавлен командой :silent.

Также смотрите:

  • :help :lua
  • :help :lua-heredoc

:luado

Эта команда выполняет фрагмент кода Lua, который воздействует на диапазон строк в текущем буфере. Если диапазон не указан, вместо него используется весь буфер. Строка возвращаемая из блока, используется для определения того, чем должна быть заменена каждая строка в диапазоне.

Следующая команда заменит каждую строку в текущем буфере текстом hello world:

:luado return 'hello world'

Также предусмотрены две неявные переменные line и linenr. line – это текст строки, по которой выполняется итерация, а linenr – ее номер. Следующая команда сделает каждую строку, номер которой делится на 2, в верхний регистр:

:luado if linenr % 2 == 0 then return line:upper() end

Также смотрите:

  • :help :luado

:luafile

Эта команда считывает файл Lua.

:luafile ~/foo/bar/baz/myluafile.lua

Эта команда аналогична команде :source для файлов .vim или встроенной функции dofile() в Lua.

Также смотрите:

  • :help :luafile

luafile vs require():

Вам может быть интересно, в чем разница между lua require() и luafile, и стоит ли вам использовать одно вместо другого. У них разные варианты использования:

  • require():
    • это встроенная функция Lua. Это позволяет вам использовать модульную систему Lua
    • ищет модули в папках lua в вашем runtimepath
    • отслеживает, какие модули были загружены, и предотвращает повторный парсинг и выполнение скрипта. Если вы измените файл, содержащий код для модуля, и попытаетесь require() второй раз во время работы Neovim, модуль на самом деле не будет обновляться
  • :luafile:
    • является Ex командой. Не поддерживает модули
    • принимает абсолютный или относительный путь к рабочей папке текущего окна
    • выполняет содержимое скрипта независимо от того, выполнялся ли он раньше

:luafile также может быть полезен, если вы хотите запустить файл Lua, над которым вы работаете:

luaeval()

Эта встроенная функция Vimscript оценивает выражение Lua в форме строки и возвращает ее значение. Типы данных Lua автоматически преобразуются в типы Vimscript (и наоборот).

" Вы можете сохранить результат в переменной
let variable = luaeval('1 + 1')
echo variable
" 2
let concat = luaeval('"Lua".." is ".."awesome"')
echo concat
" 'Lua is awesome'

" Таблицы в виде списков преобразуются в списки Vim.
let list = luaeval('{1, 2, 3, 4}')
echo list[0]
" 1
echo list[1]
" 2
" Обратите внимание, что в отличие от таблиц Lua, списки Vim индексируются с нуля 

" Таблицы в виде словарей конвертируются в словари Vim.
let dict = luaeval('{foo = "bar", baz = "qux"}')
echo dict.foo
" 'bar'

" То же самое для логических значений и значений nil
echo luaeval('true')
" v:true
echo luaeval('nil')
" v:null

" Вы можете создавать алиас в Vimscript для функций Lua.
let LuaMathPow = luaeval('math.pow')
echo LuaMathPow(2, 2)
" 4
let LuaModuleFunction = luaeval('require("mymodule").myfunction')
call LuaModuleFunction()

" Также можно передавать функции Lua в качестве значений функциям Vim.
lua X = function(k, v) return string.format("%s:%s", k, v) end
echo map([1, 2, 3], luaeval("X"))

luaeval() принимает необязательный второй аргумент, который позволяет передавать данные в выражение. Затем вы можете получить доступ к этим данным из Lua, используя волшебную глобальную переменную _A:

echo luaeval('_A[1] + _A[2]', [1, 1])
" 2

echo luaeval('string.format("Lua is %s", _A)', 'awesome')
" 'Lua is awesome'

Также смотрите:

  • :help luaeval()

v:lua

Эта глобальная переменная Vim позволяет вам вызывать глобальные функции Lua прямо из Vimscript. Опять же, типы данных Vim преобразуются в типы Lua и наоборот.

call v:lua.print('Hello from Lua!')
" 'Hello from Lua!'

let scream = v:lua.string.rep('A', 10)
echo scream
" 'AAAAAAAAAA'

" Загрузка модулей работает
call v:lua.require('mymodule').myfunction()

" Как насчет неплохой статусной строки?
lua << EOF
function _G.statusline()
    local filepath = '%f'
    local align_section = '%='
    local percentage_through_file = '%p%%'
    return string.format(
        '%s%s%s',
        filepath,
        align_section,
        percentage_through_file
    )
end
EOF

set statusline=%!v:lua.statusline()

" Также работает в сопоставлениях выражений
lua << EOF
function _G.check_back_space()
    local col = vim.fn.col('.') - 1
    if col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') then
        return true
    else
        return false
    end
end
EOF

inoremap <silent> <expr> <Tab>
     pumvisible() ? '<C-n>' :
     v:lua.check_back_space() ? '<Tab>' :
     completion#trigger_completion()

Также смотрите:

  • :help v:lua
  • :help v:lua-call

Предостережения

Эта переменная может использоваться только для вызова функций. Следующий код всегда будет вызывать ошибку:

" Создание алиасов не работает
let LuaPrint = v:lua.print

" Доступ к словарям не работает
echo v:lua.some_global_dict['key']

" Использование функции в качестве значения не работает
echo map([1, 2, 3], v:lua.global_callback)

Советы

Вы можете получить подсветку синтаксиса Lua внутри файлов .vim, поместив let g: vimsyn_embed = 'l' в свой файл конфигурации. См. :help g:vimsyn_embed для получения дополнительной информации об этой опции.

Пространство имён vim

Neovim предоставляет глобальную переменную vim, которая служит точкой входа для взаимодействия с её API из Lua. Она предоставляет пользователям расширенную “стандартную библиотеку” функций, а также различные подмодули.

Некоторые примечательные функции и модули включают:

  • vim.inspect: вывод Lua объектов (полезно для проверки таблиц)
  • vim.regex: использование регулярных выражений Vim из Lua
  • vim.api: модуль, который предоставляет функции API (тот же API, что используют удалённые(remote) плагины)
  • vim.loop: модуль, который предоставляет функционал цикла событий Neovim (с использованием LibUV)
  • vim.lsp: модуль, который управляет встроенным клиентом LSP
  • vim.treesitter: модуль, который предоставляет функционал библиотеки tree-sitter

Этот список ни в коем случае не является исчерпывающим. Если вы хотите узнать больше о том, что делает переменная vim, :help lua-stdlib и :help lua-vim вам в помощь :). В качестве альтернативы вы можете выполнить :lua print (vim.inspect (vim)), чтобы получить список всех модулей.

Советы

Писать print(vim.inspect(x)) каждый раз, когда вы хотите проверить содержимое объекта, может оказаться довольно утомительным. Возможно, стоит иметь где-нибудь в вашей конфигурации глобальную функцию-оболочку:

function _G.dump(...)
    local objects = vim.tbl_map(vim.inspect, {...})
    print(unpack(objects))
end

Затем вы можете очень быстро проверить содержимое объекта в своем коде или из командной строки:

Кроме того, вы можете обнаружить, что встроенных функций Lua иногда не хватает по сравнению с тем, что вы найдете в других языках (например, os.clock() возвращает значение только в секундах, а не в миллисекундах). Обязательно посмотрите Neovim stdlib (и vim.fn, подробнее об этом позже), вероятно, в нем есть то, что вы ищете.

Использование Vimscript из Lua

vim.api.nvim_eval()

Эта функция оценивает строку выражения Vimscript и возвращает ее значение. Типы данных Vimscript автоматически преобразуются в типы Lua (и наоборот).

Это Lua-эквивалент функции luaeval() в Vimscript.

-- Типы данных конвертируются правильно
print(vim.api.nvim_eval('1 + 1')) -- 2
print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 }
print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) -- { baz = "qux", foo = "bar" }
print(vim.api.nvim_eval('v:true')) -- true
print(vim.api.nvim_eval('v:null')) -- nil

TODO: возможно ли, чтобы vim.api.nvim_eval() возвращала funcref?

Предостережения

В отличие от luaeval(), vim.api.nvim_eval() не предоставляет неявную переменную _A для передачи данных в выражение.

vim.api.nvim_exec()

Эта функция оценивает фрагмент кода Vimscript. Она принимает строку, содержащую исходный код для выполнения, и логическое значение, чтобы определить, должен ли вывод кода возвращаться функцией (вы можете сохранить вывод в переменной, для примера).

local result = vim.api.nvim_exec(
[[
let mytext = 'hello world'

function! MyFunction(text)
    echo a:text
endfunction

call MyFunction(mytext)
]],
true)

print(result) -- 'hello world'

TODO: в документации указано, что скриптовая область действия(s:) поддерживается, но запуск этого фрагмента с переменной скриптовой области действия вызывает ошибку. Почему?

vim.api.nvim_command()

Эта функция выполняет команду ex. Она принимает строку, содержащую команду для выполнения.

vim.api.nvim_command('new')
vim.api.nvim_command('wincmd H')
vim.api.nvim_command('set nonumber')
vim.api.nvim_command('%s/foo/bar/g')

Примечание: vim.cmd – более короткий alias для этой функции.

Советы

Поскольку вам нужно передавать строки этим функциям, вам часто приходится экранировать обратный слэш:

vim.cmd('%s/\Vfoo/bar/g')

Строковые литералы проще использовать, поскольку они не требуют экранирующих символов:

vim.cmd([[%s/Vfoo/bar/g]])

Управление опции vim

Использование функций API

Neovim предоставляет набор функций API для изменения опции или получения её текущего значения:

  • Глобальные опции:
    • vim.api.nvim_set_option()
    • vim.api.nvim_get_option()
  • Локальные опции буферов:
    • vim.api.nvim_buf_set_option()
    • vim.api.nvim_buf_get_option()
  • Локальные опции окон:
    • vim.api.nvim_win_set_option()
    • vim.api.nvim_win_get_option()

Они принимают строку, содержащую имя опции, которую нужно установить / получить, а также значение, которое вы хотите установить.

Логические параметры (например, (no)number) должны иметь значение true или false:

vim.api.nvim_set_option('smarttab', false)
print(vim.api.nvim_get_option('smarttab')) -- false

Неудивительно, что параметры строки должны быть строками:

vim.api.nvim_set_option('selection', 'exclusive')
print(vim.api.nvim_get_option('selection')) -- 'exclusive'

Числовые опции принимают число:

vim.api.nvim_set_option('updatetime', 3000)
print(vim.api.nvim_get_option('updatetime')) -- 3000

Локальные опции буффера и окна также нуждаются в номере буфера или номере окна (использование 0 установит/получит опцию для текущего буфера/окна)

vim.api.nvim_win_set_option(0, 'number', true)
vim.api.nvim_buf_set_option(10, 'shiftwidth', 4)
print(vim.api.nvim_win_get_option(0, 'number')) -- true
print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4

Использование мета-аксессоров

Если вы хотите установить параметры более “идиоматическим” способом, доступны несколько мета-аксессуаров. По сути, они обертывают вышеуказанные функции API и позволяют управлять параметрами, как если бы они были переменными:

  • vim.o.{option}: глобальные опции
  • vim.bo.{option}: локальные опции буффера
  • vim.wo.{option}: локальные опции окна
vim.o.smarttab = false
print(vim.o.smarttab) -- false

vim.bo.shiftwidth = 4
print(vim.bo.shiftwidth) -- 4

Вы можете указать номер для опций, локальных для буфера и для локального окна. Если номер не указан, используется текущий буфер / окно:

vim.bo[4].expandtab = true -- тоже самое что и vim.api.nvim_buf_set_option(4, 'expandtab', true)
vim.wo.number = true -- тоже самое что и vim.api.nvim_win_set_option(0, 'number', true)

Также смотрите:

  • :help lua-vim-internal-options

Предостережения

В Lua нет эквивалента команде :set, вы либо устанавливаете параметр глобально, либо локально.

Также смотрите:

  • :help :setglobal
  • :help global-local

Управление внутренними переменными vim

Использование функций API

Как и у параметров, внутренние переменные имеют собственный набор функций API:

  • Глобальные переменные (g:):
    • vim.api.nvim_set_var ()
    • vim.api.nvim_get_var ()
    • vim.api.nvim_del_var ()
  • Переменные буфера (b:):
    • vim.api.nvim_buf_set_var ()
    • vim.api.nvim_buf_get_var ()
    • vim.api.nvim_buf_del_var ()
  • Оконные переменные (w:):
    • vim.api.nvim_win_set_var ()
    • vim.api.nvim_win_get_var ()
    • vim.api.nvim_win_del_var ()
  • Переменные вкладки (t:):
    • vim.api.nvim_tabpage_set_var ()
    • vim.api.nvim_tabpage_get_var ()
    • vim.api.nvim_tabpage_del_var ()
  • Предопределенные переменные Vim (v:):
    • vim.api.nvim_set_vvar ()
    • vim.api.nvim_get_vvar ()

За исключением предопределенных переменных Vim, они также могут быть удалены (команда :unlet является эквивалентом в Vimscript). Локальные переменные (l:), скриптовые переменные (s:) и аргументы функции (a:) не могут быть изменены, поскольку они имеют смысл только в контексте Vimscript, Lua имеет свои собственные правила области видимости

Если вы не знакомы с тем, что делают эти переменные, :help internal-variables описывает их подробно.

Эти функции принимают строку, содержащую имя переменной для изменения/получения/удаления, а также значение, которое вы хотите установить.

vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 300 })
print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- { key1 = "value", key2 = 300 }
vim.api.nvim_del_var('some_global_variable')

Переменные, которые ограничены буфером, окном или вкладкой, также получают номер (использование 0 изменит/получит/удалит переменную для текущего буфера/окна/вкладки):

vim.api.nvim_win_set_var(0, 'some_window_variable', 2500)
vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world')
print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500
print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 'hello world'
vim.api.nvim_win_del_var(0, 'some_window_variable')
vim.api.nvim_buf_del_var(3, 'some_tabpage_variable')

Использование мета-аксессоров

Внутренними переменными можно управлять более интуитивно с помощью этих мета-аксессоров:

  • vim.g.{name}: глобальные переменные
  • vim.b.{name}: буферные переменные
  • vim.w.{name}: переменные окна
  • vim.t.{name}: переменные вкладки
  • vim.v.{name}: предопределенные переменные Vim
vim.g.some_global_variable = {
    key1 = 'value',
    key2 = 300
}

print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", key2 = 300 }

Чтобы удалить одну из этих переменных, просто присвойте ей nil:

vim.g.some_global_variable = nil

Предостережения

В отличие от мета-аксессоров опций, вы не можете указать число для переменных с областью буфера/окна/вкладки.

Кроме того, вы не можете добавлять/обновлять/удалять ключи из словаря, хранящегося в одной из этих переменных. Например, этот фрагмент кода Vimscript не работает:

let g:variable = {}
lua vim.g.variable.key = 'a'
echo g:variable
" {}

Это известная проблема:

  • Issue #12544

Вызов функций Vimscript

vim.call()

vim.call() вызывает функцию Vimscript. Это может быть встроенная функция Vim или пользовательская функция. Опять же, типы данных конвертируются из Lua в Vimscript и обратно.

Она принимает имя функции, за которым следуют аргументы, которые вы хотите передать этой функции:

print(vim.call('printf', 'Hello from %s', 'Lua'))

local reversed_list = vim.call('reverse', { 'a', 'b', 'c' })
print(vim.inspect(reversed_list)) -- { "c", "b", "a" }

local function print_stdout(chan_id, data, name)
    print(data[1])
end

vim.call('jobstart', 'ls', { on_stdout = print_stdout })

vim.call('my#autoload#function')

See also:

  • :help vim.call()

vim.fn.{function}()

vim.fn does the exact same thing as vim.call(), but looks more like a native Lua function call:

print(vim.fn.printf('Hello from %s', 'Lua'))

local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' })
print(vim.inspect(reversed_list)) -- { "c", "b", "a" }

local function print_stdout(chan_id, data, name)
    print(data[1])
end

vim.fn.jobstart('ls', { on_stdout = print_stdout })

Хэши # не являются допустимыми символами для идентификаторов в Lua, поэтому функции автозагрузки должны вызываться с таким синтаксисом:

vim.fn['my#autoload#function']()

Также смотрите:

  • :help vim.fn

Советы

Neovim имеет обширную библиотеку мощных встроенных функций, которые очень полезны для плагинов. Смотрите :help vim-function для списка в алфавитном порядке и :help function-list для списка функций, сгруппированных по темам.

Предостережения

Некоторые функции Vim, которые должны возвращать логическое значение 1 или 0. В Vimscript это не проблема, поскольку 1 истинно, а 0 ложно, что позволяет использовать такие конструкции:

if has('nvim')
    " do something...
endif

Однако в Lua ложными считаются только false и nil, числа всегда оцениваются как true, независимо от их значения. Вы должны явно проверить 1 или 0:

if vim.fn.has('nvim') == 1 then
    -- do something...
end

Определение сопоставлений клавиш

Neovim предоставляет список функций API для установки, получения и удаления сопоставлений:

  • Для глобальных сопоставлений:
    • vim.api.nvim_set_keymap()
    • vim.api.nvim_get_keymap()
    • vim.api.nvim_del_keymap()
  • Для локальных сопоставлений:
    • vim.api.nvim_buf_set_keymap()
    • vim.api.nvim_buf_get_keymap()
    • vim.api.nvim_buf_del_keymap()

Начнем с vim.api.nvim_set_keymap() и vim.api.nvim_buf_set_keymap()

Первым аргументом, переданным в функцию, является строка, содержащая имя режима, для которого сопоставление будет действовать:

Строчное значение Страница помощи Затронутые режимы Эквивалент Vimscript
'' (пустая строка) mapmode-nvo Normal, Visual, Select, Operator-pending :map
'n' mapmode-n Normal :nmap
'v' mapmode-v Visual and Select :vmap
's' mapmode-s Select :smap
'x' mapmode-x Visual :xmap
'o' mapmode-o Operator-pending :omap
'!' mapmode-ic Insert and Command-line :map!
'i' mapmode-i Insert :imap
'l' mapmode-l Insert, Command-line, Lang-Arg :lmap
'c' mapmode-c Command-line :cmap
't' mapmode-t Terminal :tmap

Второй аргумент – это строка, содержащая левую часть отображения (ключ или набор ключей, запускающих команду, определенную в сопоставлении). Пустая строка эквивалентна <Nop>, который отключает ключ.

Третий аргумент – это строка, содержащая правую часть сопоставления (команду для выполнения).

Последний аргумент – это таблица, содержащая логические параметры для сопоставления, как определено в :help :map-arguments (включая noremap и исключая buffer).

Сопоставления локальных буферов также принимают номер буфера в качестве первого аргумента (0 устанавливает сопоставление для текущего буфера).

vim.api.nvim_set_keymap('n', '<leader><Space>', ':set hlsearch!<CR>', { noremap = true, silent = true })
-- :nnoremap <silent> <leader><Space> :set hlsearch<CR>

vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : "ggcc"', { noremap = true, expr = true })
-- :noremap <buffer> <expr> cc line('.') == 1 ? 'cc' : 'ggcc'

vim.api.nvim_get_keymap() принимает строку, содержащую краткое имя режима, для которого вы хотите получить список сопоставлений (см. таблицу выше). Возвращаемое значение – это таблица, содержащая все глобальные сопоставления для режима.

print(vim.inspect(vim.api.nvim_get_keymap('n')))
-- :verbose nmap

vim.api.nvim_buf_get_keymap () принимает дополнительный номер буфера в качестве своего первого аргумента (0 получит сопоставления для текущего буфера)

print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i')))
-- :verbose imap <buffer>

vim.api.nvim_del_keymap() принимает режим и левую часть сопоставления.

vim.api.nvim_del_keymap('n', '<leader><Space>')
-- :nunmap <leader><Space>

Опять же, vim.api.nvim_buf_del_keymap () принимает номер буфера в качестве своего первого аргумента, где 0 представляет текущий буфер.

vim.api.nvim_buf_del_keymap(0, 'i', '<Tab>')
-- :iunmap <buffer> <Tab>

Определение пользовательских команд

В настоящее время в Lua нет интерфейса для создания пользовательских команд. Тем не менее, планы имеются:

  • Pull request #11613

В настоящее время вам, вероятно, лучше создавать команды в Vimscript.

Определение автокоманд

Augroup-ы и autcommand-ы еще не имеют интерфейса, но над ним работают:

  • Pull request #12378

А пока вы можете создавать автокоманды в Vimscript или использовать эту оболочку из norcalli/nvim_utils

Определение синтаксиса/подсветки

Синтаксический API все еще находится в стадии разработки. Вот пара указателей:

  • Issue #9876
  • tjdevries/colorbuddy.vim, библиотека для создания цветовых схем в Lua
  • :help lua-treesitter

Общие советы и рекомендации

Настройка линтеров/языковых серверов

Если вы используете линтеры и/или языковые серверы для диагностики и автозаполнения для проектов Lua, возможно, вам придется настроить для них параметры, специфичные для Neovim. Вот несколько рекомендуемых настроек для популярных инструментов:

luacheck

Вы можете заставить luacheck распознать глобал vim, поместив эту конфигурацию в ~/.luacheckrc (или $XDG_CONFIG_HOME/luacheck/.luacheckrc):

Языковой сервер Alloyed/lua-lsp использует luacheck для обеспечения линтинга и читает тот же файл.

Для получения дополнительной информации о том, как настроить luacheck, обратитесь к его документации

sumneko/lua-language-server

Пример конфигурации для sumneko/lua-language-server (в примере используется встроенный клиент LSP, но конфигурация для другого клиента LSP должна быть идентична):

require'lspconfig'.sumneko_lua.setup {
    settings = {
        Lua = {
            runtime = {
                -- Заставьте языковой сервер распознавать глобальные переменные LuaJIT, такие как `jit` и` bit`
                version = 'LuaJIT',
                - Настройте путь к lua
                path = vim.split(package.path, ';'),
            },
            diagnostics = {
                - Заставьте языковой сервер распознавать глобальную переменную `vim`
                globals = {'vim'},
            },
            workspace = {
                -- Сделать так, чтобы сервер знал о рантайм файлах Neovim
                library = {
                    [vim.fn.expand('$VIMRUNTIME/lua')] = true,
                    [vim.fn.expand('$VIMRUNTIME/lua/vim/lsp')] = true,
                },
            },
        },
    },
}

Для получения дополнительной информации о настройке sumneko/lua-language-server см. “Setting without VSCode”

coc.nvim

Источник автодополнения rafcamlet/coc-nvim-lua для coc.nvim предоставляет элементы автодополнения для библиотеки Neovim stdlib.

TODO:

  • Горячая перезагрузка модулей
  • vim.validate()?
  • Добавить материал о модульных тестах? Я знаю, что Neovim использует фреймворк busted, но я не знаю, как использовать его для плагинов.
  • Лучшие практики? Я не Lua мастер, поэтому не знаю
  • Как использовать пакеты LuaRocks (wbthomason/packer.nvim?)

Разное

vim.loop

vim.loop– это модуль, который предоставляет API LibUV . Некоторые ресурсы:

  • Official documentation for LibUV
  • Luv documentation
  • teukka.tech – Using LibUV in Neovim

Также смотрите:

  • :help vim.loop

vim.lsp

vim.lsp – это модуль, который управляет встроенным клиентом LSP. Репозиторий neovim/nvim-lspconfig содержит конфигурации по умолчанию для популярных языковых серверов.

Поведение клиента можно настроить с помощью обработчиков “lsp-handlers”. Для дополнительной информации:

  • :help lsp-handler
  • neovim/neovim#12655
  • How to migrate from diagnostic-nvim

Вы также можете взглянуть на плагины, построенные вокруг клиента LSP:

  • nvim-lua/completion-nvim
  • RishabhRD/nvim-lsputils

Также смотрите:

  • :help lsp

vim.treesitter

vim.treesitter – это модуль, который управляет интеграцией библиотеки Tree-sitter в Neovim. Если вы хотите узнать больше о Tree-sitter, вам может быть интересна эта презентация (38:37).

Организация nvim-treeitter размещает различные плагины, использующие преимущества библиотеки.

See also:

  • :help lua-treesitter

Транспайлеры

Одним из преимуществ использования Lua является то, что вам фактически не нужно писать код Lua! Для этого языка доступно множество транспайлеров.

  • Moonscript

Вероятно, один из самых известных транспилеров для Lua. Добавляет множество удобных функций, таких как классы, списковое включение или функциональные литералы. Плагин svermeulen/nvim-moonmaker позволяет писать плагины и настройку Neovim непосредственно в Moonscript.

  • Fennel

Lisp, который компилируется в Lua. Вы можете написать конфигурацию и плагины для Neovim в Fennel с помощью плагина Olical/aniseed. Кроме того, плагин Olical/conjure предоставляет интерактивную среду разработки, которая поддерживает Fennel (среди других языков).

Другие интересные проекты:

  • TypeScriptToLua/TypeScriptToLua
  • teal-language/tl
  • Haxe
  • SwadicalRag/wasm2lua
  • hengestone/lua-languages

2.15. Скрипты Lua

1. Введение

Double Commander может выполнять скрипты Lua с помощью команды cm_ExecuteScript.
Параметры скриптов должны передаваться как есть, без экранирования (без кавычек или “”), для этого необходимо использовать переменную %”0: например, %"0%p0 для файла под курсором вместо %p0, %"0%D для текущего каталога вместо %D и так далее.
Для получения списка всех выделенных файлов мы можем использовать %LU или внутренние команды cm_SaveSelectionToFile или cm_CopyFullNamesToClip.

Также на языке Lua можно писать информационные плагины, примеры можно найти в папке программы (plugins/wdx/scripts).
В Вики есть страница, посвящённая написанию плагинов.
Ограничения: поддерживаются только следующие типы данных

  • ft_numeric_32 – 32-битное целое число со знаком;
  • ft_numeric_64 – 64-битное целое число со знаком;
  • ft_numeric_floating – число с плавающей запятой;
  • ft_boolean – логический (булев) тип: true или false;
  • ft_multiplechoice – значение, допускающее ограниченное количество вариантов выбора;
  • ft_string – текстовая строка (используйте UTF-8);
  • ft_fulltext – полный текст (многострочный текст), используется только для поиска с помощью плагинов;
  • ft_datetime – для даты/времени: возвращаемая дата будет сконвертирована в отформатированную строку даты и времени (значение зависит от ваших региональных настроек).

Примечание: При сохранении скриптов используйте кодировку UTF-8 без BOM.

Более подробную информацию о языке программирования Lua можно найти на официальном веб-сайте Lua.

(наверх)

2. Необходимая DLL

Чтобы использовать скрипты Lua, нам требуется интерпретатор Lua, Double Commander поддерживает версии 5.1 – 5.4.

По умолчанию DC ищет файл с именем lua5.1.dll (Windows), liblua5.1.so.0 (Unix или GNU/Linux) или liblua5.1.dylib (macOS(*)) в своём каталоге и в системном. Мы можем изменить имя файла (и путь) в параметре Библиотека Lua.

Мы можем использовать DLL-файл проекта LuaJIT.
LuaJIT сочетает в себе высокоскоростной интерпретатор, написанный на ассемблере, и JIT-компилятор. Также мы получаем библиотеку FFI: с её помощью в скриптах можно будет вызывать внешние функции C и использовать структуры данных C.

Дистрибутивы DC для Windows включают в себя DLL-файл Lua (в DC 0.9.7 и новее из проекта LuaJIT), в иных случаях мы можем найти и установить его с помощью менеджера пакетов или скомпилировать. Если используем 64-битную версию DC, то DLL-файл также должен быть 64-битным.

(наверх)

3. Библиотеки функций Double Commander

Double Commander предлагает несколько библиотек функций для скриптов Lua, список представлен ниже.

Список библиотек
Библиотека Имя функции Краткое описание

Double Commander

DC Специфические функции Double Commander

System

SysUtils Различные системные функции

Clipboard

Clipbrd Различные функции для работы с буфером обмена

Dialogs

Dialogs Взаимодействие с пользователем

UTF-8

LazUtf8 Строковые функции для работы с UTF-8

OS

OS Функции, связанные с операционной системой

(наверх)

3.1. Библиотека DC

Эта библиотека содержит специфические функции Double Commander, все функции представлены в таблице DC.

Библиотека DC
Функция Описание

DC.LogWrite

DC.LogWrite(Message, MsgType, bForce, bLogFile)

Пишет сообщение в окно протокола.

Описание:

  • Message : Текст сообщения.
  • MsgType : Тип сообщения: 0 – информационное, 1 – успешная операция, 2 – ошибка.
  • bForce : Логическое (булево) значение, если true, то показать окно протокола (если оно скрыто).
  • bLogFile : Логическое (булево) значение, если true, то сообщение будет записано и в файл протокола.

DC.CurrentPanel

iPanel = DC.CurrentPanel()

Получить активную панель: возвращает 0, если активна левая панель, или 1, если правая.

DC.CurrentPanel(iPanel)

Сделать активной: левую панель, если iPanel равно 0, или правую, если равно 1.

DC.ExecuteCommand

DC.ExecuteCommand(Command, Param1, Param2,…,ParamX)

Вызывает внутреннюю команду Double Commander Command с параметрами Param1..ParamX.

Мы можем подставить столько Param…, сколько поддерживает команда Command.

Примечание: Скрипты работают в основном потоке Double Commander, поэтому иногда последовательное выполнение команд для навигации может не сработать (например, большие каталоги, медленный диск), в этом случае попробуйте отключить Загружать список файлов в отдельном потоке в настройках.

(наверх)

3.1.1. Пример с DC.ExecuteCommand

В этом примере мы написали простой скрипт, который сделает следующее:

  1. перенесёт фокус на правую панель
  2. закроет все открытые вкладки
  3. перейдёт в указанную папку
  4. перенесёт фокус на левую панель
  5. закроет все открытые вкладки
  6. перейдёт в указанный каталог
  7. откроет новую вкладку
  8. перейдёт в указанный каталог
-- 1. Перенести фокус на правую панель.
DC.ExecuteCommand("cm_FocusSwap", "side=right")

-- 2. Закрыть все вкладки.
DC.ExecuteCommand("cm_CloseAllTabs")

-- 3. Перейти в указанный каталог.
DC.ExecuteCommand("cm_ChangeDir", "E:\FakeKey\Documents\Music")

-- 4. Перенести фокус на левую панель.
DC.ExecuteCommand("cm_FocusSwap", "side=left")

-- 5. Закрыть все вкладки.
DC.ExecuteCommand("cm_CloseAllTabs")

-- 6. Перейти в указанный каталог.
DC.ExecuteCommand("cm_ChangeDir", "C:\Users\Public\Music")

-- 7. Открыть новую вкладку.
DC.ExecuteCommand("cm_NewTab")

-- 8. Перейти в указанный каталог.
DC.ExecuteCommand("cm_ChangeDir", "E:\VirtualMachines\ShareFolder")

Для выполнения нашего скрипта мы можем создать кнопку на панели инструментов с внутренней командой cm_ExecuteScript.

Предположим, наш скрипт E:scriptsluamusic.lua, мы можем настроить эту кнопку следующим образом:

Вызов скрипта Lua кнопкой панели инструментов

Кроме того, для редактирования наших скриптов мы можем использовать встроенный редактор Double Commander.

Если файл имеет расширение .lua, то он будет распознан редактором и открыт с подсветкой синтаксиса, специфичного для языка Lua:

Подсветка синтаксиса Lua во встроенном редакторе

(наверх)

3.2. Библиотека System

Эта библиотека содержит различные системные функции, все они представлены в таблице SysUtils.

Библиотека System
Функция Описание

SysUtils.Sleep

SysUtils.Sleep(Milliseconds)

Приостанавливает выполнение скрипта на указанное количество миллисекунд (Milliseconds), выполнение сценария будет продолжено после истечения указанного времени.

SysUtils.GetTickCount

SysUtils.GetTickCount()

Возвращает количество интервалов времени (тиков) с момента старта системы. Это полезно для измерения времени, но не следует делать каких-либо предположений относительно количества времени в интервале между тиками.

SysUtils.FileExists

bFlagExists = SysUtils.FileExists(FileName)

Проверяет, существует ли в файловой системе определённый файл.

FileExists возвращает true, если файл с именем FileName существует на диске, и false в противном случае.

SysUtils.DirectoryExists

bFlagExists = SysUtils.DirectoryExists(Directory)

Проверяет существование Directory в файловой системе и что это действительно каталог.

Если это так, то функция возвращает true, иначе возвращает false.

SysUtils.FileGetAttr

Attr = SysUtils.FileGetAttr(FileName)

Возвращает в Attr атрибуты файла FileName.

Подробное описание возвращаемого значения смотрите здесь.

SysUtils.FindFirst

Handle, FindData = SysUtils.FindFirst(Path)

Ищет файлы, совпадающие с Path (можно использовать маски).

Если файл не найден, Handle будет равно nil.

В случае успеха функция вернёт дескриптор поиска Handle для последующих вызовов SysUtils.FindNext и поиска других совпадений с паттерном.

Таблица FindData содержит информацию о найденном файле или каталоге.

Поля таблицы FindData:

  • Name : Имя файла (без пути).
  • Attr : Атрибуты файла (подробнее смотрите здесь).
  • Size : Размер файла в байтах.
  • Time : Отметка времени файла (в формате POSIX, так называемое Unix-время: количество секунд, прошедших с 1 января 1970 г.)

SysUtils.FindNext

Result, FindData = SysUtils.FindNext(Handle)

Находит следующее вхождение поиска, инициированного FindFirst, Handle – дескриптор поиска, возвращённый функцией FindFirst.

В случае успеха функция вернёт Result не равный nil и таблицу FindData, содержащую информацию о найденном файле или каталоге.

Замечание: За последним вызовом SysUtils.FindNext всегда должен следовать вызов SysUtils.FindClose с тем же Handle. Несоблюдение этого приведёт к утечке памяти.

SysUtils.FindClose

SysUtils.FindClose(Handle)

Завершает серию вызовов SysUtils.FindFirst/SysUtils.FindNext и освобождает использованную память.

Вызов этой функции абсолютно необходим, иначе могут возникнуть большие утечки памяти.

SysUtils.CreateDirectory

bResult = SysUtils.CreateDirectory(Directory)

Создаёт цепочку каталогов, Directory – полный путь каталога.

Возвращает true, если Directory уже существует или был успешно создан, или false, если не удалось создать какую-либо часть пути.

SysUtils.CreateHardLink

bResult = SysUtils.CreateHardLink(Path, LinkName)

Создаёт жёсткую ссылку LinkName на файл Path.

Возвращает true в случае успеха, иначе возвращает false.

SysUtils.CreateSymbolicLink

bResult = SysUtils.CreateSymbolicLink(Path, LinkName)

Создаёт символьную ссылку LinkName на файл Path.

Возвращает true в случае успеха, иначе возвращает false.

SysUtils.ReadSymbolicLink

sTarget = SysUtils.ReadSymbolicLink(LinkName, Recursive)

Читает имя файла, на который указывает символьная ссылка LinkName.

Если Recursive равно true и ссылка указывает на ссылку, то она разрешается рекурсивно до тех пор, пока не будет найдено допустимое имя файла, не являющееся ссылкой.

Возвращает путь, на который указывает символьная ссылка LinkName, или пустую строку, если ссылка недействительна или файл, на который она указывает, не существует и значение Recursive равно true.

SysUtils.ExtractFileName

sName = SysUtils.ExtractFileName(FileName)

Возвращает имя файла из полного (имя+путь) имени файла.

Имя файла содержит все символы после последнего символа разделителя каталогов (“/” или “”) или буквы диска.

SysUtils.ExtractFilePath

sPath = SysUtils.ExtractFilePath(FileName)

Возвращает путь из полного имени файла (включая букву диска).

Путь содержит все символы до последнего символа разделителя каталогов (“/” или “”), включая сам разделитель каталогов.

SysUtils.ExtractFileDir

sDir = SysUtils.ExtractFileDir(FileName)

Возвращает только каталог из FileName, включая букву диска.

Результат НЕ содержит разделитель каталогов в конце, в отличие от SysUtils.ExtractFilePath.

SysUtils.ExtractFileDrive

sDrive = SysUtils.ExtractFileDrive(FileName)

Возвращает диск из полного имени файла.

Обратите внимание, некоторые операционные системы не поддерживают буквы дисков.

SysUtils.ExtractFileExt

sExt = SysUtils.ExtractFileExt(FileName)

Возвращает расширение файла (все символы после последней точки, включая сам символ “.”).

SysUtils.GetAbsolutePath

sName = SysUtils.GetAbsolutePath(FileName, BaseDirectory)

Возвращает абсолютный (полный) путь к файлу:

  • FileName : Имя файла с относительным путём.
  • BaseDirectory : Каталог, который использовался как базовый каталог для FileName.

SysUtils.GetRelativePath

sName = SysUtils.GetRelativePath(FileName, BaseDirectory)

Возвращает имя файла относительно указанного каталога:

  • FileName : Полное (абсолютное) имя файла.
  • BaseDirectory : Каталог, который будет использоваться как базовый каталог для FileName.

Если FileName и BaseDirectory содержат одно и то же значение, функция вернёт пустую строку (“”).

SysUtils.MatchesMask

bResult = SysUtils.MatchesMask(FileName, Mask, MaskOptions)

Возвращает true, если FileName совпадает с переданной маской Mask.

MaskOptions (необязательный параметр, по умолчанию 0) задаётся как сумма следующих значений:

Значение Описание

1

с учётом регистра

2

игнорировать акценты и лигатуры

4

фильтр в стиле Windows: “*.*” также совпадает с файлами без расширения и т.д.

8

включить поддержку пиньинь (будет использоваться файл pinyin.tbl)

SysUtils.MatchesMaskList

bResult = SysUtils.MatchesMaskList(FileName, MaskList, Separator, MaskOptions)

Возвращает true, если FileName совпадает с хотя бы одной из переданных масок MaskList, разделённых Separator (по умолчанию “;”).

Separator и MaskOptions (см. выше) – необязательные параметры.

SysUtils.PathDelim

SysUtils.PathDelim

Символ, используемый в текущей операционной системе для разделения имён каталогов в полном имени файла.

В системах Unix/Linux разделителем каталогов будет “/” и “” в Windows.

(наверх)

3.2.1. Описание возвращаемого значения SysUtils.FileGetAttr

FileGetAttr возвращает атрибуты FileName в виде ИЛИ-совокупности следующих констант:

Константы, используемые в возвращаемом значении SysUtils.FileGetAttr
Значение Описание

0x00000001
faReadOnly

Файл только для чтения.

0x00000002
faHidden

Скрытый файл.
В Unix/Linux это значит, что имя файла начинается с точки.

0x00000004
faSysFile

Системный файл.
В Unix/Linux это может быть символьное или блочное физическое устройство, именованный канал (FIFO).

0x00000008
faVolumeId

Метка тома (означает, что файл содержит идентификатор (ID) тома).
Только для DOS/Windows 9x на обычной файловой системе FAT (не VFAT или FAT32).

0x00000010
faDirectory

Каталог.

0x00000020
faArchive

Архивный.
Не используется в Unix/Linux.

0x00000400
faSymLink

Символьная ссылка.
Примечание: В случае ошибки функция возвращает -1.

Смотрите пример в следующей секции.

(наверх)

3.2.2. Пример с SysUtils.FileGetAttr

Пример скрипта ниже использует SysUtils.FileGetAttr.

Если параметр окажется каталогом, то скрипт откроет его в новой вкладке активной панели и переключится на неё.

local params = {...}
local myfileattr

if #params == 1 then -- Мы получили один параметр?
  myfileattr = SysUtils.FileGetAttr(params[1])
  if myfileattr > 0 then -- Получили значение атрибута?
    if math.floor(myfileattr / 0x00000010) % 2 ~= 0 then
      -- 0x00000010 присутствует? Тогда это каталог.
      DC.ExecuteCommand("cm_NewTab")
      DC.ExecuteCommand("cm_ChangeDir", params[1])
    end
  end
end

В приведённом выше примере params[1] является первым параметром, переданным скрипту.

При использовании внутренней команды cm_ExecuteScript это будет первый параметр, переданный после имени файла скрипта.

Итак, в нашем примере мы можем создать на панели инструментов кнопку, как показано ниже:

Параметр с cm_ExecuteScript

В этом примере скрипту будет передан параметр %”0%p: имя выделенного в активной панели файла или папки, без кавычек.

(наверх)

3.2.3. Пример использования FindFirst, FindNext и FindClose

В следующем примере мы просканируем содержимое каталога, переданного первым параметром, и сохраним полученные данные в текстовый файл с именем, переданным вторым параметром.

Это даст нам хорошее представление об использовании FindFirst, FindNext и FindClose.

local params = {...}

if #params == 2 then -- У нас есть два параметра?
  local Result = nil
  local OutputFile = nil

  OutputFile = io.output(params[2])

  local Handle,FindData = SysUtils.FindFirst(params[1] .. "\*")
  if Handle ~= nil then
    repeat
      io.write(FindData.Name .. "r")
      io.write(FindData.Size .. "r")
      io.write("---------------r")

      Result,FindData = SysUtils.FindNext(Handle)
    until Result == nil

    SysUtils.FindClose(Handle)
    io.close(OutputFile)
  end
end

В приведённом выше примере нам нужно передать скрипту два параметра:

  1. params[1] – каталог, содержимое которого мы хотим получить
  2. params[2] – имя файла для сохранения результата работы скрипта

Настраиваем кнопку на панели инструментов с внутренней командой cm_ExecuteScript и передаём параметрами всё необходимое:

Параметр с cm_ExecuteScript

В этом примере скрипту в качестве первого параметра будет передано %”0%Ds: имя каталога активной панели, без кавычек.

(наверх)

3.3. Библиотека Clipboard

Double Commander предоставляет скриптам Lua библиотеку функций для работы с буфером обмена.

Библиотека Clipboard
Функция Описание

Clipbrd.Clear

Clipbrd.Clear()

Очищает содержимое буфера обмена.

Clipbrd.GetAsText

StringVar = Clipbrd.GetAsText()

Получает содержимое буфера обмена как строку StringVar.

Clipbrd.SetAsText

Clipbrd.SetAsText(StringVar)

Помещает в буфер обмена строку текста StringVar.

Clipbrd.SetAsHtml

Clipbrd.SetAsHtml(Html)

Добавляет в буфер обмена текст Html в формате HTML (формат буфера обмена CF_HTML).

Содержимое может быть вставлено в приложения, поддерживающие этот формат буфера обмена, такие как MS Word, LO Writer и другие.

Правильным будет сохранять данные с помощью и Clipbrd.SetAsText, и Clipbrd.SetAsHtml: приложение будет использовать тот формат, который поддерживает.

Например, у нас может быть следующее:

  • Clipbrd.SetAsText("Добро пожаловать в Double Commander!")
  • Clipbrd.SetAsHtml("Добро пожаловать в <b>Double Commander</b>!")

Если мы запустим Блокнот и попытаемся вставить текст из буфера обмена, то будет вставлен текст, скопированный с помощью Clipbrd.SetAsText. Но если мы перейдём к Microsoft Word, то будет вставлена строка с выделенным жирным шрифтом Double Commander, потому что Microsoft Word распознаёт и поддерживает этот формат буфера обмена.

(наверх)

3.3.1. Пример работы с буфером обмена

В следующем примере используются три функции, связанные с буфером обмена: Clear, GetAsText и SetAsText.

Это относительно большой скрипт, но было бы неплохо собрать вместе несколько функций, с которыми мы познакомились ранее.

Предполагается, что в нашей активной панели открыт каталог с большим количеством текстовых файлов.

Также предполагается, что в настоящее время в буфере обмена одно слово и что скрипт в качестве единственного параметра получит текущий каталог активной панели.

Скрипт будет сканировать папку, читать содержимое файлов, один за другим, и искать слово из буфера обмена.

Затем имена файлов, которые содержат это словом, будут скопированы в буфер обмена.

Далее скрипт вызовет внутреннюю команду cm_LoadSelectionFromClip и все эти файлы будут выделены.

Кроме того, в конце вернём обратно в буфер обмена слово, которое мы искали.

local params = {...}
local Result = nil
local myfileattr
local bFound = false
local sCompleteFilename = ""
local InputFile = nil
local line = ""
local iPosS
local iPosE
local sFileToSelect = ""
local sSearchString = ""

if #params == 1 then -- Мы получили наш параметр?
  sSearchString = Clipbrd.GetAsText() -- Получаем выражение для поиска.
  Clipbrd.Clear() -- Очищаем буфер обмена.
  DC.ExecuteCommand("cm_MarkUnmarkAll") -- Убедимся, что ничего не выделено.

  -- Начинаем сканировать все файлы нашего каталога один за другим.
  local Handle,FindData = SysUtils.FindFirst(params[1] .. "\*")
  if Handle ~= nil then
    repeat
      sCompleteFilename = params[1] .. "\" .. FindData.Name
      myfileattr = SysUtils.FileGetAttr(sCompleteFilename)
      if myfileattr > 0 then -- Получили значение атрибута?
        -- Нам нужен файл, не каталог!
        if math.floor(myfileattr / 0x00000010) % 2 == 0 then

          -- Начинаем читать файл построчно, до конца файла ИЛИ до совпадения.
          InputFile = io.open(sCompleteFilename, "r")
          bFound = false

          while bFound == false do
            line = InputFile:read()
            if line == nil then break end
            iPosS, iPosE = string.find(line, sSearchString)
            if iPosS ~= nil then bFound = true end
          end

          if bFound == true then
            sFileToSelect = sFileToSelect .. FindData.Name .. "n"
          end

          io.close(InputFile)
        end
      end
      Result,FindData = SysUtils.FindNext(Handle)
    until Result == nil

    SysUtils.FindClose(Handle)
  end

  -- Если что-то нашли, то выделяем!
  if sFileToSelect ~= "" then
    Clipbrd.SetAsText(sFileToSelect)
    DC.ExecuteCommand("cm_LoadSelectionFromClip")
  end

  Clipbrd.SetAsText(sSearchString) -- Восстанавливаем содержимое буфера обмена.
end

(наверх)

3.4. Библиотека Dialogs

Эта библиотека позволяет нашим скриптам взаимодействовать с пользователем, показывая сообщения, выдавая запросы и т.д.

Библиотека Dialogs
Функция Описание

Dialogs.MessageBox

ButPressed = Dialogs.MessageBox(Message, Title, ButFlags)

Показывает окно сообщения, функция вернёт нажатую пользователем кнопку.

Описание:

  • Message : Сообщение окна.
  • Title : Текст в заголовке окна.
  • ButFlags : Сумма констант, задающих отображаемые кнопки, стиль окна и кнопку по умолчанию. Смотрите ниже таблицы с кнопками, стилями и кнопкой по умолчанию.
  • ButPressed : Возвращаемое значение, указывающее нажатую кнопку (смотрите эту таблицу).

Dialogs.InputQuery

bAck, sAnswer = Dialogs.InputQuery(Title, Msg, bMask, sDefault)

Показывает диалоговое окно с полем ввода текста.

Описание:

  • Title : Текст в заголовке окна.
  • Msg : Сообщение окна.
  • bMask : Логическое (булево) значение, если true, то вводимый текст будет скрываться “звёздочками”.
  • sDefault : Текст, который будет отображаться в строке ввода при появлении окна.
  • bAck : Возвращаемое логическое (булево) значение, указывающее, ввёл ли что-то пользователь или нет.
  • sAnswer : Возвращаемая строка, если пользователь что-то ввёл, а затем нажал ОК.

Dialogs.InputListBox

sAnswer = Dialogs.InputListBox(Title, Msg, Items, sDefault)

Показывает диалоговое окно с возможностью выбора из списка элементов.

Описание:

  • Title : Текст в заголовке окна.
  • Msg : Сообщение окна.
  • Items : Таблица Lua, каждый элемент таблицы должен быть строкой.
  • sDefault : Пункт списка, выделенный по умолчанию.
  • sAnswer : Возвращаемая строка с выбранным пунктом или nil в случае отмены.

(наверх)

3.4.1. Кнопки Dialogs.MessageBox

Кнопки, отображаемые в окне Dialogs.MessageBox, задаются одним из следующих значений:

Константы для кнопок в Dialogs.MessageBox
Значение константы Отображаемые кнопки, слева направо

0x0000
MB_OK

Кнопка OK

0x0001
MB_OKCANCEL

Кнопка OK
Кнопка ОТМЕНА

0x0002
MB_ABORTRETRYIGNORE

Кнопка ПРЕРВАТЬ
Кнопка ПОВТОР
Кнопка ПРОПУСТИТЬ

0x0003
MB_YESNOCANCEL

Кнопка ДА
Кнопка НЕТ
Кнопка ОТМЕНА

0x0004
MB_YESNO

Кнопка ДА
Кнопка НЕТ

0x0005
MB_RETRYCANCEL

Кнопка ПОВТОР
Кнопка ОТМЕНА

(наверх)

3.4.2. Стиль окна Dialogs.MessageBox

Стиль окна Dialogs.MessageBox задаётся одним из следующих значений:

Константы, задающие значок и стиль окна Dialogs.MessageBox
Значение константы Стиль окна

0x0040
MB_ICONINFORMATION

Значок ИНФОРМАЦИЯ Информационное окно

0x0030
MB_ICONWARNING

Значок ПРЕДУПРЕЖДЕНИЕ Окно предупреждения

0x0020
MB_ICONQUESTION

Значок ВОПРОС Окно подтверждения

0x0010
MB_ICONERROR

Значок ОШИБКА Окно ошибки

(наверх)

3.4.3. Кнопка по умолчанию в Dialogs.MessageBox

Кнопка по умолчанию (активная) в Dialogs.MessageBox задаётся одним из следующих значений:

Константы, задающие кнопку по умолчанию в Dialogs.MessageBox
Значение константы Кнопка по умолчанию

0x0000
MB_DEFBUTTON1

Первая кнопка слева

0x0100
MB_DEFBUTTON2

Вторая кнопка слева

0x0200
MB_DEFBUTTON3

Третья кнопка слева

(наверх)

3.4.4. Возвращаемое значение Dialogs.MessageBox

Число, возвращаемое функцией Dialogs.MessageBox, указывает на кнопку, которую нажал пользователь, и может быть одним из следующих:

Возвращаемое значение Dialogs.MessageBox
Значение константы Нажатая кнопка

0x0000
mrNone

Кнопка не нажата

0x0001
mrOK

Результат: OK

0x0002
mrCancel

Результат: ОТМЕНА

0x0003
mrAbort

Результат: ПРЕРВАТЬ

0x0004
mrRetry

Результат: ПОВТОР

0x0005
mrIgnore

Результат: ПРОПУСТИТЬ

0x0006
mrYes

Результат: ДА

0x0007
mrNo

Результат: НЕТ

Примечание: Если закрыть окно, нажав крестик “x” в углу окна или клавишу Esc, то функция вернёт 0x0002, как нажатие кнопки Отмена.

(наверх)

3.4.5. Пример использования Dialogs.MessageBox

Маленький скрипт, использующий Dialogs.MessageBox:

-- Отображаемые кнопки
MB_OK = 0x0000
MB_OKCANCEL = 0x0001
MB_ABORTRETRYIGNORE = 0x0002
MB_YESNOCANCEL = 0x0003
MB_YESNO = 0x0004
MB_RETRYCANCEL = 0x0005

-- Стиль окна
MB_ICONINFORMATION = 0x0040
MB_ICONWARNING = 0x0030
MB_ICONQUESTION = 0x0020
MB_ICONERROR = 0x0010

-- Кнопка по умолчанию
MB_DEFBUTTON1 = 0x0000
MB_DEFBUTTON2 = 0x0100
MB_DEFBUTTON3 = 0x0200

-- Возвращаемое значение
mrNone = 0x0000
mrOK = 0x0001
mrCancel = 0x0002
mrAbort = 0x0003
mrRetry = 0x0004
mrIgnore = 0x0005
mrYes = 0x0006
mrNo = 0x0007

ButFlags = MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2
ButPressed = Dialogs.MessageBox("Хотите завершить?", "Вопрос", ButFlags)

if ButPressed == mrYes then
  DC.ExecuteCommand("cm_Exit")
end

Пример использования Dialogs.MessageBox

(наверх)

3.4.6. Пример использования Dialogs.InputQuery

Маленький скрипт, использующий Dialogs.InputQuery:

bAck, sAnswer = Dialogs.InputQuery("Идентификация", "Введите ваше имя:", false, "Иван")

if bAck == true then
  Dialogs.MessageBox("Привет, " .. sAnswer .. "!", "Добро пожаловать!", 0x0040)
end

Пример использования Dialogs.InputQuery

(наверх)

3.5. Библиотека UTF-8

Эта библиотека обеспечивает базовую поддержку кодировки UTF-8.

Все функции представлены в таблице LazUtf8.

Библиотека UTF-8
Функция Описание

LazUtf8.Pos

Result = LazUtf8.Pos(SearchText, SourceText, Offset)

Поиск подстроки в строке, начиная с определённой позиции. Поиск чувствителен к регистру.

Возвращает позицию первого вхождения подстроки SearchText в строке SourceText, поиск начинается с позиции Offset (по умолчанию 1).

Если в SourceText не найдено совпадение с SearchText после заданного Offset, то функция возвращает ноль.

LazUtf8.Copy

Result = LazUtf8.Copy(Source, Index, Count)

Копирует (извлекает) часть строки.

Функция возвращает Count символов из строки Source, начиная с позиции Index.

Если Count больше длины строки Source, то результат усекается. Если Index больше длины строки Source, то возвращается пустая строка.

LazUtf8.Length

Result = LazUtf8.Length(String)

Возвращает количество символов в строке с учётом кодировки UTF-8.

LazUtf8.UpperCase

Result = LazUtf8.UpperCase(String)

Возвращает строку, в которой все буквы в нижнем регистре (строчные) заменены на буквы в верхнем регистре (прописные или заглавные).

LazUtf8.LowerCase

Result = LazUtf8.LowerCase(String)

Возвращает строку, в которой все буквы в верхнем регистре (прописные или заглавные) заменены на буквы в нижнем регистре (строчные).

LazUtf8.ConvertEncoding

Result = LazUtf8.ConvertEncoding(String, FromEnc, ToEnc)

Конвертирует кодировку String из FromEnc в ToEnc.

Список поддерживаемых значений кодировок:

  • Системная кодировка по умолчанию (зависит от языковых стандартов системы): “default”.
  • Кодировка ANSI (Windows) по умолчанию (зависит от языковых стандартов системы): “ansi”.
  • Кодировка OEM (DOS) по умолчанию (зависит от языковых стандартов системы): “oem”.
  • Юникод: “utf8”, “utf8bom”, “ucs2le”, “ucs2be”.
  • ANSI (Windows): “cp1250”, “cp1251”, “cp1252”, “cp1253”, “cp1254”, “cp1255”, “cp1256”, “cp1257”, “cp1258”.
  • OEM (DOS): “cp437”, “cp850”, “cp852”, “cp866”, “cp874”, “cp932”, “cp936”, “cp949”, “cp950”.
  • ISO 8859: “iso88591”, “iso88592”, “iso885915”.
  • Другие: “macintosh”, “koi8”.

Специальные значения кодировок (примеры).

В Windows (английкий или русский языки):

  • “default” – cp1252 или cp1251
  • “ansi” – cp1252 или cp1251
  • “oem” – cp850 или cp866

В Linux (английкий или русский языки):

  • “default” – utf8
  • “ansi” – cp1252 или cp1251
  • “oem” – cp850 или cp866

(наверх)

3.6. Библиотека OS

Эта библиотека содержит функции, связанные с операционной системой, в которой запущен Double Commander.

Список доступных функций:

Библиотека OS
Функция Описание

os.execute

ResultCode = os.execute(Command)

Выполнить Command, аналогично введённой в командной строке, будет возвращён код завершения.

Command может быть:

  • Команда терминала, например, os.execute("dir > all.txt")
  • Исполняемый файл, например, os.execute("C:\Windows\System32\calc.exe")
  • Исполняемый файл с параметрами:
    os.execute("C:\Utils\fsum.exe -md5 test.bin > md5.txt")

os.tmpname

TempFileName = os.tmpname()

Возвращает строку с именем файла, который может быть использован в качестве временного файла.

os.remove

bResult, ErrorStr, ErrorNum = os.remove(FileName)

Удалить файл с именем FileName.

Если удалось, функция вернёт true.

Если не удалось, функция вернёт:

  1. nil как индикатор неудачи
  2. ErrorStr с описанием ошибки
  3. ErrorNum в виде кода ошибки (число)

os.rename

bResult, ErrorStr, ErrorNum = os.rename(OldName, NewName)

Переименовать файл OldName в NewName.

Если удалось, функция вернёт true.

Если не удалось, функция вернёт:

  1. nil как индикатор неудачи
  2. ErrorStr с описанием ошибки
  3. ErrorNum в виде кода ошибки (число)

os.getenv

Value = os.getenv(VariableName)

Получить в Value значение переменной окружения VariableName.
Если переменная не существует, то функция вернёт nil.

os.setenv

os.setenv(VariableName, Value)

Добавить или изменить переменную окружения VariableName. В случае ошибки функция возвращает -1.

os.unsetenv

os.unsetenv(VariableName)

Удалить переменную окружения VariableName. В случае ошибки функция возвращает -1.

(наверх)

Добавить комментарий