сортировка по клику на заголовок колонки

Вам не хватает чего-то в Far? Вы считаете, что вашу идею стоит услышать? Пишите сюда.
Post Reply
lvmm
Posts: 119
Joined: Thu 15 Apr, 2021 14:31
Has thanked: 8 times
Been thanked: 3 times

сортировка по клику на заголовок колонки

Post by lvmm »

Кмк будет удобно, если по клику на заголовок колонки в панели файлы будут сортироваться по этой колонке, а если уже по ней отсортированы - сортировка реверсировалась бы.
User avatar
citRiks
Posts: 1733
Joined: Fri 25 Oct, 2019 18:18
Has thanked: 610 times
Been thanked: 102 times

сортировка по клику на заголовок колонки

Post by citRiks »

Тема родственная этой, как мне кажется:
ClickToTitleDir — переход к папкам по щелчку на заголовке панели
viewtopic.php?t=11797

Нa уровне самого ФАРа реализовано думаю что не будет никогда,
на уровне скрипта - думаю что можно позаимствовать все нужные идеи из ClickToTitleDir
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

citRiks, да, первое что пришло в голову - именно это :-) Допилить ClickToTitleDir …
User avatar
HaRT
Moderator
Posts: 10806
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 220 times
Been thanked: 357 times

сортировка по клику на заголовок колонки

Post by HaRT »

buniak_a_h wrote: Tue 04 May, 2021 16:40 Допилить ClickToTitleDir
Стоит ли пихать такие разные функции в общий скрипт?! Да и название неподходящее. Вот если бы отдельный сделать… А с новым названием я бы тоже помог, как и с тонкостями логики (предвижу, что они будут).
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

HaRT wrote: Tue 04 May, 2021 16:53 Стоит ли пихать такие разные функции в общий скрипт?! Да и название неподходящее. Вот если бы отдельный сделать… А с новым названием я бы тоже помог, как и с тонкостями логики (предвижу, что они будут).
Да ну нет, конечно. Я имел в виду взять за основу ClickToTitleDir и немного поменять. Возможно, логика там будет даже проще: получить ширины столбцов и координату левой границы панели - просто.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

Всем интересующимся.
Вот такой макрос решает задачу:
  1. local F = far.Flags
  2.  
  3. local ReadConsole = require"BAX.ReadConsole"
  4.  
  5. local ReadConsoleLine = ReadConsole.ReadConsoleLine
  6.  
  7.  
  8.  
  9. Macro{
  10.  
  11.   id="7AEEB668-FFE0-422E-8E2F-0A58C2708997";
  12.  
  13.   area="Shell";
  14.  
  15.   key="MsLClick";
  16.  
  17.   description="Сортировка по клику на заголовке столбца";
  18.  
  19.   condition=function(key, data)
  20.  
  21.    data.Mouse = {X=Mouse.X; Y=Mouse.Y}
  22.  
  23.    local lPan, rPan = APanel, PPanel
  24.  
  25.    if not APanel.Left then
  26.  
  27.     lPan, rPan = rPan, lPan
  28.  
  29.    end
  30.  
  31.    local lgr, rgr = 3, lPan.Width-1
  32.  
  33.    if Mouse.X > rgr then
  34.  
  35.     lgr, rgr = lPan.Width + 4, lPan.Width + rPan.Width-1
  36.  
  37.    end
  38.  
  39.    if Mouse.Y == 1 and
  40.  
  41.       Mouse.X > lgr and
  42.  
  43.       Mouse.X < rgr and
  44.  
  45.       ReadConsoleLine(Mouse.X, 1, 1):match"[^%s|║│]" then
  46.  
  47.     return true
  48.  
  49.    end
  50.  
  51.   end;
  52.  
  53.   action=function(data)
  54.  
  55.    local aMouse = data.Mouse
  56.  
  57.    -- Определяем, тыкнули ли на активной панели
  58.  
  59.    local Rect = panel.GetPanelInfo(nil, 1).PanelRect -- APanel
  60.  
  61.    if not (aMouse.X > Rect.left and aMouse.X < Rect.right) then
  62.  
  63.     Rect = panel.GetPanelInfo(nil, 0).PanelRect -- APanel
  64.  
  65.     if aMouse.X > Rect.left and aMouse.X < Rect.right then
  66.  
  67.      panel.SetActivePanel(nil, 0)
  68.  
  69.     else
  70.  
  71.      return false
  72.  
  73.     end
  74.  
  75.    end
  76.  
  77.    local aColumns = loadstring('return {' .. panel.GetColumnWidths(nil, 1) .. '}')()
  78.  
  79.    local iCol = 1
  80.  
  81.    if #aColumns > 1 then
  82.  
  83.     local l = Rect.left + 1
  84.  
  85.     for i=1,#aColumns do
  86.  
  87.      iCol = i
  88.  
  89.      if aMouse.X > l and aMouse.X < l+aColumns[i] then break end
  90.  
  91.      l = l + aColumns[i]
  92.  
  93.     end
  94.  
  95.    end
  96.  
  97.    local sTypes = panel.GetColumnTypes(nil, 1)
  98.  
  99.    local aTypes = {}
  100.  
  101.    sTypes:gsub( '[^,]+', function(a) table.insert(aTypes, a:sub(1,1)) end)
  102.  
  103.    local Info = panel.GetPanelInfo(nil, 1)
  104.  
  105.    if aTypes[iCol] == 'N' then
  106.  
  107.     -- по имени
  108.  
  109.     if Info.SortMode == F.SM_NAME or Info.SortMode == F.SM_NAMEONLY then
  110.  
  111.      panel.SetSortOrder(nil, 1, band(Info.Flags, F.PFLAGS_REVERSESORTORDER) == 0 )
  112.  
  113.     else
  114.  
  115.      panel.SetSortMode(nil, 1, F.SM_NAME)
  116.  
  117.     end
  118.  
  119.    elseif aTypes[iCol] == 'X' then
  120.  
  121.     -- по расширению
  122.  
  123.     if Info.SortMode == F.SM_EXT then
  124.  
  125.      panel.SetSortOrder(nil, 1, band(Info.Flags, F.PFLAGS_REVERSESORTORDER) == 0)
  126.  
  127.     else
  128.  
  129.      panel.SetSortMode(nil, 1, F.SM_EXT)
  130.  
  131.     end
  132.  
  133.    elseif aTypes[iCol] == 'S' then
  134.  
  135.     -- по размеру
  136.  
  137.     if Info.SortMode == F.SM_SIZE then
  138.  
  139.      panel.SetSortOrder(nil, 1, band(Info.Flags, F.PFLAGS_REVERSESORTORDER) == 0)
  140.  
  141.     else
  142.  
  143.      panel.SetSortMode(nil, 1, F.SM_SIZE)
  144.  
  145.     end
  146.  
  147.    elseif aTypes[iCol] == 'D' or aTypes[iCol] == 'T' then
  148.  
  149.     -- по времени
  150.  
  151.     if Info.SortMode == F.SM_CHTIME or Info.SortMode == F.SM_MTIME or Info.SortMode == F.SM_CTIME then
  152.  
  153.      panel.SetSortOrder(nil, 1, band(Info.Flags, F.PFLAGS_REVERSESORTORDER) == 0)
  154.  
  155.     else
  156.  
  157.      panel.SetSortMode(nil, 1, F.SM_MTIME)
  158.  
  159.     end
  160.  
  161.    elseif aTypes[iCol] == 'L' or aTypes[iCol] == 'T' then
  162.  
  163.     -- по количеству жёстких связей
  164.  
  165.     if Info.SortMode == F.SM_NUMLINKS then
  166.  
  167.      panel.SetSortOrder(nil, 1, band(Info.Flags, F.PFLAGS_REVERSESORTORDER) == 0)
  168.  
  169.     else
  170.  
  171.      panel.SetSortMode(nil, 1, F.SM_NUMLINKS)
  172.  
  173.     end
  174.  
  175.    else
  176.  
  177.     -- не реализовано
  178.  
  179.     far.Message('Не реализовано','',nil,'w')
  180.  
  181.    end
  182.  
  183.   end;
  184.  
  185. }
Ну, правда, не все виды сортировки реализованы. К тому же некоторые виды столбцов я не стал различать (дата - время как по CtrlF5 все). Если надо - легко добавить.

Для удобства скачивания:
Тут было вложение.

P/S. Тема, посвящённая этому макросу, отделена. Сам макрос слегка изменён.
PPS. Вложение куда-то подевалось … Уже второй раз за сегодня
Last edited by buniak_a_h on Fri 07 May, 2021 06:35, edited 2 times in total.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

Ну вот, вроде, реализована сортировка по всем "стандартным" типам колонок (кроме атрибутов). Программа даже короче стала :-)
  1. local F = far.Flags
  2.  
  3. local ReadConsole = require"BAX.ReadConsole"
  4.  
  5. local ReadConsoleLine = ReadConsole.ReadConsoleLine
  6.  
  7.  
  8.  
  9. Macro{
  10.  
  11.   id="7AEEB668-FFE0-422E-8E2F-0A58C2708997";
  12.  
  13.   area="Shell";
  14.  
  15.   key="MsLClick";
  16.  
  17.   description="Сортировка по клику на заголовке столбца";
  18.  
  19.   condition=function(key, data)
  20.  
  21.    data.Mouse = {X=Mouse.X; Y=Mouse.Y}
  22.  
  23.    local lPan, rPan = APanel, PPanel
  24.  
  25.    if not APanel.Left then
  26.  
  27.     lPan, rPan = rPan, lPan
  28.  
  29.    end
  30.  
  31.    local lgr, rgr = 3, lPan.Width-1
  32.  
  33.    if Mouse.X > rgr then
  34.  
  35.     lgr, rgr = lPan.Width + 4, lPan.Width + rPan.Width-1
  36.  
  37.    end
  38.  
  39.    if Mouse.Y == 1 and
  40.  
  41.       Mouse.X > lgr and
  42.  
  43.       Mouse.X < rgr and
  44.  
  45.       ReadConsoleLine(Mouse.X, 1, 1):match"[^%s|║│]" then
  46.  
  47.     return true
  48.  
  49.    end
  50.  
  51.   end;
  52.  
  53.   action=function(data)
  54.  
  55.    local aMouse = data.Mouse
  56.  
  57.    -- Определяем, тыкнули ли на активной панели
  58.  
  59.    local Rect = panel.GetPanelInfo(nil, 1).PanelRect -- APanel
  60.  
  61.    if not (aMouse.X > Rect.left and aMouse.X < Rect.right) then
  62.  
  63.     Rect = panel.GetPanelInfo(nil, 0).PanelRect -- APanel
  64.  
  65.     if aMouse.X > Rect.left and aMouse.X < Rect.right then
  66.  
  67.      panel.SetActivePanel(nil, 0)
  68.  
  69.     else
  70.  
  71.      return false
  72.  
  73.     end
  74.  
  75.    end
  76.  
  77.    local aColumns = loadstring('return {' .. panel.GetColumnWidths(nil, 1) .. '}')()
  78.  
  79.    local iCol = 1
  80.  
  81.    if #aColumns > 1 then
  82.  
  83.     local l = Rect.left + 1
  84.  
  85.     for i=1,#aColumns do
  86.  
  87.      iCol = i
  88.  
  89.      if aMouse.X > l and aMouse.X < l+aColumns[i] then break end
  90.  
  91.      l = l + aColumns[i]
  92.  
  93.     end
  94.  
  95.    end
  96.  
  97.    local sTypes = panel.GetColumnTypes(nil, 1)
  98.  
  99.    local aTypes = {}
  100.  
  101.    sTypes:gsub( '[^,]+', function(a) table.insert(aTypes, a) end)
  102.  
  103.    local Info = panel.GetPanelInfo(nil, 1)
  104.  
  105.    local function SetSortMode(Mode)
  106.  
  107.     if type(Mode) ~= 'table' then Mode = {Mode} end
  108.  
  109.     local function ASCAN(tbl, what)
  110.  
  111.      for i,v in ipairs(tbl) do if v == what then return i end end
  112.  
  113.     end -- ASCAN
  114.  
  115.     if ASCAN(Mode, Info.SortMode) then
  116.  
  117.      panel.SetSortOrder(nil, 1, band(Info.Flags, F.PFLAGS_REVERSESORTORDER) == 0 )
  118.  
  119.     else
  120.  
  121.      panel.SetSortMode(nil, 1, Mode[1])
  122.  
  123.     end
  124.  
  125.    end -- SetSortMode
  126.  
  127.    local aSwitch = {
  128.  
  129.     {'^N.*N$', F.SM_NAMEONLY}; -- Имя без расширения
  130.  
  131.     {'^N', F.SM_NAME};         -- Имя
  132.  
  133.     {'^X', F.SM_EXT};          -- Расширение
  134.  
  135.     {'^S', F.SM_SIZE};         -- Размер файла
  136.  
  137.     {'^P', F.SM_SIZE};         -- Выделенный размер файла
  138.  
  139.     {'^G', F.SM_STREAMSSIZE};  -- Размер потоков файла
  140.  
  141.     {'^[DT]$', F.SM_MTIME};    -- Дата или время последней записи в файл
  142.  
  143.     {'^DM', F.SM_MTIME};       -- Дата и время последней записи в файл
  144.  
  145.     {'^DC', F.SM_CTIME};       -- Дата и время создания файла
  146.  
  147.     {'^DA', F.SM_ATIME};       -- Дата и время последнего доступа к файлу
  148.  
  149.     {'^DE', F.SM_CHTIME};      -- Дата и время изменения файла
  150.  
  151.     {'^Z', F.SM_DESCR};        -- Описание
  152.  
  153.     {'^O', F.SM_OWNER};        -- Владелец
  154.  
  155.     {'^LN', F.SM_NUMLINKS};    -- Колич. жёстких ссылок
  156.  
  157.     {'^F', F.SM_NUMSTREAMS};   -- Количество потоков
  158.  
  159.     {'^A',  nil};              -- Атрибуты - не сортируется
  160.  
  161.    } -- aSwitch
  162.  
  163.    for _,v in ipairs(aSwitch) do
  164.  
  165.     if aTypes[iCol]:match(v[1]) then
  166.  
  167.      if v[2] then
  168.  
  169.       SetSortMode({v[2]})
  170.  
  171.      end
  172.  
  173.     end
  174.  
  175.    end
  176.  
  177.   end;
  178.  
  179. }
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

P/S. Макрос реагирует на клик по имени колонки. Символ под курсором при клике должен быть отличен от пробела и псевдографики - символов |, и . Пи этом при клике по пассивной панели она активируется как в стандарте.
User avatar
HaRT
Moderator
Posts: 10806
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 220 times
Been thanked: 357 times

сортировка по клику на заголовок колонки

Post by HaRT »

buniak_a_h wrote: Thu 06 May, 2021 23:40 Программа даже короче стала
Но где же номер версии? Как потом разбираться, где ошибка обнаружена, где исправлена?
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

Самый первый вариант я написал "на коленке" за полчаса. Второй - немного подумав. Почти сразу. Поэтому надеялся, что первый никто не успел скачать. Оказалось, успели.
На самом деле если скрипт того заслуживает, то я оформлю и в другую тему зашлю. На конференции "Обсуждение макросов". Ну просто неудобно, если скрипт в "рядовых" сообщениях (ответах). Надо в первое сообщение темы.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

сортировка по клику на заголовок колонки

Post by buniak_a_h »

P/S. Сделал я ветку, посвящённую этому макросу.
P/S. Правда, туда, похоже, никто не ходит … :-(
Last edited by buniak_a_h on Sun 09 May, 2021 19:48, edited 1 time in total.
Post Reply

Return to “Предложения и идеи”