###################################################### # ProjMan 2 # Distributed under GNU Public License # Author: Sergey Kalinin svk@nuk-svk.ru # Copyright (c) "", 2022, https://nuk-svk.ru ###################################################### # Working with files module ###################################################### namespace eval FileOper { variable types set ::types { {"All files" *} } proc GetFileMimeType {fileFullPath {opt ""}} { global cfgVariables # Проверям наличие программы в системе, если есть то добавляем опции # если нет то используем тиклевый пакет if [file exists $cfgVariables(fileTypeCommand)] { set cmd exec lappend cmd $cfgVariables(fileTypeCommand) foreach _ [split $cfgVariables(fileTypeCommandOptions) " "] { lappend cmd $_ } } else { set cmd [list eval ::fileutil::magic::filetype] } # lappend cmd $activeProject lappend cmd $fileFullPath # puts $cmd catch $cmd pipe # puts $pipe if [regexp -nocase -- {(\w+)/([\w\-_\.]+); charset=([[:alnum:]-]+)} $pipe m fType fExt fCharset] { puts "$fType $fExt $fCharset" } switch $opt { "charset" { if [info exists fCharset] { return $fCharset } } } # линуксовый file не всегда корректно определяет тип файла # используем пакет из tcl lassign [::fileutil::fileType $fileFullPath] fType fBinaryType fBinaryInterp puts "File type is $fType, $fBinaryType, $fBinaryInterp" switch $fType { "binary" { return false } "text" { return text } "image" { return false } default { return false } } } ## GETTING FILE ATTRIBUTES ## proc GetFileAttr {file {opt ""}} { global tcl_platform set fileAttribute "" # get file modify time switch $opt { attr { if {$tcl_platform(platform) == "windows"} { set unixTime [file mtime $file] set modifyTime [clock format $unixTime -format "%d/%m/%Y, %H:%M"] } elseif {$tcl_platform(platform) == "mac"} { } elseif {$tcl_platform(platform) == "unix"} { set unixTime [file mtime $file] set modifyTime [clock format $unixTime -format "%d/%m/%Y, %H:%M"] } return $modifyTime } size { # get file size set size [file size $file] if {$size < 1024} { set fileSize "$size b" } if {$size >= 1024} { set s [expr ($size.0) / 1024] set dot [string first "\." $s] set int [string range $s 0 [expr $dot - 1]] set dec [string range $s [expr $dot + 1] [expr $dot + 2]] set fileSize "$int.$dec Kb" } if {$size >= 1048576} { set s [expr ($size.0) / 1048576] set dot [string first "\." $s] set int [string range $s 0 [expr $dot - 1]] set dec [string range $s [expr $dot + 1] [expr $dot + 2]] set fileSize "$int.$dec Mb" } return $fileSize } } } proc OpenDialog {} { global env project activeProject if [info exists activeProject] { set dir $activeProject } else { set dir $env(HOME) } set fullPath [tk_getOpenFile -initialdir $dir -filetypes $::types -parent .] set file [string range $fullPath [expr [string last "/" $fullPath]+1] end] regsub -all "." $file "_" node set dir [file dirname $fullPath] set file [file tail $fullPath] set name [file rootname $file] set ext [string range [file extension $file] 1 end] if {$fullPath != ""} { # puts $fullPath return $fullPath } else { return } } proc OpenFolderDialog {} { global env activeProject #global tree node types dot env noteBook fontNormal fontBold fileList noteBook projDir activeProject imgDir editor rootDir # set dir $projDir if [info exists activeProject] { set dir $activeProject } else { set dir $env(HOME) } set fullPath [tk_chooseDirectory -initialdir $dir -parent .] # set file [string range $fullPath [expr [string last "/" $fullPath]+1] end] # regsub -all "." $file "_" node # set dir [file dirname $fullPath] # # EditFile .frmBody.frmCat.noteBook.ffiles.frmTreeFiles.treeFiles $node $fullPath # # puts $fullPath # if ![info exists activeProject] { # set activeProject $fullPath # } # .frmStatus.lblGitLogo configure -image git_logo_20x20 # .frmStatus.lblGit configure -text "[::msgcat::mc "Branch"]: [Git::Branches current]" return $fullPath } proc CloseFolder {} { global tree nbEditor activeProject set treeItem [$tree selection] set parent [$tree parent $treeItem] while {$parent ne ""} { set treeItem $parent set parent [$tree parent $treeItem] } set upper [Tree::GetUpperItem $tree $treeItem] if {$parent eq "" && [string match "directory::*" $treeItem] == 1} { # puts "tree root item: $treeItem" set proj [string trimleft $upper "directory::"] foreach nbItem [$nbEditor tabs] { set item [string trimleft [file extension $nbItem] "."] # puts "$upper $item" if [string match "$proj*" $item] { if [$tree exists "file::$item"] { $nbEditor select $nbItem Close } } } set nextProj [$tree next $treeItem] # puts $nextProj set prevProj [$tree prev $treeItem] # puts $prevProj if {$nextProj ne ""} { SetActiveProject [$tree item $nextProj -values] # puts $activeProject } elseif {$prevProj ne ""} { SetActiveProject [$tree item $prevProj -values] # puts $activeProject } else { unset activeProject .frmStatus.lblGitLogo configure -image pixel .frmStatus.lblGit configure -text "" } $tree delete $treeItem unset nextProj unset prevProj } } proc CloseAll {} { global nbEditor modified foreach nb2Item [.frmWork.nbEditor2 tabs] { .frmWork.nbEditor2 forget $nb2Item } if {[lsearch -exact [.frmWork.panelNB panes] .frmWork.nbEditor2] != -1} { .frmWork.panelNB forget .frmWork.nbEditor2 } foreach nbItem [$nbEditor tabs] { catch {$nbEditor select $nbItem} if {[Close] eq "cancel"} { return "cancel" } } } proc Close {} { global nbEditor modified tree editors set nbItem [$nbEditor select] # puts "close tab $nbItem" if {$nbItem == ""} {return} if [info exists modified($nbItem)] { if {$modified($nbItem) eq "true"} { set answer [tk_messageBox -message [::msgcat::mc "File was modifyed"] \ -icon question -type yesnocancel \ -detail [::msgcat::mc "Do you want to save it?"]] switch $answer { yes Save no {} cancel {return "cancel"} } } } $nbEditor forget $nbItem destroy $nbItem set treeItem "file::[string range $nbItem [expr [string last "." $nbItem] +1] end ]" if [$tree exists $treeItem] { # delete all functions from tree item set children [$tree children $treeItem] if {$children ne ""} { foreach i $children { $tree delete $i } } if {[$tree parent $treeItem] eq ""} { $tree delete $treeItem } } if [info exists modified($nbItem)] { unset modified($nbItem) } # puts $nbItem set editors [dict remove $editors $nbItem.frmText.t] .frmStatus.lblPosition configure -text "" .frmStatus.lblEncoding configure -text "" .frmStatus.lblSize configure -text "" NB::NextTab $nbEditor 0 } proc Save {} { global nbEditor tree env activeProject if [info exists activeProject] { set dir $activeProject } else { set dir $env(HOME) } set nbEditorItem [$nbEditor select] puts "Saved editor text: $nbEditorItem" if [string match "*untitled*" $nbEditorItem] { set filePath [tk_getSaveFile -initialdir $dir -filetypes $::types -parent .] if {$filePath eq ""} { return } # set fileName [string range $filePath [expr [string last "/" $filePath]+1] end] set fileName [file tail $filePath] $nbEditor tab $nbEditorItem -text $fileName # set treeitem [Tree::InsertItem $tree {} $filePath "file" $fileName] set lblName "lbl[string range $nbEditorItem [expr [string last "." $nbEditorItem] +1] end]" $nbEditorItem.header.$lblName configure -text $filePath } else { set treeItem "file::[string range $nbEditorItem [expr [string last "." $nbEditorItem] +1] end ]" set filePath [Tree::GetItemID $tree $treeItem] } set editedText [$nbEditorItem.frmText.t get 0.0 end] set f [open $filePath "w+"] puts -nonewline $f $editedText puts "$f was saved" close $f ResetModifiedFlag $nbEditorItem $nbEditor } proc SaveAll {} { } proc Delete {} { set node [$tree selection get] set fullPath [$tree itemcget $node -data] set dir [file dirname $fullPath] set file [file tail $fullPath] set answer [tk_messageBox -message "[::msgcat::mc "Delete file"] \"$file\"?"\ -type yesno -icon question -default yes] case $answer { yes { FileDialog $tree close file delete -force "$fullPath" $tree delete $node $tree configure -redraw 1 return 0 } } } proc ReadFolder {directory {parent ""}} { global tree dir lexers project puts "Read the folder $directory" set rList "" if {[catch {cd $directory}] != 0} { return "" } set parent [Tree::InsertItem $tree $parent $directory "directory" [file tail $directory]] $tree selection set $parent foreach i [$tree children $parent] { $tree delete $i } # if {[ $tree item $parent -open] eq "false"} { # $tree item $parent -open true # } else { # $tree item $parent -open false # } # Проверяем наличие списка каталогов для спецобработки # и если есть читаем в список (ножно для ansible) if {[dict exists $lexers ALL varDirectory] == 1} { foreach i [split [dict get $lexers ALL varDirectory] " "] { # puts "-------- $i" lappend dirListForCheck [string trim $i] } } # Getting an files and directorues lists foreach file [glob -nocomplain *] { lappend rList [list [file join $directory $file]] if [file isdirectory $file] { lappend lstDir $file } else { lappend lstFiles $file } } foreach file [glob -nocomplain .?*] { if {$file ne ".."} { lappend rList [list [file join $directory $file]] if [file isdirectory $file] { lappend lstDir $file } else { lappend lstFiles $file } } } # Sort lists and insert into tree if {[info exists lstDir] && [llength $lstDir] > 0} { foreach f [lsort $lstDir] { set i [Tree::InsertItem $tree $parent [file join $directory $f] "directory" $f] # puts "Tree insert item: $i $f]" ReadFolder [file join $directory $f] $i unset i } } if {[info exists lstFiles] && [llength $lstFiles] > 0} { foreach f [lsort $lstFiles] { Tree::InsertItem $tree $parent [file join $directory $f] "file" $f # puts "Tree insert item: " } } # Чтение структуры файлов в каталоге # пока криво работает # Accept $dir(lib) $directory } proc ReadFile {fileFullPath itemName} { set txt $itemName.frmText.t if ![string match "*untitled*" $itemName] { set file [open "$fileFullPath" r] $txt insert end [chan read -nonewline $file] close $file } # Delete emty last line if {[$txt get {end-1 line} end] eq "\n" || [$txt get {end-1 line} end] eq "\r\n"} { $txt delete {end-1 line} end puts ">[$txt get {end-1 line} end]<" } $txt see 1.0 } proc Edit {fileFullPath {nbEditor .frmWork.nbEditor}} { global tree if {[file exists $fileFullPath] == 0} { return false } else { puts "$fileFullPath File type [::fileutil::magic::filetype $fileFullPath]" set fileType [FileOper::GetFileMimeType $fileFullPath] } switch $fileType { "text" { # return text } "image" { # return image } false { return } } set filePath [file dirname $fileFullPath] set fileName [file tail $fileFullPath] regsub -all {\.|/|\\|\s} $fileFullPath "_" itemName set itemName "$nbEditor.$itemName" set treeItemName [Tree::InsertItem $tree {} $fileFullPath "file" $fileName] # переместим указатель на нужный файл в дереве Tree::SelectItem $treeItemName if {[winfo exists $itemName] == 0} { NB::InsertItem $nbEditor $fileFullPath "file" Editor::Editor $fileFullPath $nbEditor $itemName ReadFile $fileFullPath $itemName $itemName.frmText.t highlight 1.0 end ResetModifiedFlag $itemName $nbEditor $itemName.frmText.t see 1.1 } $nbEditor select $itemName Editor::ReadStructure $itemName.frmText.t $treeItemName GetVariablesFromFile $fileFullPath $itemName.frmText.t.t mark set insert 1.0 $itemName.frmText.t.t see 1.0 focus -force $itemName.frmText.t.t .frmStatus.lblSize configure -text [GetFileAttr $fileFullPath "size"] .frmStatus.lblEncoding configure -text [GetFileMimeType $fileFullPath "charset"] return $itemName } proc FindInFiles {} { global nbEditor activeProject set res "" set txt "" set str "" set nbEditorItem [$nbEditor select] if {$nbEditorItem ne ""} { set txt $nbEditorItem.frmText.t # set txt [focus] set selIndex [$txt tag ranges sel] if {$selIndex ne ""} { set selBegin [lindex [$txt tag ranges sel] 0] set selEnd [lindex [$txt tag ranges sel] 1] set str [$txt get $selBegin $selEnd] # puts $str set res [SearchStringInFolder $str] } } if [FindInFilesDialog $txt $res] { .find.entryFind delete 0 end .find.entryFind insert end $str } } proc ReplaceInFiles {} { global nbEditor return # set selIndex [$txt tag ranges sel] # set selBegin [lindex [$txt tag ranges sel] 0] # set selEnd [lindex [$txt tag ranges sel] 1] # puts [$txt get [$txt tag ranges sel]] # } }