From 1758afd100a2fcce20819ecb7bbe40a8b0aa0d2a Mon Sep 17 00:00:00 2001 From: svk Date: Mon, 26 Jan 2026 19:46:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20=D0=B2=D0=BD=D0=B5?= =?UTF-8?q?=D1=88=D0=BD=D0=B8=D0=BC=D0=B8=20=D0=B8=D0=BD=D1=81=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D0=BC=D0=B8:=20-=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B8=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=20(=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B2,=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5)=20=D1=81=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=BE=D0=BC=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BA?= =?UTF-8?q?=20tools.ini=20-=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=BC=D0=B5=D0=BD=D1=8E=20'=D0=98=D0=BD=D1=81=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D1=8B'=20=D0=BA=D0=B0=D0=BA=20?= =?UTF-8?q?=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=20=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20(=D0=B2=D1=81=D0=BF?= =?UTF-8?q?=D0=BB=D1=8B=D0=B2=D0=B0=D1=8E=D1=89=D0=B5=D0=B3=D0=BE)=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B5=20=20tools.?= =?UTF-8?q?ini.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/gui.tcl | 9 ++- lib/msgs/en.msg | 2 +- lib/msgs/ru.msg | 1 + lib/tools.tcl | 150 ++++++++++++++++++++++++++++++++++++++++++++++++ projman.tcl | 13 ++++- 5 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 lib/tools.tcl diff --git a/lib/gui.tcl b/lib/gui.tcl index 3f26659..d5f0a8f 100644 --- a/lib/gui.tcl +++ b/lib/gui.tcl @@ -135,7 +135,11 @@ GetEditMenu [menu .frmMenu.mnuEdit.m] ttk::menubutton .frmMenu.mnuView -text [::msgcat::mc "View"] -menu .frmMenu.mnuView.m GetViewMenu [menu .frmMenu.mnuView.m] -pack .frmMenu.mnuFile .frmMenu.mnuEdit .frmMenu.mnuView -side left +ttk::menubutton .frmMenu.mnuTools -text [::msgcat::mc "Tools"] -menu .frmMenu.mnuTools.m +Tools::GetMenu [menu .frmMenu.mnuTools.m] + + +pack .frmMenu.mnuFile .frmMenu.mnuEdit .frmMenu.mnuView .frmMenu.mnuTools -side left ttk::menubutton .frmMenu.mnuHelp -text [::msgcat::mc "Help"] -menu .frmMenu.mnuHelp.m GetHelpMenu [menu .frmMenu.mnuHelp.m] @@ -151,6 +155,9 @@ GetFileMenu .popup.file menu .popup.view .popup add cascade -label [::msgcat::mc "View"] -menu .popup.view GetViewMenu .popup.view +menu .popup.tools +.popup add cascade -label [::msgcat::mc "Tools"] -menu .popup.tools +Tools::GetMenu .popup.tools set frmTool [ttk::frame .frmBody.frmTool] ttk::panedwindow .frmBody.panel -orient horizontal -style TPanedwindow diff --git a/lib/msgs/en.msg b/lib/msgs/en.msg index 1840432..72cadfe 100644 --- a/lib/msgs/en.msg +++ b/lib/msgs/en.msg @@ -174,6 +174,7 @@ ::msgcat::mcset en "Title normal" ::msgcat::mcset en "Title modify" ::msgcat::mcset en "Toolbar" +::msgcat::mcset en "Tools" ::msgcat::mcset en "Undo" ::msgcat::mcset en "Update" ::msgcat::mcset en "Variables" @@ -185,4 +186,3 @@ ::msgcat::mcset en "Work dir" - diff --git a/lib/msgs/ru.msg b/lib/msgs/ru.msg index bff7471..0991f34 100644 --- a/lib/msgs/ru.msg +++ b/lib/msgs/ru.msg @@ -214,6 +214,7 @@ ::msgcat::mcset ru "Title normal" "Файл нормальный" ::msgcat::mcset ru "Title modify" "Файл изменен" ::msgcat::mcset ru "Toolbar" "Панель инструментов" +::msgcat::mcset ru "Tools" "Инструменты" ::msgcat::mcset ru "User name" "Имя пользователя" ::msgcat::mcset ru "Undo" "Отменить" ::msgcat::mcset ru "Update" "Обновить" diff --git a/lib/tools.tcl b/lib/tools.tcl new file mode 100644 index 0000000..4be511d --- /dev/null +++ b/lib/tools.tcl @@ -0,0 +1,150 @@ +################################################################## +# tools.tcl - this file implements the logic of working +# with external tools. +################################################################## +# svk, 01/2026 +################################################################## + +namespace eval Tools {} { + variable toolsINISections + variable toolsVariables +} + +set ::toolsDefault "\[VisualRegexp\] +commandString=tkregexp % +description'A graphical front-end to write/debug regular expression +icon= +shortCut= +\[TkDIFF\] +commandString=tkdiff %f %f +description=TkDiff is a Tcl/Tk front-end to diff +icon= +shortCut= +" +# Создание файла настроек внешних инструментов +proc Tools::Create {dir} { + set toolsFile [open [file join $dir tools.ini] "w+"] + puts $toolsFile $::toolsDefault + close $toolsFile +} + +proc Tools::Read {dir} { + set toolsFile [ini::open [file join $dir tools.ini] "r"] + foreach section [ini::sections $toolsFile] { + foreach key [ini::keys $toolsFile $section] { + lappend ::toolsINIsections($section) $key + dict set ::toolsVariables $section $key [ini::value $toolsFile $section $key] + DebugPuts "Tools::Read: $toolsFile $section $key = [ini::value $toolsFile $section $key]" + } + } + ini::close $toolsFile +} + +proc Tools::Write {dir} { + set toolsFile [ini::open [file join $dir tools.ini] "w"] + foreach section [array names ::toolsINIsections] { + dict for {key value} [dict get $::toolsVariables $section] { + DebugPuts "Tools::write: $section $key = $value" + # ini::set $toolsFile $section $key [dict get $::toolsVariables $section $key] + ini::set $toolsFile $section $key $value + } + } + ini::commit $toolsFile + ini::close $toolsFile +} + +# Добавление перменной в список +# если отсутствует нужная секция то она будет добавлена. +proc Tools::AddVariable {key value section} { + # Проверяем, существует ли уже такая переменная + if {[info exists ::toolsVariables($key)]} { + DebugPuts "The variable '$key' already exists: " + return 0 + } + # Добавляем в массив переменных + # set ::toolsVariables($key) $value + dict set ::toolsVariables $section $key $value + # Добавляем в список ключей секции + if {[dict exists $::toolsVariables $key]} { + # Проверяем, нет ли уже такого ключа в секции + if {[lsearch -exact $::toolsINIsections($section) $key] == -1} { + lappend ::toolsINIsections($section) $key + } + } else { + set ::toolsINIsections($section) [list $key] + } + DebugPuts "Tools::AddVariable: The variable '$key' has been added to the '$section' array 'toolsVariables' with value '$value'" + + return 1 +} + +# Проверяем наличие переменных в tools.ini на основе "эталонного" списка +# и выставляем значение по умолчанию если в конфиге переменной нет +proc Tools::CheckVariables {} { + set valList [split $::toolsDefault "\n"] + foreach item $valList { + if {[regexp -nocase -all -- {\[(\w+)\]} $item -> v1]} { + set section $v1 + } + if {[regexp {^([^=]+)=(.*)$} $item -> key value]} { + # puts "$section $key $value >> [dict get $::toolsVariables $section $key]" + # if {[dict get $::toolsVariables $section $key] eq ""} + if ![dict exists $::toolsVariables $section $key] { + DebugPuts "Error in Tools::CheckVariables: variable $section $key not found" + Tools::AddVariable "$key" "$value" "$section" + # DebugPuts "Tools::CheckVariables: The variable toolsVariables $key setting to default value \"$value\"" + } + } + } + foreach id [dict keys $::toolsVariables] { + DebugPuts "Tools::CheckVariables: config parameters for $id [dict get $::toolsVariables $id]!" + } + # DebugPuts "toolsVariables dict keys: [dict keys $::toolsVariables]" +} + +proc Tools::GetMenu {m} { + global cfgVariables toolsVariables + foreach toolName [dict keys $toolsVariables] { + dict for {key value} [dict get $toolsVariables $toolName] { + DebugPuts "GetToolsMenu $key $value" + if {$key eq "commandString"} { + set cmd "$value" + } + if {$key eq "shortCut"} { + set shortCut "$value" + } + } + if {[info exists cmd] == 1 && $cmd ne ""} { + if {[info exists shortCut] == 1 && $shortCut ne ""} { + $m add command -label $toolName -accelerator $shortCut -command [list Tools::Execute "$toolName"] + } else { + $m add command -label $toolName -command [list Tools::Execute "$toolName"] + } + } + } +} + +proc Tools::Execute {toolName} { + global cfgVariables toolsVariables + if ![dict exists $::toolsVariables $toolName commandString] { + DebugPuts "Tools::Execute: command for $toolName not found" + return + } else { + set command [dict get $::toolsVariables $toolName commandString] + DebugPuts "Tools::Execute: command for $toolName as $command" + } + # 1. Определять текущий файл + # 2. Определять выделен ли текст в открытом редакторе + # 3. Опеределять сколько файлов выделено в дереве + # 4. Заменяем знак %f на имя текущего файла (файлов) + # regsub -all "%f" $command "$filePath" fullCommand + # 5. Заменяем %s на выделенный в редакторе текст + # 6. Заменяем %d на текущий каталог(и), если он выделен в дереве, + # и если не выделено то корневой открытый в дереве + # 7. Проверять команды на доступность в системе и подставлять полный путь к команде + # если в конфиге не указан полный путь. + set pipe [open "|$command" "r"] + fileevent $pipe readable + fconfigure $pipe -buffering none -blocking no +} + diff --git a/projman.tcl b/projman.tcl index 18ad1ef..47d07bb 100755 --- a/projman.tcl +++ b/projman.tcl @@ -114,13 +114,22 @@ foreach modFile [lsort [glob -nocomplain [file join $dir(theme) *]]] { } -# загружаем пользовательский конфиг, если он отсутствует, то копируем дефолтный -if {[file exists [file join $dir(cfg) projman.ini]] ==0} { +# загружаем пользовательский конфиг, если он отсутствует или пустой, то копируем дефолтный +if {[file exists [file join $dir(cfg) projman.ini]] == 0 || [file size [file join $dir(cfg) projman.ini]] == 0} { Config::create $dir(cfg) } Config::read $dir(cfg) Config::CheckVariables +# загружаем пользовательский конфиг для инстурментов, если он отсутствует или пустой, то копируем дефолтный +if {[file exists [file join $dir(cfg) tools.ini]] == 0 || [file size [file join $dir(cfg) tools.ini]] == 0} { + Tools::Create $dir(cfg) +} +# Читаем настройки для внешних инструментов +Tools::Read $dir(cfg) +Tools::CheckVariables +Tools::Write $dir(cfg) + ::msgcat::mclocale $cfgVariables(locale) if [::msgcat::mcload [file join $dir(lib) msgs]] {