1
0
mirror of https://github.com/kepler155c/opus synced 2024-06-13 17:06:54 +00:00

global clipboard plus directory sizes in Files

This commit is contained in:
kepler155c@gmail.com 2017-05-12 01:12:58 -04:00
parent e287958faa
commit ae3ee946e4
8 changed files with 192 additions and 56 deletions

View File

@ -2,6 +2,7 @@ require = requireInjector(getfenv(1))
local Util = require('util') local Util = require('util')
local Event = require('event') local Event = require('event')
local UI = require('ui') local UI = require('ui')
local Config = require('config')
local cleanEnv = Util.shallowCopy(getfenv(1)) local cleanEnv = Util.shallowCopy(getfenv(1))
cleanEnv.require = nil cleanEnv.require = nil
@ -9,10 +10,16 @@ cleanEnv.require = nil
multishell.setTitle(multishell.getCurrent(), 'Files') multishell.setTitle(multishell.getCurrent(), 'Files')
UI:configure('Files', ...) UI:configure('Files', ...)
local config = {
showHidden = false,
showDirSizes = false,
}
Config.load('Files', config)
local copied = { } local copied = { }
local marked = { } local marked = { }
local directories = { } local directories = { }
local hidden = true
local cutMode = false local cutMode = false
function formatSize(size) function formatSize(size)
@ -60,6 +67,7 @@ local Browser = UI.Page {
buttons = { buttons = {
{ text = 'Refresh r', event = 'refresh' }, { text = 'Refresh r', event = 'refresh' },
{ text = 'Hidden ^h', event = 'toggle_hidden' }, { text = 'Hidden ^h', event = 'toggle_hidden' },
{ text = 'Dir Size ^s', event = 'toggle_dirSize' },
UI.Text { }, UI.Text { },
} }
}, },
@ -200,12 +208,18 @@ function Browser:updateDirectory(dir)
dir.totalSize = dir.totalSize + file.size dir.totalSize = dir.totalSize + file.size
file.fsize = formatSize(file.size) file.fsize = formatSize(file.size)
else 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' file.flags = 'D'
end end
if file.isReadOnly then if file.isReadOnly then
file.flags = file.flags .. 'R' file.flags = file.flags .. 'R'
end 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 dir.files[file.fullName] = file
end end
end end
@ -277,15 +291,27 @@ function Browser:eventHandler(event)
self:setStatus('Refreshed') self:setStatus('Refreshed')
elseif event.type == 'toggle_hidden' then elseif event.type == 'toggle_hidden' then
hidden = not hidden config.showHidden = not config.showHidden
Config.update('Files', config)
self:updateDirectory(self.dir) self:updateDirectory(self.dir)
self.grid:draw() self.grid:draw()
if hidden then if not config.showHidden then
self:setStatus('Hiding hidden') self:setStatus('Hiding hidden')
else else
self:setStatus('Displaying hidden') self:setStatus('Displaying hidden')
end 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 elseif event.type == 'mark' and file then
file.marked = not file.marked file.marked = not file.marked
if file.marked then if file.marked then

View File

@ -258,6 +258,10 @@ function page.grid:eventHandler(event)
elseif event.type == 'grid_select' then elseif event.type == 'grid_select' then
page:setPrompt(commandAppend(), true) page:setPrompt(commandAppend(), true)
page:executeStatement(commandAppend()) page:executeStatement(commandAppend())
elseif event.type == 'copy' then
if entry then
clipboard.setData(entry.rawValue)
end
else else
return UI.Grid.eventHandler(self, event) return UI.Grid.eventHandler(self, event)
end end

View File

@ -29,15 +29,36 @@ local fileInfo
local dirty = { y = 1, ey = h } local dirty = { y = 1, ey = h }
local mark = { anchor, active, continue } local mark = { anchor, active, continue }
local keyboard local keyboard
local clipboard = { size, internal }
local searchPattern local searchPattern
local undo = { chain = { }, pointer = 0 } local undo = { chain = { }, pointer = 0 }
local complete = { } local complete = { }
if _G.__CLIPBOARD then if not clipboard then
clipboard = _G.__CLIPBOARD _G.clipboard = { internal, data }
else clipboard.shim = true
_G.__CLIPBOARD = clipboard
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 end
local color = { local color = {
@ -363,7 +384,7 @@ local function redraw()
if not (w < 32 and #sStatus > 0) then if not (w < 32 and #sStatus > 0) then
local clipboardIndicator = 'S' local clipboardIndicator = 'S'
if clipboard.internal then if clipboard.isInternal() then
clipboardIndicator = 'I' clipboardIndicator = 'I'
end end
@ -1016,8 +1037,10 @@ local __actions = {
end, end,
toggle_clipboard = function() toggle_clipboard = function()
clipboard.internal = not clipboard.internal if clipboard.shim then
if clipboard.internal then clipboard.setInternal(not clipboard.internal)
end
if clipboard.isInternal() then
setStatus('Using internal clipboard') setStatus('Using internal clipboard')
else else
setStatus('Using system clipboard') setStatus('Using system clipboard')
@ -1025,10 +1048,11 @@ local __actions = {
end, end,
copy_marked = function() copy_marked = function()
clipboard.lines, clipboard.size = local text, size =
actions.copyText(mark.x, mark.y, mark.ex, mark.ey) actions.copyText(mark.x, mark.y, mark.ex, mark.ey)
setStatus('%d chars copied', clipboard.size) clipboard.setData(text)
clipboard.internal = true setStatus('%d chars copied', size)
clipboard.useInternal(true)
end, end,
cut = function() cut = function()
@ -1049,16 +1073,14 @@ local __actions = {
if mark.active then if mark.active then
actions.delete() actions.delete()
end end
if clipboard.internal then if clipboard.isInternal() then
if clipboard.lines then text = clipboard.getText()
actions.insertText(x, y, clipboard.lines) end
setStatus('%d chars added', clipboard.size) if text then
else
setStatus('Internal clipboard empty')
end
else
actions.insertText(x, y, text) actions.insertText(x, y, text)
setStatus('%d chars added', #text) setStatus('%d chars added', #text)
else
setStatus('Clipboard empty')
end end
end, end,

View File

@ -42,7 +42,6 @@ function socketClass:read(timeout)
local e, id = os.pullEvent() local e, id = os.pullEvent()
if e == 'transport_' .. self.sport then if e == 'transport_' .. self.sport then
data, distance = transport.read(self) data, distance = transport.read(self)
if data then if data then
os.cancelTimer(timerId) os.cancelTimer(timerId)
@ -74,7 +73,6 @@ function socketClass:ping()
transport.write(self, { transport.write(self, {
type = 'PING', type = 'PING',
seq = self.wseq, seq = self.wseq,
data = data,
}) })
return true return true
end end

View File

@ -128,9 +128,27 @@ function Manager:init(args)
end end
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) Event.addHandler('paste', function(h, text)
self:emitEvent({ type = 'paste', text = text }) if clipboard.isInternal() then
self.currentPage:sync() text = clipboard.getData()
end
if text and type(text) == 'string' then
self:emitEvent({ type = 'paste', text = text })
self.currentPage:sync()
end
end) end)
Event.addHandler('char', function(h, ch) Event.addHandler('char', function(h, ch)
@ -431,7 +449,7 @@ end
function Manager:getDefaults(element, args) function Manager:getDefaults(element, args)
local defaults = Util.deepCopy(element.defaults) local defaults = Util.deepCopy(element.defaults)
if args then if args then
Util.merge(defaults, args) Manager.setProperties(defaults, args)
end end
return defaults return defaults
end end
@ -1449,6 +1467,18 @@ UI.Grid.defaults = {
inverseSortIndicator = '^', inverseSortIndicator = '^',
values = { }, values = { },
columns = { }, 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) function UI.Grid:init(args)
local defaults = UI:getDefaults(UI.Grid, 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 if row > 0 and row <= Util.size(self.values) then
self:setIndex(row) self:setIndex(row)
if event.type == 'mouse_doubleclick' then if event.type == 'mouse_doubleclick' then
self:emit({ type = 'key', key = 'enter' }) self:emit({ type = 'key_enter' })
end end
return true return true
end end
elseif event.type == 'key' then return false
if event.key == 'enter' then
if self.selected then elseif event.type == 'scroll_down' then
self:emit({ type = 'grid_select', selected = self.selected }) self:setIndex(self.index + 1)
end elseif event.type == 'scroll_up' then
return true self:setIndex(self.index - 1)
elseif event.key == 'down' then elseif event.type == 'scroll_top' then
self:setIndex(self.index + 1) self:setIndex(1)
elseif event.key == 'up' then elseif event.type == 'scroll_bottom' then
self:setIndex(self.index - 1) self:setIndex(Util.size(self.values))
elseif event.key == 'control-b' or event.key == 'pageUp' then elseif event.type == 'scroll_pageUp' then
self:setIndex(self.index - self.pageSize) self:setIndex(self.index - self.pageSize)
elseif event.key == 'control-f' or event.key == 'pageDown' then elseif event.type == 'scroll_pageDown' then
self:setIndex(self.index + self.pageSize) self:setIndex(self.index + self.pageSize)
elseif event.key == 'home' then elseif event.type == 'key_enter' then
self:setIndex(1) if self.selected then
elseif event.key == 'end' then self:emit({ type = 'grid_select', selected = self.selected })
self:setIndex(Util.size(self.values))
else
return false
end 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 end
return false return true
end end
--[[-- ScrollingGrid --]]-- --[[-- ScrollingGrid --]]--
@ -2776,6 +2809,9 @@ UI.TextEntry.defaults = {
height = 1, height = 1,
limit = 6, limit = 6,
pos = 0, pos = 0,
accelerators = {
[ 'control-c' ] = 'copy',
}
} }
function UI.TextEntry:init(args) function UI.TextEntry:init(args)
local defaults = UI:getDefaults(UI.TextEntry, args) local defaults = UI:getDefaults(UI.TextEntry, args)
@ -2910,6 +2946,9 @@ function UI.TextEntry:eventHandler(event)
end end
return true return true
elseif event.type == 'copy' then
clipboard.setData(self.value)
elseif event.type == 'paste' then elseif event.type == 'paste' then
local input = tostring(self.value) local input = tostring(self.value)
local text = event.text local text = event.text

View 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)

View File

@ -66,7 +66,23 @@ function nativefs.list(node, dir, full)
return files return files
end 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 if node.mountPoint == dir and node.nodes then
return 0 return 0
end end

View File

@ -5,8 +5,6 @@
* write acknowledgements * write acknowledgements
* background read buffering * background read buffering
]]-- ]]--
require = requireInjector(getfenv(1))
local Logger = require('logger')
multishell.setTitle(multishell.getCurrent(), 'Net transport') multishell.setTitle(multishell.getCurrent(), 'Net transport')
@ -53,7 +51,7 @@ while true do
if e == 'timer' then if e == 'timer' then
local socket = transport.timers[timerId] local socket = transport.timers[timerId]
if socket and socket.connected then if socket and socket.connected then
Logger.log('transport', 'timeout - closing socket ' .. socket.sport) print('transport timeout - closing socket ' .. socket.sport)
socket:close() socket:close()
transport.timers[timerId] = nil transport.timers[timerId] = nil
end end
@ -84,7 +82,7 @@ while true do
elseif msg.type == 'DATA' and msg.data then elseif msg.type == 'DATA' and msg.data then
if msg.seq ~= socket.rseq 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() socket:close()
else else
socket.rseq = socket.rseq + 1 socket.rseq = socket.rseq + 1