Ich kann mich erinnern, dass wir vor langer Zeit festgestellt hatten, dass NPP ein nettes Feature besitzt:
- Rechteckige Markierung (also Cursormarkierung in einer Spalte über mehrere Zeilen, <Shift+Alt+Arrow up/down>)
- Aufruf Funktion
- Eintragen Startwert und Schrittweite
- Ausfüllen an allen Cursorpositionen
EDIT v 0.3
- Einrückungsposition der Arrayvariable wird übernommen
- Dialogsprache (Standard EN u. GER, Erkennung anhand der "locale.properties"), kann auf weitere Sprachen ergänzt werden
- Fehler bei falschen oder ungültigen Ubound-Werten beseitigt
EDIT v 0.2
Der Funktionsumfang wurde nun erweitert, die Operationen werden anhand der Markierung vorgenommen (ein Hotkey für alles) .
- Eintragen von Index mit Auswahl von Start und Schrittweite bei Rechteckmarkierung (s.o.)
- Erstellen von statischen Zuweisungen für 1D/2D-Arrays mit indexwerten anhand der Deklarationszeile. Es braucht nur die Arravariable markiert werden. Es wird immer getestet, ob davor Global/Local/Dim steht.
- Erstellen von statischen Zuweisungen für 1D/2D-Arrays mit indexwerten anhand abgefragter Werte per Strip-Dialog bei Arrayvariablen ohne Deklarations-Keywort
- To-Do:
mögliche Einrückungen berücksichtigen
Bsp. rechteckige Auswahl
vorher ("|"=Cursor):
Starwert=0, Schrittweite=1
nachher:
Bsp. Markierung Array-Deklaration
vorher:
nachher:
Global $arTest[3][2]
$arTest[0][0] = |
$arTest[0][1] =
$arTest[1][0] =
$arTest[1][1] =
$arTest[2][0] =
$arTest[2][1] =
Bsp. Markierung Array ohne Deklaration
vorher:
nachher (Abfrage Anzahl Elemente im Strip-Dialog):
$arTest[0][0] = |
$arTest[0][1] =
$arTest[1][0] =
$arTest[1][1] =
$arTest[2][0] =
$arTest[2][1] =
Wir hatten damals auch eine AutoIt Variante dafür erstellt.
Hier nun meine Lua-Lösung.
Die Schrittweite kann kombiniert werden mit - * /, + ist die Voreinstellung.
Zur Eingabe wird der Strip-Dialog von SciTE verwendet.
Das Skript speichern und einer Tastenkombination zuweisen.
-- TIME_STAMP 2021-12-05 18:05:21 v 0.3
-- coding:utf-8
-- v 0.3 added: The position in the line (indentation) is taken into account
-- added: The dialogs support English and German language by default (evaluation of the "locale.properties" file).
-- Other languages can be used by replacing the German terms in the "tSetIndex.t_trans" table.
-- fixed: Errors when using declarations without valid ubound value.
-- v 0.2 added: Static array assignment lines with/without declaration (1D/2D array)
local tSetIndex = {}
do
tSetIndex.f_onstrip = nil
tSetIndex.t_rect = {{false}}
tSetIndex.s_start = nil
tSetIndex.s_end = nil
tSetIndex.s_mode = nil
tSetIndex.s_count = nil
tSetIndex.l_start = nil
tSetIndex.l_end = nil
tSetIndex.l_text = nil
tSetIndex.indent = nil
tSetIndex.i_1 = 0
tSetIndex.i_2 = 0
tSetIndex.caret = nil
-- If your locale is neither English nor German, write here a unique line from your locale.properties.
-- Here you can find your local properties: https://github.com/moltenform/scite-files/blob/main/files/translations_list.md
tSetIndex.locale_pattern = "# Updated german translations" -- i.e.: french: "# locale.fr.properties" or italian: "# locale.it.properties"
tSetIndex.t_trans = {} -- Replace the German terms with those of your language.
tSetIndex.t_trans.start = {'Start value', 'Startwert'}
tSetIndex.t_trans.step = {'Step size, can be combined with:', 'Schrittweite, kann kombiniert werden mit:'}
tSetIndex.t_trans.start_ix = {'Start index', 'Start Index'}
tSetIndex.t_trans.start_ix1 = {'Start index 1', 'Start Index 1'}
tSetIndex.t_trans.start_ix2 = {'Start index 2', 'Start Index 2'}
tSetIndex.t_trans.num = {'Number of elements', 'Anzahl Elemente'}
tSetIndex.t_trans.num1 = {'Count 1', 'Anzahl 1'}
tSetIndex.t_trans.num2 = {'Count 2', 'Anzahl 2'}
tSetIndex.t_trans.apply = {'Apply', 'Übernehmen'}
tSetIndex.b_locale = false
tSetIndex.IsLocale = function(self)
local fh = io.open(props['SciteDefaultHome']..'/locale.properties')
if fh == nil then return false end -- default installation: english
local s = fh:read('*a') fh:close()
if s:find(self.locale_pattern) then return true end
return false
end
tSetIndex.Ternary = function(self, _cond, _if_val, _else_val)
if _cond == true then return _if_val else return _else_val end
end
tSetIndex.Init = function(self)
self.s_start = editor.SelectionStart
self.s_end = editor.SelectionEnd
if self.s_start > self.s_end then self.s_start, self.s_end = self.s_end, self.s_start end
self.s_mode = editor.SelectionMode
self.s_count = editor.Selections
self.l_start = editor:LineFromPosition(self.s_start)
self.l_end = editor:LineFromPosition(self.s_end)
self.b_locale = self:IsLocale()
end
--[[
check for declaration (Global/Local/Dim): true/false
read ubound-size(declaration)/index-value(otherwise)
returns: true, ubound1, ubound2
or false, index1, index2
If no array variable is selected, the following is returned: false, nil, nil
]]
tSetIndex.IsDeclaration = function(self, _line)
local arr1D = '%$[%w_]+%[(%d-)%]'
local arr2D = '%$[%w_]+%[(%d-)%]%[(%d-)%]'
local pattern = {}
table.insert(pattern, '(%s-)[Gg][Ll][Oo][Bb][Aa][Ll]%s-'..arr2D)
table.insert(pattern, '(%s-)[Gg][Ll][Oo][Bb][Aa][Ll]%s-'..arr1D)
table.insert(pattern, '(%s-)[Ll][Oo][Cc][Aa][Ll]%s-'..arr2D)
table.insert(pattern, '(%s-)[Ll][Oo][Cc][Aa][Ll]%s-'..arr1D)
table.insert(pattern, '(%s-)[Dd][Ii][Mm]%s-'..arr2D)
table.insert(pattern, '(%s-)[Dd][Ii][Mm]%s-'..arr1D)
local indent, ub1, ub2
for i=1, #pattern do
indent, ub1, ub2 = _line:match(pattern[i]) -- if 2nd index empty: ub2==''
if ub1 ~= nil then
self.indent = indent
return true, ub1, ub2 -- without 2nd index: ub2==nil
end
end
-- if no declaration: detection type 1D/2D, read possible index values
local indent, i1, i2 = _line:match('(%s-)'..arr2D)
if i1 ~= nil then
self.indent = indent
return false, i1, i2
else
indent, i1 = _line:match('(%s-)'..arr1D)
self.indent = indent
return false, i1
end
end
tSetIndex.InsertByDeclaration = function(self, _ub1, _ub2)
local ar_type, l_ub1, l_ub2 = nil
if _ub2 == nil then
if (_ub1 == '' or tonumber(_ub1) == 0) then
print('! FAILURE: No or no valid ubound in the declaration.') return
else
ar_type = 1
l_ub1 = tostring(_ub1 -1):len()
end
else
if (_ub1 == '' or tonumber(_ub1) == 0) then
print('! FAILURE: No or no valid ubound 1 in the declaration.') return
else
if (_ub2 == '' or tonumber(_ub2) == 0) then
print('! FAILURE: No or no valid ubound 2 in the declaration.') return
else
l_ub1 = tostring(_ub1 -1):len()
l_ub2 = tostring(_ub2 -1):len()
ar_type = 2
end
end
end
local s_insert, v, s_idx = ''
v = self.l_text:match('(%$[%w_]+)%[%d-%]')
if ar_type == 1 then -- 1D array
for i=1, _ub1 do
s_idx = ('[%s%d]'):format((' '):rep(l_ub1-tostring(i-1):len()), i-1)
s_insert = s_insert..self.indent..v..s_idx..' = \n'
if self.caret == nil then self.caret = self.s_end + s_insert:len() +1 end
end
elseif ar_type == 2 then -- 2D array
for i=1, _ub1 do
for j=1, _ub2 do
s_idx = ('[%s%d][%s%d]'):format((' '):rep(l_ub1-tostring(i-1):len()), i-1, (' '):rep(l_ub2-tostring(j-1):len()), j-1)
s_insert = s_insert..self.indent..v..s_idx..' = \n'
if self.caret == nil then self.caret = self.s_end + s_insert:len() +1 end
end
end
end
local posIns = editor:PositionFromLine(self.l_start +1)
editor:InsertText(posIns, s_insert)
editor:SetSelection(self.caret, self.caret)
end
tSetIndex.StripInsertNoDeclarationAr1D = function(self, _id, _change)
if _id == 4 and _change == 1 then
local start, count = tonumber(scite.StripValue(1)), tonumber(scite.StripValue(3))
local i_len, s_idx = tostring(count + start):len()
local s = editor:GetSelText()
local v, s_insert = s:match('(%$[%w_]+)%[%d-%]'), ''
for i=start, start+count-1 do
s_idx = ('[%s%d]'):format((' '):rep(i_len-tostring(i):len()), i)
s_insert = s_insert..self:Ternary(i==start,'',self.indent)..v..s_idx..' = \n'
if self.caret == nil then self.caret = self.s_end + 3 end
end
editor:ReplaceSel(s_insert)
editor:SetSelection(self.caret, self.caret)
scite.StripShow('')
end
end
tSetIndex.StripInsertNoDeclarationAr2D = function(self, _id, _change)
if _id == 8 and _change == 1 then
local start1, start2 = tonumber(scite.StripValue(1)), tonumber(scite.StripValue(3))
local count1, count2 = tonumber(scite.StripValue(5)), tonumber(scite.StripValue(7))
local i_len1, i_len2, s_idx1, s_idx2 = tostring(count1 + start1):len(), tostring(count2 + start2):len()
local s = editor:GetSelText()
local v, s_insert = s:match('(%$[%w_]+)%[%d-%]%[%d-%]'), ''
for i=start1, start1+count1-1 do
for j=start2, start2+count2-1 do
s_idx = ('[%s%d][%s%d]'):format((' '):rep(i_len1-tostring(i):len()), i, (' '):rep(i_len2-tostring(j):len()), j)
s_insert = s_insert..self:Ternary(i==start,'',self.indent)..v..s_idx..' = \n'
if self.caret == nil then self.caret = self.s_end + 3 end
end
end
editor:ReplaceSel(s_insert)
editor:SetSelection(self.caret, self.caret)
scite.StripShow('')
end
end
tSetIndex.GetRect = function(self)
local tRet, s, e = {}
repeat
s = editor:GetLineSelStartPosition(self.l_start)
e = editor:GetLineSelEndPosition(self.l_start)
if s ~= e then return end -- don't use if text is selected
table.insert(tRet, {self.l_start,s})
self.l_start = self.l_start +1
self.s_count = self.s_count -1
until self.s_count == 0
self.t_rect = tRet
end
tSetIndex.StripRectSetIndex = function(self, _id, _change)
if _id == 4 and _change == 1 then
if not self.t_rect[1][1] then
print('! FAILURE: The rectangular selection includes text.')
scite.StripShow('') return
end
local start, step = scite.StripValue(1), scite.StripValue(3)
local pos_add, v_ins, int
local op, step = step:match('^([-*/]-)(%d+)')
if tonumber(step) == 0 then
print('! FAILURE: No step width is set')
self.t_rect = {{false}} scite.StripShow('') return
end
-- set 1st value
editor:InsertText(self.t_rect[1][2], start)
pos_add = tostring(start):len()
for i=2, #self.t_rect do
if op == '-' then
v_ins = tostring(start - step)
elseif op == '*' then
if tonumber(start) == 0 then
print('! FAILURE: Multiplication by zero remains zero')
self.t_rect = {{false}} scite.StripShow('') return
end
v_ins = tostring(start * step)
elseif op == '/' then
if tonumber(start) == 0 then
print('! FAILURE: Any attempt to divide the zero remains zero')
self.t_rect = {{false}} scite.StripShow('') return
end
int, frac = math.modf(start / step)
if int == 0 or frac ~= 0 then
print('! FAILURE: The division ( '..tostring(start)..' / '..tostring(step)..' ) does not have an integer result')
self.t_rect = {{false}} scite.StripShow('') return
end
v_ins = tostring(start / step)
else
v_ins = tostring(start + step)
end
editor:InsertText(self.t_rect[i][2] + pos_add, v_ins)
pos_add = pos_add + v_ins:len()
start = tonumber(v_ins)
end
scite.MenuCommand(IDM_SAVE)
self.t_rect = {{false}} -- reset
scite.StripShow('')
end
end
tSetIndex.ShowStripIndex = function(self)
local idx = self:Ternary(self.b_locale, 2, 1)
local strip_def_index = ("!'%s'[]'%s [ - * / ]'[]((%s))"):format(self.t_trans.start[idx], self.t_trans.step[idx], self.t_trans.apply[idx])
scite.StripShow(strip_def_index)
scite.StripSet(1, 0)
scite.StripSet(3, 1)
end
tSetIndex.ShowStripAr1D = function(self)
local idx = self:Ternary(self.b_locale, 2, 1)
local strip_def_index = ("!'%s'[]'%s'[]((%s))"):format(self.t_trans.start_ix[idx], self.t_trans.num[idx], self.t_trans.apply[idx])
scite.StripShow(strip_def_index)
scite.StripSet(1, self.i_1)
end
tSetIndex.ShowStripAr2D = function(self)
local idx = self:Ternary(self.b_locale, 2, 1)
local strip_def_index = ("!'%s'[]'%s'[]'%s'[]'%s'[]((%s))"):format(self.t_trans.start_ix1[idx], self.t_trans.start_ix2[idx], self.t_trans.num1[idx], self.t_trans.num2[idx], self.t_trans.apply[idx])
scite.StripShow(strip_def_index)
scite.StripSet(1, self.i_1)
scite.StripSet(3, self.i_2)
end
end
OnStrip = function(_id, _change)
tSetIndex:f_onstrip(_id, _change)
end
tSetIndex:Init()
if tSetIndex.s_mode == SC_SEL_RECTANGLE then
tSetIndex.f_onstrip = tSetIndex.StripRectSetIndex
tSetIndex:GetRect()
tSetIndex:ShowStripIndex()
elseif tSetIndex.s_mode == SC_SEL_STREAM then
if tSetIndex.s_count == 1 then -- no selection or one selection over multiple lines
if tSetIndex.s_start == tSetIndex.s_end then return end -- no selection
if tSetIndex.l_start == tSetIndex.l_end then -- selection in one line
tSetIndex.l_text = editor:GetLine(tSetIndex.l_start)
local b_decl, ub1, ub2 = tSetIndex:IsDeclaration(tSetIndex.l_text)
if b_decl then
tSetIndex:InsertByDeclaration(ub1, ub2)
else
tSetIndex.i_1 = ub1
tSetIndex.i_2 = ub2
if ub2 == nil then
if ub1 ~= nil then
tSetIndex.f_onstrip = tSetIndex.StripInsertNoDeclarationAr1D
tSetIndex:ShowStripAr1D()
end
else
tSetIndex.f_onstrip = tSetIndex.StripInsertNoDeclarationAr2D
tSetIndex:ShowStripAr2D()
end
end
else -- selection over multiple lines
output:ClearAll()
print('! Selection over multiple lines.\n> This function supports either text selection in one line, i.e.: "Global $ar[10][2]", "$array[]" or rectangular selection without text selection.')
end
end
end
Alles anzeigen