2 Commits

17 changed files with 27 additions and 768 deletions

View File

@@ -163,7 +163,6 @@ Or type "projman" into terminal, Or choose the name of the program "Projman" on
ProjMan allows you to connect any external tools to the editor. To do this, you need to add an entry to the file ~/.config/projman/tools.ini.
Calling an external program is available through the main and pop-up menus. To transfer the parameters, write the appropriate template in the file.
- %s - template for substituting selected text in the editor
- %f - template for substituting selected file\(s\) in the file tree

22
debian/changelog vendored
View File

@@ -1,24 +1,3 @@
projman (2.0.0-beta6) stable; urgency=medium
* Отключил сжатие README.md в пакете
* Добавил README.md по F1. Сделал черновой вариант парсера и визуализатора MD
-- Sergey Kalinin <svk@nuk-svk.ru> Thu, 26 Mar 2026 19:39:54 +0300
projman (2.0.0-beta5) stable; urgency=medium
* Исправил перевод (все равно какой-то кривой)
* Исправил changelog
-- Sergey Kalinin <svk@nuk-svk.ru> Tue, 17 Feb 2026 13:00:42 +0300
projman (2.0.0-beta5) stable; urgency=medium
* Добавил код из https://github.com/wandrien/projman/tree/master для работы с выделенным текстом. И внес изменения в связи с этим.
* Исправления работы с С
-- Sergey Kalinin <svk@nuk-svk.ru> Fri, 13 Feb 2026 11:27:41 +0300
projman (2.0.0-beta4) stable; urgency=medium
* Исправлено регулярное выражение для поиска переменных в коде на С.
@@ -533,4 +512,3 @@ projman (2.0.0-alfa0) stable; urgency=medium

2
debian/docs vendored
View File

@@ -1,2 +1,4 @@
README.md
CHANGELOG
TODO

2
debian/install vendored
View File

@@ -4,6 +4,6 @@ tkregexp /usr/bin
lib/*.tcl /usr/share/projman/lib
lib/msgs/* /usr/share/projman/lib/msgs
theme /usr/share/projman/
README.md /usr/share/doc/projman
projman.desktop /usr/share/applications
projman.png /usr/share/pixmaps
README.md /usr/share/doc/projman/

16
debian/rules vendored
View File

@@ -1,4 +1,5 @@
#!/usr/bin/make -f
# debian/rules for alien
PACKAGE=$(shell dh_listpackages)
@@ -20,13 +21,26 @@ binary-arch: build
dh_install
dh_installdocs
dh_installchangelogs
# Copy the packages's files.
# find . -maxdepth 1 -mindepth 1 -not -name debian -print0 | \
# xargs -0 -r -i cp -a {} debian/$(PACKAGE)
#
# If you need to move files around in debian/$(PACKAGE) or do some
# binary patching, do it here
#
# This has been known to break on some wacky binaries.
# dh_strip
dh_compress
gunzip -f debian/$(PACKAGE)/usr/share/doc/$(PACKAGE)/README.md.gz 2>/dev/null || true
# dh_fixperms
dh_makeshlibs
dh_installdeb
-dh_shlibdeps
dh_gencontrol
dh_md5sums
# dh_link
dh_builddeb
binary: binary-indep binary-arch

View File

@@ -78,19 +78,6 @@ LUA=lua
\[Debug\]
debug=false
debugOut=stdout
\[Viewer\]
listSymbol=
h1Font={Droid Sans Mono} 20 bold
h2Font={Droid Sans Mono} 18 bold
h3Font={Droid Sans Mono} 16 bold
h4Font={Droid Sans Mono} 14 bold
h5Font={Droid Sans Mono} 12 bold
h6Font={Droid Sans Mono} 10 bold
mdListFont={Droid Sans Mono} 10
codeBlockBG=#7a7a7a
codeBlockFG=black
codeBlockFont=Monospace 10 italic
textBG=#333333
"
proc Config::create {dir} {
set cfgFile [open [file join $dir projman.ini] "w+"]

View File

@@ -746,18 +746,6 @@ namespace eval Editor {
}
bind $txt <Control-r> "Editor::SplitEditorForExecute $w $fileType $nb "
bind $txt <Control-Cyrillic_ka> "Editor::SplitEditorForExecute $w $fileType $nb "
bind $txt <Control-Shift-U> {SelectionToUpperCase %W}
bind $txt <Control-Shift-u> {SelectionToUpperCase %W}
bind $txt <Control-Shift-L> {SelectionToLowerCase %W}
bind $txt <Control-Shift-l> {SelectionToLowerCase %W}
bind $txt <Control-Shift-T> {SelectionToTitleCase %W}
bind $txt <Control-Shift-t> {SelectionToTitleCase %W}
bind $txt <Control-Shift-Y> {SelectionToSentenceCase %W}
bind $txt <Control-Shift-y> {SelectionToSentenceCase %W}
bind $txt <Control-Shift-I> {SelectionToggleCase %W}
bind $txt <Control-Shift-i> {SelectionToggleCase %W}
# bind $txt <Shift-Control-s> FileOper::Close
# bind $txt <Shift-Control-Cyrillic_es> "FileOper::Close saveas"

View File

@@ -236,7 +236,7 @@ ttk::style layout TNotebook.Tab {
}
}
bind TNotebook <Button-1> "catch {NB::PressTab %W %x %y}\;[bind TNotebook <Button-1>];break"
bind <<NotebookTabChanged>> "catch {NB::PressTab %W %x %y}\;[bind TNotebook <Button-1>];break"
# bind <<NotebookTabChanged>> "NB::PressTab %W %x %y"
# bind TNotebook <ButtonRelease-1> "NB::PressTab %W %x %y"
# bind TNotebook <Control-w> FileOper::Close
# bind . <Control-Tab> "NB::NextTab $nbEditor"

View File

@@ -1,29 +0,0 @@
######################################################
# ProjMan 2
# Distributed under GNU Public License
# Author: Sergey Kalinin svk@nuk-svk.ru
# Copyright (c) "", 2022-2026, https://nuk-svk.ru
######################################################
#
# Projman Help dialog
#
######################################################
proc ShowHelpDialog {} {
ShowMD [HelpFileLocation README.md]
}
proc HelpFileLocation {fileName} {
global dir projman
if [file exists [file join $dir(lib) $fileName]] {
return [file join $dir(lib) fileName]
} elseif [file exists [file join /usr/share/doc/projman $fileName]] {
return [file join /usr/share/doc/projman $fileName]
} elseif [file exists [file join /usr/share/doc/projman-$projman(Version) $fileName]] {
return [file join /usr/share/doc/projman-$projman(Version) $fileName]
} else {
return [file join [pwd] $fileName]
}
}

View File

@@ -1,213 +0,0 @@
######################################################
# ProjMan 2
# Distributed under GNU Public License
# Author: Sergey Kalinin svk@nuk-svk.ru
# Copyright (c) "", 2022-2026, https://nuk-svk.ru
######################################################
#
# The markdown file viewer
#
######################################################
proc ShowMD {fileFullPath} {
global cfgVariables
set win .viewer
set parentGeometry [wm geometry .]
set parentWidth [winfo width .]
set parentHeight [winfo height .]
set parentX [winfo x .]
set parentY [winfo y .]
# Устанавливаем размеры нового окна (меньше на 200)
set newWidth [expr {$parentWidth - 200}]
set newHeight [expr {$parentHeight - 200}]
# Вычисляем позицию для центрирования относительно родительского окна
set x [expr {$parentX + ($parentWidth - $newWidth) / 2}]
set y [expr {$parentY + ($parentHeight - $newHeight) / 2}]
# Применяем геометрию
if { [winfo exists $win] } { destroy $win; return false }
toplevel $win
wm title $win "[::msgcat::mc "Help"]"
wm geometry $win ${newWidth}x${newHeight}+${x}+${y}
wm overrideredirect $win 0
set frm [ttk::frame $win.frmHelp]
pack $frm -expand 1 -fill both
set txt [text $frm.txt -wrap $cfgVariables(editorWrap) -background $cfgVariables(textBG) \
-xscrollcommand "$win.h set" -yscrollcommand "$frm.v set"]
pack $txt -side left -expand 1 -fill both
pack [ttk::scrollbar $frm.v -command "$frm.txt yview"] -side right -fill y
ttk::scrollbar $win.h -orient horizontal -command "$frm.txt xview"
if {$cfgVariables(editorWrap) eq "none"} {
pack $win.h -side bottom -fill x
}
bind .viewer <Escape> {destroy .viewer}
$txt tag configure h1 -font $cfgVariables(h1Font)
$txt tag configure h2 -font $cfgVariables(h2Font)
$txt tag configure h3 -font $cfgVariables(h3Font)
$txt tag configure h4 -font $cfgVariables(h4Font)
$txt tag configure h5 -font $cfgVariables(h5Font)
$txt tag configure h6 -font $cfgVariables(h6Font)
$txt tag configure mdList -font $cfgVariables(mdListFont)
$txt tag configure codeBlock -foreground $cfgVariables(codeBlockFG) \
-background $cfgVariables(codeBlockBG) -font $cfgVariables(codeBlockFont)
set codeBlockBegin false
set f [open "$fileFullPath" r]
set lineNumber 0
while {[gets $f line] >= 0} {
# puts $line
if {$line eq ""} {
if {$codeBlockBegin eq "true"} {
$txt insert end "\n" codeBlock
} else {
$txt insert end "\n"
}
incr lineNumber
continue
}
set result [MarkDownParser $line]
# puts $result
set textTag [lindex $result 0]
if {$textTag eq "codeBlock" && $codeBlockBegin eq "false"} {
set codeBlockBegin true
} elseif {$textTag eq "codeBlock" && $codeBlockBegin eq "true"} {
set codeBlockBegin false
}
if {$codeBlockBegin eq "true"} {
set textTag "codeBlock"
}
if {$textTag eq "" && $codeBlockBegin eq "false"} {
$txt insert end "[lindex $result 1]\n"
} elseif {$textTag eq "codeBlockOneString"} {
ProcessLineWithCode $line $txt
} elseif {$textTag eq "mdList"} {
$txt insert end " $cfgVariables(listSymbol) $result\n"
} else {
$txt insert end "[lindex $result 1]\n" $textTag
}
incr lineNumber
}
close $f
}
proc ProcessLineWithCode {line txt} {
set codeBlocks [ExtractCodeBlocks $line]
if {[llength $codeBlocks] == 0} {
$txt insert end "$line\n"
return
}
set lastPos 0
foreach block $codeBlocks {
# Извлекаем данные из блока
set fullMatch [lindex $block 0]
set codeText [lindex $block 1]
set matchPos [lindex $block 2]
set codePos [lindex $block 3]
set start [lindex $matchPos 0]
set end [lindex $matchPos 1]
# Вставляем текст перед кодом
if {$start > $lastPos} {
set text_before [string range $line $lastPos [expr {$start - 1}]]
$txt insert end $text_before
}
# Вставляем код с соответствующим тегом
if {[string match "```*" $fullMatch]} {
$txt insert end $codeText codeBlock
} else {
$txt insert end $codeText code_inline
}
set lastPos [expr {$end + 1}]
}
# Вставляем остаток строки
if {$lastPos < [string length $line]} {
$txt insert end [string range $line $lastPos end]
}
$txt insert end "\n"
}
proc MarkDownParser {line} {
# Title
# [regexp -nocase -line -- {^(#{1,6})\s\w+} $line match sharp]
if [regexp -nocase -all -line -- {^(#{1,6})\s(.+)} $line match sharp title] {
set titlePrefixLength [string length $sharp]
puts $title
switch $titlePrefixLength {
1 {return [list h1 "$title"]}
2 {return [list h2 "$title"]}
3 {return [list h3 "$title"]}
4 {return [list h4 "$title"]}
5 {return [list h5 "$title"]}
6 {return [list h6 "$title"]}
}
}
# Lists
if [regexp -nocase -all -line -- {^\s*(\*|-|\+)\s(.+)} $line match symbol textLine] {
# puts $textLine
return [list mdList "$textLine"]
}
# Multi-line code block
if [regexp -nocase -all -line -- {^```(\w*)} $line match lang] {
return [list codeBlock {}]
}
# One string code blockregexp -nocase -all -line -- {(`{1,3}([^`]+)`{1,3})} string match v1 v2
if [regexp -nocase -all -line -- {`{1,3}([^`]+)`{1,3}} $line match v1 code v2] {
# puts $line
set result [ExtractCodeBlocks $line]
# puts "$v1, $code, $v2"
# puts "$result"
return [list codeBlockOneString $result]
}
return [list {} $line]
}
proc ExtractCodeBlocks {line} {
set pattern {`{1,3}([^`]+)`{1,3}}
set result {}
# Ищем все вхождения
set pos 0
while {[regexp -indices -start $pos -- $pattern $line match code]} {
set start [lindex $match 0]
set end [lindex $match 1]
set codeStart [lindex $code 0]
set codeEnd [lindex $code 1]
# Получаем текст кода без кавычек
set codeText [string range $line $codeStart $codeEnd]
# Получаем полный текст с кавычками
set fullMatch [string range $line $start $end]
lappend result [list $fullMatch $codeText [list $start $end] [list $codeStart $codeEnd]]
set pos [expr {$end + 1}]
}
return $result
}

View File

@@ -69,15 +69,6 @@ proc GetEditMenu {m} {
-accelerator "Ctrl+F"
# $m add command -label [::msgcat::mc "Replace"] -command Replace\
# -accelerator "Ctrl+R"
$m add separator
menu $m.convertCase
$m add cascade -label [::msgcat::mc "Convert case"] -menu $m.convertCase
GetConvertCaseMenu $m.convertCase
menu $m.convertNamingStyle
$m add cascade -label [::msgcat::mc "Convert naming style"] -menu $m.convertNamingStyle
GetConvertIdentCaseMenu $m.convertNamingStyle
$m add separator
$m add command -label [::msgcat::mc "Find in files"] -command "FileOper::FindInFiles"\
-accelerator "Ctrl+Shift+F"
@@ -147,47 +138,3 @@ proc GetHelpMenu {m} {
proc PopupMenu {x y} {
tk_popup .popup $x $y
}
# ============================================================
# 2026 Vadim Ushakov <wandrien.dev@gmail.com>
proc GetConvertCaseMenu {m} {
$m add command -label [::msgcat::mc "UPPER CASE"] -command SelectionToUpperCase\
-accelerator "Ctrl+Shift+U"
$m add command -label [::msgcat::mc "lower case"] -command SelectionToLowerCase\
-accelerator "Ctrl+Shift+L"
$m add command -label [::msgcat::mc "Title Case"] -command SelectionToTitleCase\
-accelerator "Ctrl+Shift+T"
$m add command -label [::msgcat::mc "Sentence case"] -command SelectionToSentenceCase\
-accelerator "Ctrl+Shift+Y"
$m add command -label [::msgcat::mc "iNVERT CASE"] -command SelectionToggleCase\
-accelerator "Ctrl+Shift+I"
}
proc GetConvertIdentCaseMenu {m} {
$m add command -label [::msgcat::mc "flatcase"] -command SelectionToFlatCase
$m add command -label [::msgcat::mc "UPPERCASE"] -command SelectionToUpperFlatCase
$m add separator
$m add command -label [::msgcat::mc "camelCase"] -command SelectionToCamelCase
$m add command -label [::msgcat::mc "PascalCase"] -command SelectionToPascalCase
$m add separator
$m add command -label [::msgcat::mc "snake_case"] -command SelectionToSnakeCase
$m add command -label [::msgcat::mc "SCREAMING_SNAKE_CASE"] -command SelectionToScreamingSnakeCase
$m add command -label [::msgcat::mc "camel_Snake_Case"] -command SelectionToCamelSnakeCase
$m add command -label [::msgcat::mc "Title_Case"] -command SelectionToTitleSnakeCase
$m add separator
$m add command -label [::msgcat::mc "kebab-case"] -command SelectionToKebabCase
$m add command -label [::msgcat::mc "SCREAMING-KEBAB-CASE"] -command SelectionToScreamingKebabCase
$m add command -label [::msgcat::mc "Train-Case"] -command SelectionToTrainCase
$m add separator
$m add command -label [::msgcat::mc "space separated"] -command SelectionToWords
}
# 2026 Vadim Ushakov <wandrien.dev@gmail.com>
# ============================================================

View File

@@ -185,23 +185,4 @@
::msgcat::mcset en "Word wrapping"
::msgcat::mcset en "Work dir"
::msgcat::mcset en "Convert case"
::msgcat::mcset en "Convert naming style"
::msgcat::mcset en "UPPER CASE"
::msgcat::mcset en "lower case"
::msgcat::mcset en "Title Case"
::msgcat::mcset en "Sentence case"
::msgcat::mcset en "iNVERT CASE"
::msgcat::mcset en "flatcase"
::msgcat::mcset en "UPPERCASE"
::msgcat::mcset en "camelCase"
::msgcat::mcset en "PascalCase"
::msgcat::mcset en "snake_case"
::msgcat::mcset en "SCREAMING_SNAKE_CASE"
::msgcat::mcset en "camel_Snake_Case"
::msgcat::mcset en "Title_Case"
::msgcat::mcset en "kebab-case"
::msgcat::mcset en "SCREAMING-KEBAB-CASE"
::msgcat::mcset en "Train-Case"
::msgcat::mcset en "space separated"

View File

@@ -234,23 +234,3 @@
::msgcat::mcset ru "Editors word wrapping" "Перенос слов в редакторе"
::msgcat::mcset ru "Work dir" "Рабочий каталог"
::msgcat::mcset ru "Yes" "Да"
::msgcat::mcset ru "Convert case" "Изменить регистр"
::msgcat::mcset ru "Convert naming style" "Изменить стиль написания"
::msgcat::mcset ru "UPPER CASE" "ЗАГЛАВНЫЕ БУКВЫ"
::msgcat::mcset ru "lower case" "строчные буквы"
::msgcat::mcset ru "Title Case" "С Заглавной Буквы"
::msgcat::mcset ru "Sentence case" "Предложение с заглавной"
::msgcat::mcset ru "iNVERT CASE" "иНВЕРТИРОВАННЫЙ РЕГИСТР"
::msgcat::mcset ru "flatcase" "строчныебуквы"
::msgcat::mcset ru "UPPERCASE" "ЗАГЛАВНЫЕБУКВЫ"
::msgcat::mcset ru "camelCase" "camelCase"
::msgcat::mcset ru "PascalCase" "PascalCase"
::msgcat::mcset ru "snake_case" "строчные_буквы"
::msgcat::mcset ru "SCREAMING_SNAKE_CASE" "ЗАГЛАВНЫЕУКВЫ"
::msgcat::mcset ru "camel_Snake_Case" "camel_Snake_Case"
::msgcat::mcset ru "Title_Case" "С_Заглавной_Через_Подчеркивание"
::msgcat::mcset ru "kebab-case" "строчные-буквы"
::msgcat::mcset ru "SCREAMING-KEBAB-CASE" "ЗАГЛАВНЫЕ-БУКВЫ"
::msgcat::mcset ru "Train-Case" "С-Заглавной-Через-Дефис"
::msgcat::mcset ru "space separated" "разделить пробелом"

View File

@@ -1135,74 +1135,18 @@ proc ExecutorCommandPathSetting {fileType} {
}
}
# =====================================================================
# 2026 Vadim Ushakov <wandrien.dev@gmail.com>
# -----------
# Thanks https://github.com/wandrien/
# https://github.com/wandrien/projman/commit/22f6e235c3532c20573d44ee7eaaaa1fb56ad544
proc ReplaceSelection {w newText} {
set selStart [$w index sel.first]
# Сохраняем и отключаем auto-separators
set autoSep [$w cget -autoseparators]
$w configure -autoseparators 0
# Замена текста как атомарный блок в Undo-стеке
$w edit separator
$w delete sel.first sel.last
$w insert $selStart $newText
$w edit separator
# Восстанавливаем autoseparators
$w configure -autoseparators $autoSep
# Восстанавливаем выделение на новом тексте
set selEnd [$w index "$selStart + [string length $newText] chars"]
$w tag add sel $selStart $selEnd
# Если ctext поддерживает подсветку - обновляем её
catch {$w highlight $selStart $selEnd}
}
proc HasSelection {w} {
set ranges [$w tag ranges sel]
return [expr {$ranges ne ""}]
}
proc GetLatestTxtWidget {} {
proc SendEventToLatestTxtWidget {ev} {
global latestTxtWidget
if {$latestTxtWidget eq ""} {
# pass
return
} elseif {[winfo exists $latestTxtWidget] && [winfo class $latestTxtWidget] eq "Ctext"} {
# pass
event generate ${latestTxtWidget}.t $ev
} else {
set latestTxtWidget ""
}
return $latestTxtWidget
}
proc ChoiceTxtWidgetOrLatest {{w ""}} {
if {$w ne ""} {
return $w
}
return [GetLatestTxtWidget]
}
proc ProcessSelection {handle {w ""}} {
set w [ChoiceTxtWidgetOrLatest $w]
if {$w eq ""} {
return
}
if {![HasSelection $w]} {
return
}
set text [$w get sel.first sel.last]
ReplaceSelection $w [$handle $text]
}
proc SendEventToLatestTxtWidget {ev} {
set w [GetLatestTxtWidget]
if {$w ne ""} {
event generate $w.t $ev
}
}
proc Cut {} { SendEventToLatestTxtWidget <<Cut>> }
@@ -1210,8 +1154,7 @@ proc Copy {} { SendEventToLatestTxtWidget <<Copy>> }
proc Paste {} { SendEventToLatestTxtWidget <<Paste>> }
proc Undo {} { SendEventToLatestTxtWidget <<Undo>> }
proc Redo {} { SendEventToLatestTxtWidget <<Redo>> }
# 2026 Vadim Ushakov <wandrien.dev@gmail.com>
# =====================================================================
# ------------
proc DebugPuts {msg} {
global cfgVariables
@@ -1231,5 +1174,3 @@ proc DebugPuts {msg} {
}
}
}

View File

@@ -1,302 +0,0 @@
# Copyright 2026 Vadim Ushakov <wandrien.dev@gmail.com>
proc SelectionToUpperCase {{w ""}} {
ProcessSelection TextToUpperCase $w
}
proc SelectionToLowerCase {{w ""}} {
ProcessSelection TextToLowerCase $w
}
proc SelectionToTitleCase {{w ""}} {
ProcessSelection TextToTitleCase $w
}
proc SelectionToggleCase {{w ""}} {
ProcessSelection TextToggleCase $w
}
proc SelectionToSentenceCase {{w ""}} {
ProcessSelection TextToSentenceCase $w
}
################################################################################
proc TextToUpperCase {text} {
return [string toupper $text]
}
proc TextToLowerCase {text} {
return [string tolower $text]
}
proc TextToTitleCase {text} {
set result ""
set wordStart 1
foreach char [split $text ""] {
if {[string is alpha $char]} {
if {$wordStart} {
append result [string toupper $char]
set wordStart 0
} else {
append result [string tolower $char]
}
} else {
append result $char
if {[string is space $char] || $char in {- _ . , ; : ! ? ( ) [ ]}} {
set wordStart 1
}
}
}
return $result
}
proc TextToSentenceCase {text} {
set text [TextToLowerCase $text]
set result ""
set sentenceStart 1
set afterPunctuation 0
foreach char [split $text ""] {
if {[string is alpha $char]} {
if {$sentenceStart} {
append result [TextToUpperCase $char]
set sentenceStart 0
} else {
append result $char
}
set afterPunctuation 0
} elseif {$char in {. ! ?}} {
append result $char
set afterPunctuation 1
} elseif {[string is space $char]} {
append result $char
if {$afterPunctuation} {
set sentenceStart 1
}
} else {
append result $char
set afterPunctuation 0
}
}
return $result
}
proc TextToggleCase {text} {
set result ""
foreach char [split $text ""] {
if {[string is upper $char]} {
append result [TextToLowerCase $char]
} elseif {[string is lower $char]} {
append result [TextToUpperCase $char]
} else {
append result $char
}
}
return $result
}
################################################################################
# Identifier case conversion
################################################################################
proc IsIdentSeparator {char} {
expr {$char eq "_" || $char eq "-" || [string is space $char]}
}
proc IsUpperChar {c} { string is upper -strict $c }
proc IsLowerChar {c} { string is lower -strict $c }
proc IsAlphaChar {c} { string is alpha -strict $c }
proc IsDigitChar {c} { string is digit -strict $c }
# Граница внутри "слитного" идентификатора (camel/pascal/акронимы/цифры):
# - lower -> Upper : twoWords
# - digit <-> alpha : word2Word, word2, 2word
# - "HTTPServer" : HTTP | Server (между P и S, т.к. S Upper и дальше lower)
proc IdentHasBoundary {prev cur next} {
set prevLower [IsLowerChar $prev]
set prevUpper [IsUpperChar $prev]
set prevAlpha [IsAlphaChar $prev]
set prevDigit [IsDigitChar $prev]
set curUpper [IsUpperChar $cur]
set curAlpha [IsAlphaChar $cur]
set curDigit [IsDigitChar $cur]
set nextLower 0
if {$next ne ""} {
set nextLower [IsLowerChar $next]
}
if {$prevLower && $curUpper} {
return 1
}
if {($prevAlpha && $curDigit) || ($prevDigit && $curAlpha)} {
return 1
}
if {$prevUpper && $curUpper && $nextLower} {
return 1
}
return 0
}
# Главная стадия №1: распознать границы частей и вернуть список частей.
proc IdentSplit {text} {
set parts {}
set token ""
set len [string length $text]
for {set i 0} {$i < $len} {incr i} {
set c [string index $text $i]
if {[IsIdentSeparator $c]} {
if {$token ne ""} {
lappend parts $token
set token ""
}
continue
}
if {$token ne ""} {
set prev [string index $text [expr {$i-1}]]
if {$i+1 < $len} {
set next [string index $text [expr {$i+1}]]
} else {
set next ""
}
if {[IdentHasBoundary $prev $c $next]} {
lappend parts $token
set token ""
}
}
append token $c
}
if {$token ne ""} {
lappend parts $token
}
return $parts
}
# Применение капитализации к одной части
proc IdentPartLower {p} { string tolower $p }
proc IdentPartUpper {p} { string toupper $p }
proc IdentPartTitle {p} {
if {$p eq ""} { return "" }
set p [string tolower $p]
set first [string index $p 0]
set rest [string range $p 1 end]
return "[string toupper $first]$rest"
}
proc IdentJoinAll {parts sep how} {
set out ""
set first 1
foreach p $parts {
if {!$first} { append out $sep } else { set first 0 }
switch -- $how {
lower { append out [IdentPartLower $p] }
upper { append out [IdentPartUpper $p] }
title { append out [IdentPartTitle $p] }
default { error "Unknown case '$how'" }
}
}
return $out
}
proc IdentJoinFirstRest {parts sep firstHow restHow} {
if {[llength $parts] == 0} { return "" }
set out ""
set i 0
foreach p $parts {
if {$i > 0} { append out $sep }
if {$i == 0} {
set how $firstHow
} else {
set how $restHow
}
switch -- $how {
lower { append out [IdentPartLower $p] }
upper { append out [IdentPartUpper $p] }
title { append out [IdentPartTitle $p] }
default { error "Unknown case '$how'" }
}
incr i
}
return $out
}
################################################################################
# Stage №2: parts -> target representation
################################################################################
proc IdentToFlatCase {text} {
return [IdentJoinAll [IdentSplit $text] "" lower] ;# twowords / flatcase
}
proc IdentToUpperFlatCase {text} {
return [IdentJoinAll [IdentSplit $text] "" upper] ;# TWOWORDS / UPPERCASE
}
proc IdentToCamelCase {text} {
return [IdentJoinFirstRest [IdentSplit $text] "" lower title] ;# twoWords
}
proc IdentToPascalCase {text} {
return [IdentJoinAll [IdentSplit $text] "" title] ;# TwoWords
}
proc IdentToSnakeCase {text} {
return [IdentJoinAll [IdentSplit $text] "_" lower] ;# two_words
}
proc IdentToScreamingSnakeCase {text} {
return [IdentJoinAll [IdentSplit $text] "_" upper] ;# TWO_WORDS
}
proc IdentToCamelSnakeCase {text} {
return [IdentJoinFirstRest [IdentSplit $text] "_" lower title] ;# two_Words
}
proc IdentToTitleSnakeCase {text} {
return [IdentJoinAll [IdentSplit $text] "_" title] ;# Two_Words (Title_Case)
}
proc IdentToKebabCase {text} {
return [IdentJoinAll [IdentSplit $text] "-" lower] ;# two-words
}
proc IdentToScreamingKebabCase {text} {
return [IdentJoinAll [IdentSplit $text] "-" upper] ;# TWO-WORDS
}
proc IdentToTrainCase {text} {
return [IdentJoinAll [IdentSplit $text] "-" title] ;# Two-Words
}
proc IdentToWords {text} {
return [IdentJoinAll [IdentSplit $text] " " lower] ;# two words (space separated)
}
################################################################################
proc SelectionToFlatCase {{w ""}} { ProcessSelection IdentToFlatCase $w }
proc SelectionToUpperFlatCase {{w ""}} { ProcessSelection IdentToUpperFlatCase $w }
proc SelectionToCamelCase {{w ""}} { ProcessSelection IdentToCamelCase $w }
proc SelectionToPascalCase {{w ""}} { ProcessSelection IdentToPascalCase $w }
proc SelectionToSnakeCase {{w ""}} { ProcessSelection IdentToSnakeCase $w }
proc SelectionToScreamingSnakeCase {{w ""}} { ProcessSelection IdentToScreamingSnakeCase $w }
proc SelectionToCamelSnakeCase {{w ""}} { ProcessSelection IdentToCamelSnakeCase $w }
proc SelectionToTitleSnakeCase {{w ""}} { ProcessSelection IdentToTitleSnakeCase $w }
proc SelectionToKebabCase {{w ""}} { ProcessSelection IdentToKebabCase $w }
proc SelectionToScreamingKebabCase {{w ""}} { ProcessSelection IdentToScreamingKebabCase $w }
proc SelectionToTrainCase {{w ""}} { ProcessSelection IdentToTrainCase $w }
proc SelectionToWords {{w ""}} { ProcessSelection IdentToWords $w }

View File

@@ -9,8 +9,8 @@ exec wish8.6 "$0" -- "$@"
# Home page: https://nuk-svk.ru
######################################################
# Version: 2.0.0
# Release: beta6
# Build: 27032026113701
# Release: beta4
# Build: 13022026112625
######################################################
# определим текущую версию, релиз и т.д.

View File

@@ -70,18 +70,6 @@ fi
%{_iconsdir}/hicolor/48x48/apps/projman.png
%changelog
* Fri Mar 27 2026 Sergey Kalinin <svk@nuk-svk.ru> 2.0.0-beta6
- Отключил сжатие README.md в пакете
- Добавил README.md по F1. Сделал черновой вариант парсера и визуализатора MD
* Tue Feb 17 2026 Sergey Kalinin <svkalinin@samsonpost.ru> 2.0.0-beta5
- Исправил перевод (все равно какой-то кривой)
- Исправил changelog
* Tue Feb 17 2026 Sergey Kalinin <svkalinin@samsonpost.ru> 2.0.0-beta5
- Добавил код из https://github.com/wandrien/projman/tree/master для работы с выделенным текстом. И внес изменения в связи с этим.
- Исправления работы с С
* Fri Feb 13 2026 svk <svk@nuk-svk.ru> 2.0.0-beta4
- Исправлено регулярное выражение для поиска переменных в коде на С.
- Добавил экранирование '*' в имени функции для поиска.
@@ -251,5 +239,3 @@ fi