mirror of
https://github.com/kepler155c/opus
synced 2025-03-01 07:10:19 +00:00
global clipboard plus directory sizes in Files
This commit is contained in:
parent
e287958faa
commit
ae3ee946e4
@ -2,6 +2,7 @@ require = requireInjector(getfenv(1))
|
||||
local Util = require('util')
|
||||
local Event = require('event')
|
||||
local UI = require('ui')
|
||||
local Config = require('config')
|
||||
|
||||
local cleanEnv = Util.shallowCopy(getfenv(1))
|
||||
cleanEnv.require = nil
|
||||
@ -9,10 +10,16 @@ cleanEnv.require = nil
|
||||
multishell.setTitle(multishell.getCurrent(), 'Files')
|
||||
UI:configure('Files', ...)
|
||||
|
||||
local config = {
|
||||
showHidden = false,
|
||||
showDirSizes = false,
|
||||
}
|
||||
|
||||
Config.load('Files', config)
|
||||
|
||||
local copied = { }
|
||||
local marked = { }
|
||||
local directories = { }
|
||||
local hidden = true
|
||||
local cutMode = false
|
||||
|
||||
function formatSize(size)
|
||||
@ -60,6 +67,7 @@ local Browser = UI.Page {
|
||||
buttons = {
|
||||
{ text = 'Refresh r', event = 'refresh' },
|
||||
{ text = 'Hidden ^h', event = 'toggle_hidden' },
|
||||
{ text = 'Dir Size ^s', event = 'toggle_dirSize' },
|
||||
UI.Text { },
|
||||
}
|
||||
},
|
||||
@ -200,12 +208,18 @@ function Browser:updateDirectory(dir)
|
||||
dir.totalSize = dir.totalSize + file.size
|
||||
file.fsize = formatSize(file.size)
|
||||
else
|
||||
if config.showDirSizes then
|
||||
file.size = fs.getSize(file.fullName, true)
|
||||
|
||||
dir.totalSize = dir.totalSize + file.size
|
||||
file.fsize = formatSize(file.size)
|
||||
end
|
||||
file.flags = 'D'
|
||||
end
|
||||
if file.isReadOnly then
|
||||
file.flags = file.flags .. 'R'
|
||||
end
|
||||
if not hidden or file.name:sub(1, 1) ~= '.' then
|
||||
if config.showHidden or file.name:sub(1, 1) ~= '.' then
|
||||
dir.files[file.fullName] = file
|
||||
end
|
||||
end
|
||||
@ -277,15 +291,27 @@ function Browser:eventHandler(event)
|
||||
self:setStatus('Refreshed')
|
||||
|
||||
elseif event.type == 'toggle_hidden' then
|
||||
hidden = not hidden
|
||||
config.showHidden = not config.showHidden
|
||||
Config.update('Files', config)
|
||||
|
||||
self:updateDirectory(self.dir)
|
||||
self.grid:draw()
|
||||
if hidden then
|
||||
if not config.showHidden then
|
||||
self:setStatus('Hiding hidden')
|
||||
else
|
||||
self:setStatus('Displaying hidden')
|
||||
end
|
||||
|
||||
elseif event.type == 'toggle_dirSize' then
|
||||
config.showDirSizes = not config.showDirSizes
|
||||
Config.update('Files', config)
|
||||
|
||||
self:updateDirectory(self.dir)
|
||||
self.grid:draw()
|
||||
if config.showDirSizes then
|
||||
self:setStatus('Displaying dir sizes')
|
||||
end
|
||||
|
||||
elseif event.type == 'mark' and file then
|
||||
file.marked = not file.marked
|
||||
if file.marked then
|
||||
|
@ -258,6 +258,10 @@ function page.grid:eventHandler(event)
|
||||
elseif event.type == 'grid_select' then
|
||||
page:setPrompt(commandAppend(), true)
|
||||
page:executeStatement(commandAppend())
|
||||
elseif event.type == 'copy' then
|
||||
if entry then
|
||||
clipboard.setData(entry.rawValue)
|
||||
end
|
||||
else
|
||||
return UI.Grid.eventHandler(self, event)
|
||||
end
|
||||
|
@ -29,15 +29,36 @@ local fileInfo
|
||||
local dirty = { y = 1, ey = h }
|
||||
local mark = { anchor, active, continue }
|
||||
local keyboard
|
||||
local clipboard = { size, internal }
|
||||
local searchPattern
|
||||
local undo = { chain = { }, pointer = 0 }
|
||||
local complete = { }
|
||||
|
||||
if _G.__CLIPBOARD then
|
||||
clipboard = _G.__CLIPBOARD
|
||||
else
|
||||
_G.__CLIPBOARD = clipboard
|
||||
if not clipboard then
|
||||
_G.clipboard = { internal, data }
|
||||
clipboard.shim = true
|
||||
|
||||
function clipboard.setData(data)
|
||||
clipboard.data = data
|
||||
if data then
|
||||
clipboard.useInternal(true)
|
||||
end
|
||||
end
|
||||
|
||||
function clipboard.getText()
|
||||
if clipboard.data then
|
||||
return Util.tostring(clipboard.data)
|
||||
end
|
||||
end
|
||||
|
||||
function clipboard.isInternal()
|
||||
return clipboard.internal
|
||||
end
|
||||
|
||||
function clipboard.useInternal(mode)
|
||||
if mode ~= clipboard.mode then
|
||||
clipboard.internal = mode
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local color = {
|
||||
@ -363,7 +384,7 @@ local function redraw()
|
||||
|
||||
if not (w < 32 and #sStatus > 0) then
|
||||
local clipboardIndicator = 'S'
|
||||
if clipboard.internal then
|
||||
if clipboard.isInternal() then
|
||||
clipboardIndicator = 'I'
|
||||
end
|
||||
|
||||
@ -1016,8 +1037,10 @@ local __actions = {
|
||||
end,
|
||||
|
||||
toggle_clipboard = function()
|
||||
clipboard.internal = not clipboard.internal
|
||||
if clipboard.internal then
|
||||
if clipboard.shim then
|
||||
clipboard.setInternal(not clipboard.internal)
|
||||
end
|
||||
if clipboard.isInternal() then
|
||||
setStatus('Using internal clipboard')
|
||||
else
|
||||
setStatus('Using system clipboard')
|
||||
@ -1025,10 +1048,11 @@ local __actions = {
|
||||
end,
|
||||
|
||||
copy_marked = function()
|
||||
clipboard.lines, clipboard.size =
|
||||
local text, size =
|
||||
actions.copyText(mark.x, mark.y, mark.ex, mark.ey)
|
||||
setStatus('%d chars copied', clipboard.size)
|
||||
clipboard.internal = true
|
||||
clipboard.setData(text)
|
||||
setStatus('%d chars copied', size)
|
||||
clipboard.useInternal(true)
|
||||
end,
|
||||
|
||||
cut = function()
|
||||
@ -1049,16 +1073,14 @@ local __actions = {
|
||||
if mark.active then
|
||||
actions.delete()
|
||||
end
|
||||
if clipboard.internal then
|
||||
if clipboard.lines then
|
||||
actions.insertText(x, y, clipboard.lines)
|
||||
setStatus('%d chars added', clipboard.size)
|
||||
else
|
||||
setStatus('Internal clipboard empty')
|
||||
end
|
||||
else
|
||||
if clipboard.isInternal() then
|
||||
text = clipboard.getText()
|
||||
end
|
||||
if text then
|
||||
actions.insertText(x, y, text)
|
||||
setStatus('%d chars added', #text)
|
||||
else
|
||||
setStatus('Clipboard empty')
|
||||
end
|
||||
end,
|
||||
|
||||
|
@ -42,7 +42,6 @@ function socketClass:read(timeout)
|
||||
local e, id = os.pullEvent()
|
||||
|
||||
if e == 'transport_' .. self.sport then
|
||||
|
||||
data, distance = transport.read(self)
|
||||
if data then
|
||||
os.cancelTimer(timerId)
|
||||
@ -74,7 +73,6 @@ function socketClass:ping()
|
||||
transport.write(self, {
|
||||
type = 'PING',
|
||||
seq = self.wseq,
|
||||
data = data,
|
||||
})
|
||||
return true
|
||||
end
|
||||
|
@ -128,9 +128,27 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.addHandler('mouse_drag', function(h, button, x, y)
|
||||
|
||||
if self.target then
|
||||
local event = self:pointToChild(self.target, x, y)
|
||||
|
||||
-- revisit - should send out scroll_up and scroll_down events
|
||||
-- let the element convert them to up / down
|
||||
self:inputEvent(event.element,
|
||||
{ type = 'mouse_drag', button = button, x = event.x, y = event.y })
|
||||
self.currentPage:sync()
|
||||
end
|
||||
end)
|
||||
|
||||
Event.addHandler('paste', function(h, text)
|
||||
self:emitEvent({ type = 'paste', text = text })
|
||||
self.currentPage:sync()
|
||||
if clipboard.isInternal() then
|
||||
text = clipboard.getData()
|
||||
end
|
||||
if text and type(text) == 'string' then
|
||||
self:emitEvent({ type = 'paste', text = text })
|
||||
self.currentPage:sync()
|
||||
end
|
||||
end)
|
||||
|
||||
Event.addHandler('char', function(h, ch)
|
||||
@ -431,7 +449,7 @@ end
|
||||
function Manager:getDefaults(element, args)
|
||||
local defaults = Util.deepCopy(element.defaults)
|
||||
if args then
|
||||
Util.merge(defaults, args)
|
||||
Manager.setProperties(defaults, args)
|
||||
end
|
||||
return defaults
|
||||
end
|
||||
@ -1449,6 +1467,18 @@ UI.Grid.defaults = {
|
||||
inverseSortIndicator = '^',
|
||||
values = { },
|
||||
columns = { },
|
||||
accelerators = {
|
||||
enter = 'key_enter',
|
||||
[ 'control-c' ] = 'copy',
|
||||
down = 'scroll_down',
|
||||
up = 'scroll_up',
|
||||
home = 'scroll_top',
|
||||
[ 'end' ] = 'scroll_bottom',
|
||||
pageUp = 'scroll_pageUp',
|
||||
[ 'control-b' ] = 'scroll_pageUp',
|
||||
pageDown = 'scroll_pageDown',
|
||||
[ 'control-f' ] = 'scroll_pageDown',
|
||||
},
|
||||
}
|
||||
function UI.Grid:init(args)
|
||||
local defaults = UI:getDefaults(UI.Grid, args)
|
||||
@ -1772,34 +1802,37 @@ function UI.Grid:eventHandler(event)
|
||||
if row > 0 and row <= Util.size(self.values) then
|
||||
self:setIndex(row)
|
||||
if event.type == 'mouse_doubleclick' then
|
||||
self:emit({ type = 'key', key = 'enter' })
|
||||
self:emit({ type = 'key_enter' })
|
||||
end
|
||||
return true
|
||||
end
|
||||
elseif event.type == 'key' then
|
||||
if event.key == 'enter' then
|
||||
if self.selected then
|
||||
self:emit({ type = 'grid_select', selected = self.selected })
|
||||
end
|
||||
return true
|
||||
elseif event.key == 'down' then
|
||||
self:setIndex(self.index + 1)
|
||||
elseif event.key == 'up' then
|
||||
self:setIndex(self.index - 1)
|
||||
elseif event.key == 'control-b' or event.key == 'pageUp' then
|
||||
self:setIndex(self.index - self.pageSize)
|
||||
elseif event.key == 'control-f' or event.key == 'pageDown' then
|
||||
self:setIndex(self.index + self.pageSize)
|
||||
elseif event.key == 'home' then
|
||||
self:setIndex(1)
|
||||
elseif event.key == 'end' then
|
||||
self:setIndex(Util.size(self.values))
|
||||
else
|
||||
return false
|
||||
return false
|
||||
|
||||
elseif event.type == 'scroll_down' then
|
||||
self:setIndex(self.index + 1)
|
||||
elseif event.type == 'scroll_up' then
|
||||
self:setIndex(self.index - 1)
|
||||
elseif event.type == 'scroll_top' then
|
||||
self:setIndex(1)
|
||||
elseif event.type == 'scroll_bottom' then
|
||||
self:setIndex(Util.size(self.values))
|
||||
elseif event.type == 'scroll_pageUp' then
|
||||
self:setIndex(self.index - self.pageSize)
|
||||
elseif event.type == 'scroll_pageDown' then
|
||||
self:setIndex(self.index + self.pageSize)
|
||||
elseif event.type == 'key_enter' then
|
||||
if self.selected then
|
||||
self:emit({ type = 'grid_select', selected = self.selected })
|
||||
end
|
||||
return true
|
||||
elseif event.type == 'copy' then
|
||||
if self.selected then
|
||||
clipboard.setData(Util.tostring(self.selected))
|
||||
clipboard.useInternal(true)
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
return false
|
||||
return true
|
||||
end
|
||||
|
||||
--[[-- ScrollingGrid --]]--
|
||||
@ -2776,6 +2809,9 @@ UI.TextEntry.defaults = {
|
||||
height = 1,
|
||||
limit = 6,
|
||||
pos = 0,
|
||||
accelerators = {
|
||||
[ 'control-c' ] = 'copy',
|
||||
}
|
||||
}
|
||||
function UI.TextEntry:init(args)
|
||||
local defaults = UI:getDefaults(UI.TextEntry, args)
|
||||
@ -2910,6 +2946,9 @@ function UI.TextEntry:eventHandler(event)
|
||||
end
|
||||
return true
|
||||
|
||||
elseif event.type == 'copy' then
|
||||
clipboard.setData(self.value)
|
||||
|
||||
elseif event.type == 'paste' then
|
||||
local input = tostring(self.value)
|
||||
local text = event.text
|
||||
|
33
sys/extensions/clipboard.lua
Normal file
33
sys/extensions/clipboard.lua
Normal file
@ -0,0 +1,33 @@
|
||||
_G.clipboard = { internal, data }
|
||||
|
||||
function clipboard.getData()
|
||||
return clipboard.data
|
||||
end
|
||||
|
||||
function clipboard.setData(data)
|
||||
clipboard.data = data
|
||||
if data then
|
||||
clipboard.useInternal(true)
|
||||
end
|
||||
end
|
||||
|
||||
function clipboard.getText()
|
||||
if clipboard.data then
|
||||
return Util.tostring(clipboard.data)
|
||||
end
|
||||
end
|
||||
|
||||
function clipboard.isInternal()
|
||||
return clipboard.internal
|
||||
end
|
||||
|
||||
function clipboard.useInternal(mode)
|
||||
if mode ~= clipboard.mode then
|
||||
clipboard.internal = mode
|
||||
os.queueEvent('clipboard_mode', mode)
|
||||
end
|
||||
end
|
||||
|
||||
multishell.addHotkey(20, function()
|
||||
clipboard.useInternal(not clipboard.isInternal())
|
||||
end)
|
@ -66,7 +66,23 @@ function nativefs.list(node, dir, full)
|
||||
return files
|
||||
end
|
||||
|
||||
function nativefs.getSize(node, dir)
|
||||
function nativefs.getSize(node, dir, recursive)
|
||||
if recursive and fs.native.isDir(dir) then
|
||||
local function sum(dir)
|
||||
local total = 0
|
||||
local files = fs.native.list(dir)
|
||||
for _,f in ipairs(files) do
|
||||
local fullName = fs.combine(dir, f)
|
||||
if fs.native.isDir(fullName) then
|
||||
total = total + sum(fullName)
|
||||
else
|
||||
total = total + fs.native.getSize(fullName)
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
return sum(dir)
|
||||
end
|
||||
if node.mountPoint == dir and node.nodes then
|
||||
return 0
|
||||
end
|
||||
|
@ -5,8 +5,6 @@
|
||||
* write acknowledgements
|
||||
* background read buffering
|
||||
]]--
|
||||
require = requireInjector(getfenv(1))
|
||||
local Logger = require('logger')
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'Net transport')
|
||||
|
||||
@ -53,7 +51,7 @@ while true do
|
||||
if e == 'timer' then
|
||||
local socket = transport.timers[timerId]
|
||||
if socket and socket.connected then
|
||||
Logger.log('transport', 'timeout - closing socket ' .. socket.sport)
|
||||
print('transport timeout - closing socket ' .. socket.sport)
|
||||
socket:close()
|
||||
transport.timers[timerId] = nil
|
||||
end
|
||||
@ -84,7 +82,7 @@ while true do
|
||||
|
||||
elseif msg.type == 'DATA' and msg.data then
|
||||
if msg.seq ~= socket.rseq then
|
||||
Logger.log('transport', 'seq error - closing socket ' .. socket.sport)
|
||||
print('transport seq error - closing socket ' .. socket.sport)
|
||||
socket:close()
|
||||
else
|
||||
socket.rseq = socket.rseq + 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user