Индикатор выполнения в окне Applescript

Я хочу загрузить разные приложения с помощью скрипта bash на macOS.

Поскольку есть несколько больших загрузок (например, Office 365), я хотел бы включить индикатор выполнения в обычное окно macOS.

Скрипт загрузки+установки приложений выглядит так

cd ~/Downloads/ && { curl -O https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg ; cd -; }
sudo hdiutil attach ~/Downloads/googlechrome.dmg
sudo cp -r /Volumes/Google\ Chrome/Google\ Chrome.app /Applications/
diskutil unmount Google\ Chrome

Но это не показывает никакого прогресса для пользователя (скрипт будет работать в фоновом режиме).

Я нашел следующий пример и немного отредактировал его по своему вкусу.

chromedl() {
    osascript <<AppleScript
    set progress description to "Loading"
set progress additional description to "Please wait"
set progress total steps to 3
repeat with i from 1 to 4
   set theSourceCode to do shell script "curl -L -m 30 seconds [url=https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg]https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg]"
   set progress completed steps to i
end repeat
display dialog "Progress bar is complete."
AppleScript

Но это создает ошибку выполнения curl.

Пожалуйста, помогите мне с работающим скриптом Curl Download + Progress Bar.


person LWun    schedule 14.04.2020    source источник
comment
AppleScript не знает о ходе выполнения сценариев оболочки — как вы получаете значения из загрузки, такие как общий и текущий размеры, для использования с индикатором выполнения? Или вы просто ищете неопределенный индикатор (спиннер)?   -  person red_menace    schedule 14.04.2020
comment
@red_menace индикатор выполнения был бы идеальным, но счетчик также был бы решением. Я просто хочу, чтобы у пользователя была визуальная обратная связь о том, что скрипт работает.   -  person LWun    schedule 15.04.2020


Ответы (1)


Базовое окно счетчика прогресса достаточно легко создать с помощью AppleScriptObjectiveC. Скопируйте следующее в редактор сценариев и запустите его на переднем плане (command-control-R или используйте команду меню «Сценарий» → «Выполнить на переднем плане», которая появляется, когда вы удерживаете нажатой клавишу управления).

use framework "AppKit"
use AppleScript version "2.4" -- Yosemite 10.10 or later required
use scripting additions

-- convenience properties to make ASOC more readable
property ca : current application
property NSPanel : class "NSPanel"
property NSView : class "NSView"
property NSProgressIndicator : class "NSProgressIndicator"
property NSTextField : class "NSTextField"

property HUD_mask : 8192
property nonactivating_mask : 128

global progress_panel, progress_indicator, label_field

make_progress_panel()
progress_indicator's startAnimation:me
progress_panel's orderFront:me

-- just hang it out there for 5 seconds as proof of concept
delay 5

progress_panel's |close|()

on make_progress_panel()
    -- make floating panel
    set content_rect to ca's NSMakeRect(200, 800, 140, 80)
    set progress_panel to NSPanel's alloc's initWithContentRect:content_rect styleMask:(HUD_mask + nonactivating_mask) backing:(ca's NSBackingStoreBuffered) defer:true
    set progress_panel's floatingPanel to true

    -- make progress indicator
    set progress_rect to ca's NSMakeRect(0, 0, 40, 40)
    set progress_indicator to NSProgressIndicator's alloc's initWithFrame:progress_rect
    set progress_indicator's indeterminate to true
    set progress_indicator's |style| to 1
    set progress_indicator's translatesAutoresizingMaskIntoConstraints to false

    --make text field
    set label_field to NSTextField's labelWithString:"Downloading"
    set label_field's translatesAutoresizingMaskIntoConstraints to false

    -- make container view, and add subviews
    set content_view to NSView's alloc's initWithFrame:content_rect
    content_view's addSubview:label_field
    content_view's addSubview:progress_indicator
    progress_indicator's sizeToFit()

    set progress_panel's contentView to content_view

    -- view constraints, for alignment
    set pi_y_centering to progress_indicator's centerYAnchor's constraintEqualToAnchor:(content_view's centerYAnchor)
    set lf_y_centering to label_field's centerYAnchor's constraintEqualToAnchor:(content_view's centerYAnchor)
    pi_y_centering's setActive:true
    lf_y_centering's setActive:true

    set lf_left_margin to content_view's leadingAnchor's constraintEqualToAnchor:(label_field's leadingAnchor) |constant|:-10
    lf_left_margin's setActive:true

    set pi_left_margin to label_field's trailingAnchor's constraintEqualToAnchor:(progress_indicator's leadingAnchor) |constant|:-10
    pi_left_margin's setActive:true

    set pi_right_margin to progress_indicator's trailingAnchor's constraintGreaterThanOrEqualToAnchor:(content_view's trailingAnchor) |constant|:10
    pi_left_margin's setActive:true
end make_progress_panel

Я думаю, что самый простой способ заставить это работать с curl — это полностью отсоединить процесс curl и восстановить его pid, например (код в конце отсоединяет процесс и отправляет вывод в забвение, а затем возвращает pid):

set curl_pid to do shell script "curl -L [url=...] &> /dev/null & echo $!"

Когда у вас есть pid, вы можете настроить цикл (или обработчик простоя, если вы создаете приложение) и периодически проверять, активен ли процесс:

try
    set b to do shell script "pgrep curl | grep " & curl_pid
on error
    progress_indicator's stopAnimation:me
    progress_panel's |close|()
end try

Если вам нужен определенный индикатор выполнения, им достаточно легко управлять, но вам нужно придумать способ измерения прогресса. Эта ссылка предполагает, что вы можете получить заголовки сначала для файла и извлеките размер файла; вы можете сравнить это с фактическим размером файла на диске по мере загрузки и ввести соотношение в индикатор выполнения.

person Ted Wrigley    schedule 20.04.2020