projman/lib/files.tcl

471 lines
17 KiB
Tcl

######################################################
# 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
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
}
}
}
switch $fType {
"application" {
if {$fExt ne "json"} {
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 [array names modified] {
if {[info exists modified($nbItem)] == 1 && $modified($nbItem) eq "true"} {
catch {$nbEditor select $nbItem}
# puts "close tab $nbItem"
if {[Close] eq "cancel"} {return "cancel"}
}
}
}
proc Close {} {
global nbEditor modified tree
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)
}
.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 [::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]]
# }
}