├── .DS_Store ├── .gitignore ├── .ruby-version ├── README.md ├── Rakefile ├── config.yml ├── icons ├── auto.psd └── battery.psd ├── screenshots ├── .DS_Store ├── Alfred_Preferences_Learning.png ├── battery_2.png ├── callback.png ├── filtered by query.png ├── glance.png ├── help.png ├── mixed top processes.png ├── top_sleep.png └── workflow.png ├── top ├── .DS_Store ├── 2B8AA7B1-2F79-475C-ADEF-6EE35005FCBA.png ├── 2D963FB2-D9CA-4423-AD37-66DAA9B5C6A4.png ├── 65DAE3B3-5040-4117-A911-65EDE5765DC3.png ├── 7DC8A847-D1E3-4D91-B2B5-844E95E7F38A.png ├── Authenticate.app │ └── Contents │ │ ├── Info.plist │ │ ├── MacOS │ │ └── Authenticate │ │ ├── PkgInfo │ │ └── Resources │ │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainMenu.nib │ │ ├── lock.icns │ │ └── lock.png ├── C439BF3F-F4EF-43E6-BFD2-DF8837E2B120.png ├── C844DE84-FBA3-4500-9C91-2A43C2729C1D.png ├── CA714745-B63F-46C5-9D77-50C52956368C.png ├── Gemfile ├── Gemfile.lock ├── README.pdf ├── alfred2_top_workflow.rb ├── bin │ ├── AirPodsPower.sh │ ├── fans_tempsMonitor │ ├── iosnoop.d │ └── smc ├── glance.rb ├── icon.png ├── icon │ ├── .DS_Store │ ├── battery │ │ ├── age.png │ │ ├── airpods-2.png │ │ ├── airpods-3.png │ │ ├── airpods.png │ │ ├── charging.png │ │ ├── clock.png │ │ ├── critical.png │ │ ├── cycles.png │ │ ├── full.png │ │ ├── health.png │ │ ├── low.png │ │ ├── medium.png │ │ ├── power.png │ │ ├── serial.png │ │ └── temp.png │ ├── bluetooth │ │ ├── AppleBluetoothHIDKeyboard.png │ │ ├── BNBMouseDevice.png │ │ └── BNBTrackpadDevice.png │ ├── fan │ │ ├── blue.png │ │ ├── green.png │ │ └── red.png │ ├── process │ │ ├── GPU.png │ │ ├── auto.png │ │ ├── cpu.png │ │ ├── io.png │ │ └── memory.png │ └── temperature │ │ └── GPU.png ├── info.plist ├── lsof.rb ├── setting.yaml ├── sudo.sh ├── top └── update.json └── version.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | top/bundle 2 | top/.bundle 3 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | system 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # System Monitor : An Alfred 3 Workflow. 2 | 3 | ### Take a glance at system performance. List/Kill Top Processes by Memory, Cpu or IO Usage. 4 | 5 | ###### Forked from Zhao Cai as Alfred 2 Top Workflow at https://github.com/zhaocai/alfred2-top-workflow 6 | 7 | 8 | 9 | 10 | ### [💾 Download](https://github.com/singhprd/system-monitor-alfred-workflow/releases/download/1/System.Monitor.alfredworkflow) 11 | 12 | - 1) List/Kill Top Processes by Memory/CPU/IO Usage 13 | 14 |

15 | 16 |

17 | 18 | - 2) Get a glance of system status including internal battery, fan speed, CPU/GPU Temperature, bluetooth battery, disk capacity, etc. 19 | 20 |

21 | 22 |

23 | 24 | ## Usage 25 | 26 | ### 0. Show Help 27 | 28 | Just type `-?`, `-h`, or `--help` after the keyword to show help. 29 | 30 |

31 | 32 |

33 | 34 | ### 1. Top Processes 35 | 36 | #### A. Keywords: 37 | 38 | ##### 1.) `top`: Show a mixed processes list based on top cpu/memory usage. 39 | 40 | 41 | ###### 1. `top -m`, `top --memory` to show processes ranked by memory usage 42 | 43 | ###### 2. `top -c`, `top --cpu`, to show processes ranked by cpu usage 44 | 45 | ###### 3. `top -i`, `top --io`, to show processes ranked by io usage with **callback** from top io trace collector. 46 | 47 | Top IO requires [DTrace][Dtrace] and it would take a while to finish. The new **callback** design is to run the job in he background and post a notification (OSX 10.8+) using notification center. Click on the notification to show the result in alfred. 48 | 49 | ![](https://raw.github.com/zhaocai/alfred2-top-workflow/master/screenshots/callback.png) 50 | 51 | 52 | 53 | ###### **Modifier Key** 54 | 55 | - `none` : The default action is to list files opened by process ID 56 | - `control` : Kill the selected process 57 | - `command` : kill forcefully (`kill -9`) 58 | - `alt` : Nice (lower) the selected process's cpu priority 59 | - `shift` : Search web for process information 60 | 61 | 62 | ##### 2.) `kill`: Filter process to kill. 63 | 64 | ###### **Modifier Key** 65 | 66 | - `none`: The default action is to kill by process ID 67 | - `command` : kill forcefully (`kill -9`) 68 | 69 | ##### 3.) `lsof`: List files opened by process id 70 | 71 | ###### **Modifier Key** 72 | 73 | - `none`: The default action is to reveal file in Finder 74 | 75 | #### B. Filter by Query 76 | 77 | ##### 1.) Type process name to filter 78 | 79 |

80 | 81 |

82 | 83 | 84 | ##### 2.) To search for process state, use **:idle**, **:sleep**, **:stopped**, **:zombie**, **:uninterruptible**, **:runnable**, etc. 85 | 86 |

87 | 88 |

89 | 90 | ### 2. Glance an Eye on your system 91 | 92 | #### A. Keywords: 93 | 94 | 1. `glance`: Show system information including internal battery, bluetooth battery, disk capacity, etc. 95 | 96 |

97 | 98 |

99 | 100 | #### B. Change Display Order 101 | 102 | 1. Activate `Alfred Preferences` → `Advanced` → `Top Result Keyword Latching` 103 | 104 | ![](https://raw.github.com/zhaocai/alfred2-top-workflow/master/screenshots/Alfred_Preferences_Learning.png) 105 | 106 | 2. Hit `Enter` for the feedback item you wish to show up on the top. 107 | 108 | 109 | 110 | ## Installation 111 | 112 | Two ways are provided: 113 | 114 | 1. You can download the latest release from [here](https://github.com/singhprd/system-monitor-alfred-workflow/releases) and import into to Alfred. This method is suitable for **regular users**. 115 | 116 | 2. You can `git clone` or `fork` this repository and use `rake install` and `rake uninstall` to install. Check `rake -T` for available tasks. 117 | This method create a symlink to the alfred workflow directory: "~/Library/Application Support/Alfred 2/Alfred.alfredpreferences/workflows". This method is suitable for **developers**. 118 | 119 | 120 | --- 121 | 122 | ### Forked from Zhao Cai at https://github.com/zhaocai/alfred2--workflow 123 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' unless defined? Gem # rubygems is only needed in 1.8 2 | 3 | require 'yaml' 4 | require 'plist' 5 | 6 | config_file = 'config.yml' 7 | 8 | 9 | # /Users/peter/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows 10 | 11 | workflow_home=File.expand_path("~/Library/Application Support/Alfred 3/Alfred.alfredpreferences/workflows") 12 | 13 | $config = YAML.load_file(config_file) 14 | $config["bundleid"] = "#{$config["domain"]}.#{$config["id"]}" 15 | $config["plist"] = File.join($config["path"], "info.plist") 16 | $config["workflow_dbx"] = File.join(File.expand_path($config["dropbox"]), "/Alfred.alfredpreferences/workflows") 17 | 18 | # import sub-rakefiles 19 | FileList['*/Rakefile'].each { |file| 20 | import file 21 | } 22 | 23 | task :config do 24 | 25 | info = Plist::parse_xml($config["plist"]) 26 | unless info['bundleid'].eql?($config["bundleid"]) 27 | info['bundleid'] = $config["bundleid"] 28 | File.open($config["plist"], "wb") { |file| file.write(info.to_plist) } 29 | end 30 | end 31 | 32 | task :chdir => [:config] do 33 | chdir $config['path'] 34 | end 35 | 36 | desc "Install Gems" 37 | task "bundle:install" => [:chdir] do 38 | sh %Q{bundle install --standalone --clean} do |ok, res| 39 | if ! ok 40 | puts "fail to install gems (status = #{res.exitstatus})" 41 | else 42 | sh %Q{find bundle -type d \\(-name vendor -o -name cache -o -name spec -o -name test \\) -print0 | xargs -0 rm -rf} 43 | end 44 | end 45 | end 46 | 47 | desc "Update Gems" 48 | task "bundle:update" => [:chdir] do 49 | sh %Q{bundle update && bundle install --standalone --clean} do |ok, res| 50 | if ! ok 51 | puts "fail to update gems (status = #{res.exitstatus})" 52 | else 53 | sh %Q{find bundle -type d \\( -name vendor -o -name cache -o -name spec -o -name test \\) -print0 | xargs -0 rm -rf} 54 | end 55 | end 56 | end 57 | 58 | desc "Generate Doc" 59 | task :doc do 60 | sh %Q{pandoc -f markdown -o "#{$config['path']}/README.pdf" README.md} 61 | end 62 | desc "Install to Alfred" 63 | task :install => [:config] do 64 | ln_sf File.expand_path($config["path"]), File.join(workflow_home, $config["bundleid"]) 65 | end 66 | 67 | desc "Unlink from Alfred" 68 | task :uninstall => [:config] do 69 | rm File.join(workflow_home, $config["bundleid"]) 70 | end 71 | 72 | desc "Install to Dropbox" 73 | task :dbxinstall => [:config] do 74 | ln_sf File.expand_path($config["path"]), File.join($config["workflow_dbx"], $config["bundleid"]) 75 | end 76 | 77 | desc "Unlink from Dropbox" 78 | task :dbxuninstall => [:config] do 79 | rm File.join($config["workflow_dbx"], $config["bundleid"]) 80 | end 81 | 82 | desc "Clean up all the extras" 83 | task :clean => [:config] do 84 | end 85 | 86 | desc "Remove any generated file" 87 | task :clobber => [:clean] do 88 | rmtree File.join($config["path"], ".bundle") 89 | rmtree File.join($config["path"], "bundle") 90 | end 91 | 92 | 93 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | --- # bundle id = domain.id 2 | path: top 3 | domain: me.zhaowu 4 | id: top 5 | dropbox: ~/Dropbox/Alfred 6 | 7 | -------------------------------------------------------------------------------- /icons/auto.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/icons/auto.psd -------------------------------------------------------------------------------- /icons/battery.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/icons/battery.psd -------------------------------------------------------------------------------- /screenshots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/.DS_Store -------------------------------------------------------------------------------- /screenshots/Alfred_Preferences_Learning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/Alfred_Preferences_Learning.png -------------------------------------------------------------------------------- /screenshots/battery_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/battery_2.png -------------------------------------------------------------------------------- /screenshots/callback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/callback.png -------------------------------------------------------------------------------- /screenshots/filtered by query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/filtered by query.png -------------------------------------------------------------------------------- /screenshots/glance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/glance.png -------------------------------------------------------------------------------- /screenshots/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/help.png -------------------------------------------------------------------------------- /screenshots/mixed top processes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/mixed top processes.png -------------------------------------------------------------------------------- /screenshots/top_sleep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/top_sleep.png -------------------------------------------------------------------------------- /screenshots/workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/screenshots/workflow.png -------------------------------------------------------------------------------- /top/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/.DS_Store -------------------------------------------------------------------------------- /top/2B8AA7B1-2F79-475C-ADEF-6EE35005FCBA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/2B8AA7B1-2F79-475C-ADEF-6EE35005FCBA.png -------------------------------------------------------------------------------- /top/2D963FB2-D9CA-4423-AD37-66DAA9B5C6A4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/2D963FB2-D9CA-4423-AD37-66DAA9B5C6A4.png -------------------------------------------------------------------------------- /top/65DAE3B3-5040-4117-A911-65EDE5765DC3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/65DAE3B3-5040-4117-A911-65EDE5765DC3.png -------------------------------------------------------------------------------- /top/7DC8A847-D1E3-4D91-B2B5-844E95E7F38A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/7DC8A847-D1E3-4D91-B2B5-844E95E7F38A.png -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 11C74 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDocumentTypes 10 | 11 | CFBundleExecutable 12 | Authenticate 13 | CFBundleIconFile 14 | lock.icns 15 | CFBundleIdentifier 16 | com.BinaryGhost.Authenticate 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | Authenticate 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 1.0 25 | CFBundleSignature 26 | ???? 27 | CFBundleURLTypes 28 | 29 | CFBundleVersion 30 | 1 31 | DTCompiler 32 | com.apple.compilers.llvm.clang.1_0 33 | DTPlatformBuild 34 | 4B110 35 | DTPlatformVersion 36 | GM 37 | DTSDKBuild 38 | 11A511a 39 | DTSDKName 40 | macosx10.7 41 | DTXcode 42 | 0410 43 | DTXcodeBuild 44 | 4B110 45 | LSMinimumSystemVersion 46 | 10.7 47 | NSHumanReadableCopyright 48 | Copyright © 2011 Don Southard. All rights reserved. 49 | NSMainNibFile 50 | MainMenu 51 | NSPrincipalClass 52 | NSApplication 53 | NSServices 54 | 55 | UTExportedTypeDeclarations 56 | 57 | UTImportedTypeDeclarations 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/MacOS/Authenticate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/Authenticate.app/Contents/MacOS/Authenticate -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/Authenticate.app/Contents/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/Resources/en.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/Authenticate.app/Contents/Resources/en.lproj/MainMenu.nib -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/Resources/lock.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/Authenticate.app/Contents/Resources/lock.icns -------------------------------------------------------------------------------- /top/Authenticate.app/Contents/Resources/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/Authenticate.app/Contents/Resources/lock.png -------------------------------------------------------------------------------- /top/C439BF3F-F4EF-43E6-BFD2-DF8837E2B120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/C439BF3F-F4EF-43E6-BFD2-DF8837E2B120.png -------------------------------------------------------------------------------- /top/C844DE84-FBA3-4500-9C91-2A43C2729C1D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/C844DE84-FBA3-4500-9C91-2A43C2729C1D.png -------------------------------------------------------------------------------- /top/CA714745-B63F-46C5-9D77-50C52956368C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/CA714745-B63F-46C5-9D77-50C52956368C.png -------------------------------------------------------------------------------- /top/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "plist" 4 | gem "alfred-workflow" 5 | gem 'mixlib-shellout' 6 | gem 'iStats', :git => 'https://github.com/singhprd/iStats' 7 | -------------------------------------------------------------------------------- /top/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: https://github.com/singhprd/iStats 3 | revision: 7b377e3ce2c0950adc418f3728a566c82f59e602 4 | specs: 5 | iStats (1.5.1) 6 | parseconfig (~> 1.0) 7 | sparkr (~> 0.4) 8 | 9 | GEM 10 | remote: https://rubygems.org/ 11 | specs: 12 | alfred-workflow (2.0.5) 13 | fuzzy_match (>= 2.0.4) 14 | gyoku (>= 1.1.0) 15 | moneta (>= 0.7.19) 16 | nori (>= 2.3.0) 17 | plist (>= 3.1.0) 18 | terminal-notifier (>= 1.5.0) 19 | builder (3.2.3) 20 | fuzzy_match (2.1.0) 21 | gyoku (1.3.1) 22 | builder (>= 2.1.2) 23 | mixlib-shellout (2.3.2) 24 | moneta (1.0.0) 25 | nori (2.6.0) 26 | parseconfig (1.0.8) 27 | plist (3.3.0) 28 | sparkr (0.4.1) 29 | terminal-notifier (1.8.0) 30 | 31 | PLATFORMS 32 | ruby 33 | 34 | DEPENDENCIES 35 | alfred-workflow 36 | iStats! 37 | mixlib-shellout 38 | plist 39 | 40 | BUNDLED WITH 41 | 1.16.0.pre.3 42 | -------------------------------------------------------------------------------- /top/README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/README.pdf -------------------------------------------------------------------------------- /top/alfred2_top_workflow.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # -*- coding: utf-8 -*- 3 | 4 | # ============== = =========================================================== 5 | # Description : Alfred 2 Top Processes Workflow 6 | # Author : Zhao Cai 7 | # HomePage : https://github.com/zhaocai/alfred2-top-workflow 8 | # Date Created : Sun 10 Mar 2013 09:59:48 PM EDT 9 | # Last Modified : Sat 30 Mar 2013 11:39:10 PM EDT 10 | # Tag : [ ruby, alfred, workflow ] 11 | # Copyright : © 2013 by Zhao Cai, 12 | # Released under current GPL license. 13 | # ============== = =========================================================== 14 | 15 | ($LOAD_PATH << File.expand_path("..", __FILE__)).uniq! 16 | 17 | require 'rubygems' unless defined? Gem # rubygems is only needed in 1.8 18 | 19 | require "bundle/bundler/setup" 20 | require "alfred" 21 | 22 | # require handler class on demand 23 | require 'alfred/handler/callback' 24 | 25 | require 'mixlib/shellout' 26 | 27 | 28 | class Integer 29 | def to_human 30 | units = ['', 'K', 'M', 'G', 'T', 'P'] 31 | 32 | size, unit = units.reduce(self.to_f) do |(fsize, _), utype| 33 | fsize > 512 ? [fsize / 1024, utype] : (break [fsize, utype]) 34 | end 35 | 36 | "#{size > 9 || size.modulo(1) < 0.1 ? '%d' : '%.1f'}%s" % [size, unit] 37 | end 38 | end 39 | 40 | class Top < ::Alfred::Handler::Base 41 | 42 | attr_accessor :ignored_processes, :vague_commands 43 | 44 | PS_State = { 45 | :main => { 46 | 'I' => ':idle', 47 | 'R' => ':runnable', 48 | 'S' => ':sleep', 49 | 'T' => ':stopped', 50 | 'U' => ':uninterruptible', 51 | 'Z' => ':zombie', 52 | '?' => ':unknown' 53 | }, 54 | :additional => { 55 | '+' => 'foreground', 56 | '<' => 'raised priority', 57 | '>' => 'soft limit on memory', 58 | 'A' => 'random page replacement', 59 | 'E' => 'trying to exit', 60 | 'L' => 'page locked', 61 | 'N' => 'reduced priority', 62 | 'S' => 'FIO page replacement', 63 | 's' => 'session leader', 64 | 'V' => 'suspended', 65 | 'W' => 'swapped out', 66 | 'X' => 'being traced or debugged' 67 | } 68 | } 69 | 70 | def initialize(alfred, opts = {}) 71 | super 72 | @settings = { 73 | :handler => 'Top' 74 | }.update(opts) 75 | 76 | # Ignore mds because its cpu usgae spikes the moment alfred calls the workflow 77 | @ignored_processes = ['Alfred 2', 'mds'] 78 | 79 | # [TODO] load from @core.workflow_setting @zhaocai @start(2013-10-11) 80 | @vague_commands = [ 81 | 'ruby' , 'java' , 'zsh', 'bash', 'python', 'pythonw', 'perl', 'rsync', 82 | 'macruby' , 'ctags', 'vim', 'Vim' , 'MacVim', 'ag' , 'node' , 'aria2c', 83 | 'osascript', 'caffeinate', 'sleep' 84 | ] 85 | 86 | @io_sample_interval = 15 87 | @callback = ::Alfred::Handler::Callback.new(alfred) 88 | @callback.register 89 | end 90 | 91 | def on_parser 92 | options.sort = :auto 93 | parser.on("-m", "--memory", "sort by memory usage") do 94 | options.sort = :memory 95 | end 96 | parser.on("-c", "--cpu", "sort by cpu usage") do 97 | options.sort = :cpu 98 | end 99 | 100 | parser.on("-i", "--io", "sort by io usage") do 101 | options.sort = :io 102 | end 103 | end 104 | 105 | def on_help 106 | [ 107 | { 108 | :kind => 'text' , 109 | :title => '-c, --cpu [query]' , 110 | :subtitle => 'Sort top processes based on cpu ussage.' , 111 | :autocomplete => "-c #{query}" 112 | }, 113 | { 114 | :kind => 'text' , 115 | :title => '-m, --memory [query]' , 116 | :subtitle => 'Sort top processes based on memory ussage.' , 117 | :autocomplete => "-m #{query}" 118 | }, 119 | { 120 | :kind => 'text' , 121 | :title => '-i, --io [query]' , 122 | :subtitle => 'Sort top processes based on io ussage.' , 123 | :autocomplete => "-i #{query}" 124 | }, 125 | ] 126 | end 127 | 128 | 129 | 130 | def generate_feedback(processes) 131 | processes.each_pair do |_, ps| 132 | if ps[:ignore?] 133 | ps[:order] = ps[:order] + 10 134 | end 135 | 136 | if ps[:icon] 137 | icon = ps[:icon] 138 | else 139 | icon = {:type => "default", :name => "icon/process/#{ps[:type]}.png"} 140 | end 141 | arg = xml_builder( 142 | :handler => @settings[:handler] , 143 | :type => ps[:type] , 144 | :name => ps[:command] , 145 | :pid => ps[:pid] 146 | ) 147 | 148 | feedback.add_item({ 149 | :title => ps[:title] , 150 | :subtitle => ps[:subtitle] , 151 | :arg => arg , 152 | :order => ps[:order] , 153 | :icon => icon , 154 | :match? => :all_title_match? , 155 | }) 156 | end 157 | end 158 | 159 | 160 | def on_feedback 161 | case options.sort 162 | when :auto 163 | psm = list_processes(:memory) 164 | psc = list_processes(:cpu) 165 | 166 | processes = {} 167 | psc.each_pair do |id, p| 168 | m = psm[id] 169 | if m 170 | p[:type] = :auto 171 | p[:title] = "#{p[:order]}/#{m[:order]}: #{p[:command]}" 172 | p[:order] = combined_order(p[:order], m[:order]) 173 | end 174 | processes[id] = p 175 | end 176 | generate_feedback(processes) 177 | when :memory 178 | generate_feedback(list_processes(:memory)) 179 | when :cpu 180 | generate_feedback(list_processes(:cpu)) 181 | when :io 182 | arg = xml_builder( 183 | :handler => @settings[:handler] , 184 | :task => 'callback', 185 | :type => 'iotop' 186 | ) 187 | 188 | feedback.add_item({ 189 | :title => "Collect IO trace to show top IO usage?" , 190 | :subtitle => "Wait for callback after #{@io_sample_interval} seconds." , 191 | :icon => ::Alfred::Feedback.CoreServicesIcon('GenericQuestionMarkIcon') , 192 | :arg => arg , 193 | }) 194 | end 195 | end 196 | 197 | def on_action(arg) 198 | return unless action?(arg) 199 | 200 | if arg[:task] == 'callback' 201 | case arg[:type] 202 | when 'iotop' 203 | 204 | generate_feedback(iotop) 205 | callback_entry = { 206 | :key => arg[:type], 207 | :title => "Top Workflow Callback", 208 | :subtitle => "IO Top", 209 | } 210 | 211 | @callback.on_callback('top', callback_entry, feedback.items ) 212 | end 213 | 214 | else 215 | case options.modifier 216 | when :control 217 | run_and_message("kill #{arg[:pid]}") 218 | when :command 219 | run_and_message("kill -9 #{arg[:pid]}") 220 | when :alt 221 | run_and_message("renice -n 5 #{arg[:pid]}") 222 | when :shift 223 | Alfred::Util.google(%Q{Mac "#{arg[:name]}" process}) 224 | when :none 225 | Alfred.search("lsof #{arg[:pid]}") 226 | end 227 | end 228 | end 229 | 230 | 231 | def iotop 232 | 233 | iosnoop_command = %q{./sudo.sh ./bin/iosnoop.d 2>/dev/null} 234 | iosnoop = Mixlib::ShellOut.new(iosnoop_command) 235 | iosnoop.timeout = @io_sample_interval 236 | 237 | ps = {} 238 | begin 239 | iosnoop.run_command 240 | rescue Mixlib::ShellOut::CommandTimeout 241 | iosnoop.stdout.each_line do |line| 242 | columns = line.force_encoding(Encoding::UTF_8).split('⟩').map(&:strip) 243 | 244 | pid = columns[0].to_i 245 | type = columns[1] 246 | size = columns[2].to_i 247 | command = columns[3] 248 | 249 | if ps.has_key?(pid) 250 | p = ps[pid] 251 | else 252 | p = { 253 | :pid => pid , 254 | :type => :io , 255 | :command => command , 256 | :read_size => 0 , 257 | :write_size => 0 , 258 | } 259 | end 260 | 261 | case type 262 | when 'R' 263 | p[:read_size] += size 264 | when 'W' 265 | p[:write_size] += size 266 | end 267 | 268 | ps[pid] = p 269 | end 270 | end 271 | 272 | return [] if ps.empty? 273 | ranks = {} 274 | i = 1 275 | ps.sort_by { |_, p| p[:read_size] + p[:write_size] }.reverse.each do |pair| 276 | ranks[pair[0]] = i 277 | i += 1 278 | end 279 | ps.each do |_, p| 280 | if p[:pid] > 0 281 | command_line = interpret_command(p, :use_command_line => true).to_s 282 | 283 | m = command_line.match(/(.*\.app\/).*/) 284 | p[:icon] = {:type => "fileicon", :name => m[1]} if m 285 | end 286 | 287 | p[:order] = ranks[p[:pid]] 288 | p[:title] = "#{p[:order]}: #{p[:command]}" 289 | p[:subtitle] = "Read: #{p[:read_size].to_human} ↔ Write: #{p[:write_size].to_human}" 290 | end 291 | 292 | return ps 293 | end 294 | 295 | 296 | private 297 | 298 | def combined_order(by_cpu, by_memory) 299 | order = by_cpu + by_memory 300 | if by_cpu < 3 or by_memory < 3 301 | order = 10 if order > 10 302 | else 303 | order += 10 304 | end 305 | order 306 | end 307 | 308 | 309 | def list_processes(type) 310 | 311 | type2opt = {:memory => 'm', :cpu => 'r'} 312 | 313 | cmd = %Q{ps -a#{type2opt[type]}wwwxo 'pid nice %cpu %mem state comm'} 314 | ps = Mixlib::ShellOut.new(cmd) 315 | ps.run_command 316 | 317 | lines = ps.stdout.lines.map(&:chomp) 318 | lines.shift 319 | 320 | processes = {} 321 | i = 1 322 | lines.each do |entry| 323 | columns = entry.split 324 | 325 | process = { 326 | :line => entry , 327 | :type => type , 328 | :order => i , 329 | :pid => columns[0] , 330 | :nice => columns[1] , 331 | :cpu => columns[2] , 332 | :memory => columns[3] , 333 | :state => interpret_state(columns[4]) , 334 | :command => columns[5..-1].join(" ") , 335 | } 336 | 337 | 338 | process[:icon] = {:type => "fileicon", :name => process[:command]} 339 | m = process[:command].match(/(.*\.app\/).*/) 340 | process[:icon][:name] = m[1] if m 341 | 342 | process[:command] = interpret_command(process) 343 | 344 | # Ignore this script 345 | if process[:command].include?(__FILE__) 346 | next 347 | end 348 | 349 | process[:title] = "#{process[:order]}: #{process[:command]}" 350 | 351 | if @ignored_processes.include?(File.basename(process[:command])) 352 | process[:ignore?] = true 353 | end 354 | 355 | processes[process[:pid]] = process 356 | 357 | process[:subtitle] = "cpu: #{process[:cpu].rjust(6)}%, " \ 358 | "memory: #{process[:memory].rjust(6)}%, " \ 359 | "nice:#{process[:nice].rjust(4)}, " \ 360 | "state:(#{process[:pid].center(8)}) #{process[:state]}" 361 | 362 | i += 1 363 | end 364 | return processes 365 | end 366 | 367 | def interpret_command(process, opts = {}) 368 | command = process[:command] 369 | command_basename = File.basename command 370 | 371 | if @vague_commands.include?(command_basename) || opts[:use_command_line] 372 | cmd = %Q{ps -awwwxo 'command' #{process[:pid]}} 373 | ps = Mixlib::ShellOut.new(cmd) 374 | ps.run_command 375 | 376 | if command_line = ps.stdout.lines.map(&:chomp)[1] 377 | if opts[:use_command_line] 378 | return command_line 379 | else 380 | return %Q{#{command_basename}#{command_line.sub(/^#{Regexp.escape(command)}/, '')}} 381 | end 382 | else 383 | return command_basename 384 | end 385 | else 386 | return command_basename 387 | end 388 | end 389 | 390 | def interpret_state(state) 391 | if state.empty? 392 | return "" 393 | end 394 | 395 | m = "" 396 | 397 | states = state.chars.to_a 398 | 399 | m = PS_State[:main][states.shift] 400 | a = [] 401 | states.each { |c| 402 | a.push(PS_State[:additional][c]) 403 | } 404 | 405 | if a.empty? 406 | return m 407 | else 408 | return "#{m}: #{a.join(',')}" 409 | end 410 | end 411 | 412 | def run_and_message(command, opts = {}) 413 | sh = Mixlib::ShellOut.new(command, opts) 414 | sh.run_command 415 | puts status_message(command, sh.exitstatus) 416 | end 417 | end 418 | 419 | 420 | 421 | 422 | if __FILE__ == $PROGRAM_NAME 423 | 424 | Alfred.with_friendly_error do |alfred| 425 | alfred.with_rescue_feedback = true 426 | alfred.with_help_feedback = true 427 | 428 | Top.new(alfred).register 429 | end 430 | 431 | 432 | end 433 | 434 | 435 | # (# 436 | # Modeline ⟨⟨⟨1 437 | # #) 438 | # vim: set ft=ruby ts=2 sw=2 tw=78 fdm=marker fmr=⟨⟨⟨,⟩⟩⟩ fdl=1 : 439 | -------------------------------------------------------------------------------- /top/bin/AirPodsPower.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # AirPods Battery CLI, Version 2.3 3 | # Contributors: duk242, ankushg, spetykowski, danozdotnet 4 | # Released under the MIT License. 5 | 6 | # The MIT License (MIT) 7 | 8 | # Copyright (c) 2017 Dustin Kerr, and Daniel Jones 9 | 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | 17 | # The above copyright notice and this permission notice shall be included in all 18 | # copies or substantial portions of the Software. 19 | 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | # SOFTWARE. 27 | 28 | # https://github.com/duk242/AirPodsBatteryCLI 29 | 30 | BLUETOOTH_DEFAULTS=$(defaults read /Library/Preferences/com.apple.Bluetooth); SYSTEM_PROFILER=$(system_profiler SPBluetoothDataType) 31 | MAC_ADDR=$(grep -b2 "Minor Type: Headphones"<<<"${SYSTEM_PROFILER}"|awk '/Address/{print $3}') 32 | CONNECTED=$(grep -ia6 "${MAC_ADDR}"<<<"${SYSTEM_PROFILER}"|awk '/Connected: Yes/{print 1}') 33 | BLUETOOTH_DATA=$(grep -ia6 '"'"${MAC_ADDR}"'"'<<<"${BLUETOOTH_DEFAULTS}") 34 | BATTERY_LEVELS=("BatteryPercentCombined" "HeadsetBattery" "BatteryPercentSingle" "BatteryPercentCase" "BatteryPercentLeft" "BatteryPercentRight") 35 | 36 | if [[ "${CONNECTED}" ]]; then 37 | for I in "${BATTERY_LEVELS[@]}"; do 38 | declare -x "${I}"="$(awk -v pat="${I}" '$0~pat{gsub (";",""); print $3 }'<<<"${BLUETOOTH_DATA}")" 39 | [[ ! -z "${!I}" ]] && OUTPUT="${OUTPUT} $(awk '/BatteryPercent/{print substr($0,15,1)": "}'<<<"${I}")${!I}%" 40 | done 41 | printf "%s\\n" "${OUTPUT}" 42 | else 43 | printf "%s Not Connected\\n" "${OUTPUT}" 44 | fi -------------------------------------------------------------------------------- /top/bin/fans_tempsMonitor: -------------------------------------------------------------------------------- 1 | /Users/zhaocai/Software/Theme/GeekTool/fans_tempsMonitor -------------------------------------------------------------------------------- /top/bin/iosnoop.d: -------------------------------------------------------------------------------- 1 | #!/usr/sbin/dtrace -s 2 | 3 | 4 | #pragma D option quiet 5 | #pragma D option switchrate=10hz 6 | 7 | /* 8 | * Init Variables 9 | */ 10 | dtrace:::BEGIN 11 | { 12 | last_event[""] = 0; 13 | } 14 | 15 | 16 | /* 17 | * Reset last_event for disk idle -> start 18 | * this prevents idle time being counted as disk time. 19 | */ 20 | io:::start 21 | /! pending[args[1]->dev_statname]/ 22 | { 23 | /* save last disk event */ 24 | last_event[args[1]->dev_statname] = timestamp; 25 | } 26 | 27 | /* 28 | * Store entry details 29 | */ 30 | io:::start 31 | { 32 | /* these are used as a unique disk event key, */ 33 | this->dev = args[0]->b_edev; 34 | this->blk = args[0]->b_blkno; 35 | 36 | /* save disk event details, */ 37 | start_uid[this->dev, this->blk] = (int)uid; 38 | start_pid[this->dev, this->blk] = pid; 39 | start_ppid[this->dev, this->blk] = ppid; 40 | start_args[this->dev, this->blk] = (char *)curpsinfo->pr_psargs; 41 | start_comm[this->dev, this->blk] = execname; 42 | start_time[this->dev, this->blk] = timestamp; 43 | 44 | /* increase disk event pending count */ 45 | pending[args[1]->dev_statname]++; 46 | } 47 | 48 | /* 49 | * Process and Print completion 50 | */ 51 | io:::done 52 | /start_time[args[0]->b_edev, args[0]->b_blkno]/ 53 | { 54 | /* decrease disk event pending count */ 55 | pending[args[1]->dev_statname]--; 56 | 57 | /* 58 | * Process details 59 | */ 60 | 61 | /* fetch entry values */ 62 | this->dev = args[0]->b_edev; 63 | this->blk = args[0]->b_blkno; 64 | this->suid = start_uid[this->dev, this->blk]; 65 | this->spid = start_pid[this->dev, this->blk]; 66 | this->sppid = start_ppid[this->dev, this->blk]; 67 | self->sargs = (int)start_args[this->dev, this->blk] == 0 ? 68 | "" : start_args[this->dev, this->blk]; 69 | self->scomm = start_comm[this->dev, this->blk]; 70 | this->stime = start_time[this->dev, this->blk]; 71 | this->etime = timestamp; /* endtime */ 72 | this->delta = this->etime - this->stime; 73 | this->dtime = last_event[args[1]->dev_statname] == 0 ? 0 : 74 | timestamp - last_event[args[1]->dev_statname]; 75 | 76 | /* memory cleanup */ 77 | start_uid[this->dev, this->blk] = 0; 78 | start_pid[this->dev, this->blk] = 0; 79 | start_ppid[this->dev, this->blk] = 0; 80 | start_args[this->dev, this->blk] = 0; 81 | start_time[this->dev, this->blk] = 0; 82 | start_comm[this->dev, this->blk] = 0; 83 | start_rw[this->dev, this->blk] = 0; 84 | 85 | /* 86 | * Print details 87 | */ 88 | 89 | printf("%d ⟩ %s ⟩ %d ⟩ %s ⟩ %s ⟩ %s ⟩ %s ⟩ %s\n", 90 | this->spid, 91 | args[0]->b_flags & B_READ ? "R" : "W", 92 | args[0]->b_bcount, 93 | self->scomm, 94 | self->sargs, 95 | args[1]->dev_pathname, 96 | args[2]->fi_mount, 97 | args[2]->fi_pathname 98 | ); 99 | 100 | /* save last disk event */ 101 | last_event[args[1]->dev_statname] = timestamp; 102 | 103 | /* cleanup */ 104 | self->scomm = 0; 105 | self->sargs = 0; 106 | } 107 | 108 | /* 109 | * Prevent pending from underflowing 110 | * this can happen if this program is started during disk events. 111 | */ 112 | io:::done 113 | /pending[args[1]->dev_statname] < 0/ 114 | { 115 | pending[args[1]->dev_statname] = 0; 116 | } 117 | 118 | 119 | 120 | /* 121 | * vim:ft=dtrace:ts=8:sw=4:tw=4:fmr=⟨⟨⟨,⟩⟩⟩:fdm=syntax: 122 | */ 123 | -------------------------------------------------------------------------------- /top/bin/smc: -------------------------------------------------------------------------------- 1 | /usr/local/bin/smc -------------------------------------------------------------------------------- /top/glance.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # -*- coding: utf-8 -*- 3 | ($LOAD_PATH << File.expand_path("..", __FILE__)).uniq! 4 | 5 | require 'rubygems' unless defined? Gem # rubygems is only needed in 1.8 6 | 7 | require "bundle/bundler/setup" 8 | require "alfred" 9 | require 'plist' 10 | require 'yaml' 11 | require 'mixlib/shellout' 12 | require 'iStats' 13 | 14 | class Glance 15 | SMC_KEYS = { 16 | 'TC0P' => 'cpu_temperature', 17 | 'TG0P' => 'gpu_temperature', 18 | 'F0Ac' => 'fan0_speed', 19 | 'F1Ac' => 'fan1_speed', 20 | } 21 | 22 | def self.sh(command, opts = {}) 23 | shell = Mixlib::ShellOut.new(command) 24 | shell.run_command 25 | shell.error! 26 | return shell 27 | end 28 | 29 | def self.with_query(query) 30 | if query[1].eql? '⟩' 31 | return query[2..-1] 32 | else 33 | return query 34 | end 35 | end 36 | 37 | def initialize(alfred, query) 38 | @alfred = alfred 39 | @feedback = @alfred.feedback 40 | if query[1].eql? '⟩' 41 | @actor = query[0].downcase 42 | end 43 | end 44 | 45 | 46 | def collect 47 | collect_battery 48 | collect_temperature 49 | collect_bluetooth 50 | collect_storage 51 | end 52 | 53 | 54 | def collect_temperature 55 | return if @actor 56 | 57 | # temp = IStats::Cpu.delegate("all") 58 | 59 | # > IStats.get_info[:cpu_temperature] 60 | # => {:battery_health_stats=>{:battery_health=>"Good", :max_design_cycle_count=>1000, :cycle_count=>"156", :cycle_count_percentage=>15.6, :thresholds=>[450.0, 650.0, 850.0, 950.0], :battery_temp=>31.796875}, :battery_charge_stats=>{:cur_charge=>"3630", :cur_charge_percentage=>64, :original_max_capacity=>6559.0, :current_max_capacity=>5932.0}, :cpu_temperature=>43.5, :cpu_thresholds=>[50, 68, 80, 90], :fan_numbers_and_speeds=>[[1, 0]]} 61 | 62 | cpu_temperature = IStats.get_info[:cpu_temperature] 63 | icon = {:type => "default", :name => "icon/temperature/GPU.png"} 64 | @feedback.add_item( 65 | :subtitle => "CPU: #{cpu_temperature}° C" , 66 | :title => "CPU Temperature" , 67 | :uid => "CPU Temperature" , 68 | :icon => icon) 69 | 70 | # gpu_temperature = 200 71 | # icon = {:type => "default", :name => "icon/temperature/GPU.png"} 72 | # @feedback.add_item( 73 | # :subtitle => "GPU: #{gpu_temperature}° C" , 74 | # :title => "GPU Temperature" , 75 | # :uid => "GPU Temperature" , 76 | # :icon => icon) 77 | 78 | # [number, speed] 79 | IStats.get_info[:fan_numbers_and_speeds].each{|info_arr| 80 | add_fan_speed_item(info_arr) 81 | } 82 | end 83 | 84 | def add_fan_speed_item(info_arr) 85 | fan_number = info_arr[0] 86 | fan_speed = info_arr[1] 87 | if fan_speed < 3500 88 | icon = {:type => "default", :name => "icon/fan/green.png"} 89 | title = "Fan Speed: Normal" 90 | elsif fan_speed < 5500 91 | icon = {:type => "default", :name => "icon/fan/blue.png"} 92 | title = "Fan Speed: Fast" 93 | else 94 | icon = {:type => "default", :name => "icon/fan/red.png"} 95 | title = "Fan Speed: Driving Crazy!" 96 | end 97 | @feedback.add_item( 98 | :subtitle => "Fan #{fan_number}: #{fan_speed} RPM" , 99 | :uid => "Fan #{fan_number} Speed", 100 | :title => title, 101 | :icon => icon) 102 | 103 | end 104 | 105 | def collect_storage 106 | return if @actor 107 | 108 | devices = %x{/bin/df -H}.split("\n") 109 | 110 | devices.each do |device| 111 | next unless device.start_with? '/dev/' 112 | 113 | items = device.split 114 | size = items[1] 115 | used = items[2] 116 | free = items[3] 117 | percent = items[4][0...-1].to_i 118 | mount_point = items[8..-1].join(" ") 119 | if mount_point.eql? '/' 120 | name = 'Root' 121 | else 122 | name = File.basename(mount_point) 123 | end 124 | @feedback.add_file_item(mount_point, 125 | :title => "#{name}: #{free} free", 126 | :subtitle =>"#{percent}%, #{used} used of #{size} total") 127 | end 128 | end 129 | 130 | 131 | def collect_bluetooth 132 | return if @actor 133 | 134 | bluetooth_device_keys = ["BNBMouseDevice", "AppleBluetoothHIDKeyboard", "BNBTrackpadDevice"] 135 | 136 | bluetooth_device_keys.each do |key| 137 | devices = Plist.parse_xml %x{ioreg -l -n #{key} -r -a} 138 | next if devices.nil? || devices.empty? 139 | 140 | devices.each do |device| 141 | name = device["Product"] 142 | serial = device["SerialNumber"] 143 | percent = device["BatteryPercent"].to_i 144 | icon = {:type => "default", :name => "icon/bluetooth/#{key}.png"} 145 | @feedback.add_item(:subtitle => "#{percentage_sign(percent)} #{percent}%", 146 | :title => "#{name}", 147 | :uid => "#{key}: #{serial}", 148 | :icon => icon) 149 | end 150 | end 151 | 152 | end 153 | 154 | def collect_battery 155 | if @actor.eql? "battery" 156 | show_detailed_feedback = true 157 | else 158 | if @actor 159 | return 160 | else 161 | show_detailed_feedback = false 162 | end 163 | end 164 | 165 | 166 | devices = Plist.parse_xml %x{ioreg -l -n AppleSmartBattery -r -a} 167 | return if devices.nil? || devices.empty? 168 | 169 | devices.each do |device| 170 | current_capacity = device["CurrentCapacity"] 171 | max_capacity = device["MaxCapacity"] 172 | design_capacity = device['DesignCapacity'] 173 | temperature = device['Temperature'].to_f / 100 174 | is_charging = device['IsCharging'] 175 | serial = device['BatterySerialNumber'] 176 | cycle_count = device['CycleCount'] 177 | fully_charged = device['FullyCharged'] 178 | is_external = device['ExternalConnected'] 179 | time_to_full = device['AvgTimeToFull'] 180 | time_to_empty = device['AvgTimeToEmpty'] 181 | manufacture_date = device['ManufactureDate'] 182 | 183 | 184 | day = manufacture_date & 31 185 | month = (manufacture_date >> 5 ) & 15 186 | year = 1980 + (manufacture_date >> 9) 187 | 188 | manufacture_date = Date.new(year, month, day) 189 | # month as unit 190 | age = (Date.today - manufacture_date).to_f / 30 191 | 192 | health = max_capacity * 100 / design_capacity 193 | percent = current_capacity * 100 / max_capacity 194 | 195 | 196 | if percent > 80 197 | icon_name = 'full' 198 | elsif percent > 50 199 | icon_name = 'medium' 200 | elsif percent > 10 201 | icon_name = 'low' 202 | else 203 | icon_name = 'critical' 204 | end 205 | 206 | time_info = 'Charging' 207 | 208 | if is_charging 209 | if time_to_full == 65535 210 | time_info = 'Calculating...' 211 | else 212 | time_info = "#{time_to_full} min until Full" 213 | end 214 | else 215 | if fully_charged 216 | if is_external 217 | time_info = 'On AC Power' 218 | icon_name = 'power' 219 | else 220 | time_info = "#{time_to_empty} min Left" 221 | end 222 | else 223 | time_info = "#{time_to_empty} min Left" 224 | end 225 | end 226 | 227 | if is_charging 228 | status_info = "Charging" 229 | elsif fully_charged 230 | status_info = 'Fully Charged' 231 | else 232 | status_info = "Draining" 233 | end 234 | 235 | icon = {:type => "default", :name => "icon/battery/#{icon_name}.png"} 236 | 237 | battery_item = { 238 | :title => "#{status_info}, #{time_info}" , 239 | :subtitle => "#{percentage_sign(percent)} #{percent}%" , 240 | :uid => "Battery: #{serial}" , 241 | :valid => 'no' , 242 | :autocomplete => 'Battery ⟩ ' , 243 | :icon => icon , 244 | } 245 | 246 | if show_detailed_feedback 247 | battery_item[:valid] = 'yes' 248 | battery_item[:title] = status_info 249 | 250 | @feedback.add_item(battery_item) 251 | 252 | @feedback.add_item( 253 | :title => "#{time_info}", 254 | :subtitle => 'Time', 255 | :icon => {:type => "default", :name => "icon/battery/clock.png"} 256 | ) 257 | @feedback.add_item( 258 | :title => "#{temperature}° C", 259 | :subtitle => 'Temperature', 260 | :icon => {:type => "default", :name => "icon/battery/temp.png"} 261 | ) 262 | @feedback.add_item( 263 | :title => "#{cycle_count} Cycles", 264 | :subtitle => 'Charge Cycles', 265 | :icon => {:type => "default", :name => "icon/battery/cycles.png"} 266 | ) 267 | @feedback.add_item( 268 | :title => "#{health}%", 269 | :subtitle => 'Health', 270 | :icon => {:type => "default", :name => "icon/battery/health.png"} 271 | ) 272 | @feedback.add_item( 273 | :title => "#{serial}", 274 | :subtitle => 'Serial Number', 275 | :match? => :all_title_match?, 276 | :icon => {:type => "default", :name => "icon/battery/serial.png"} 277 | ) 278 | @feedback.add_item( 279 | :title => "#{age.round} months", 280 | :subtitle => 'Age', 281 | :icon => {:type => "default", :name => "icon/battery/age.png"} 282 | ) 283 | else 284 | airpods_battery() 285 | @feedback.add_item(battery_item) 286 | end 287 | end 288 | 289 | end 290 | 291 | private 292 | 293 | def airpods_battery 294 | battery_info_raw = %x{bash ./bin/AirPodsPower.sh} 295 | return if battery_info_raw.include?("Not Connected") 296 | 297 | icon = {:type => "default", :name => "icon/battery/airpods-3.png"} 298 | battery_info = battery_info_raw 299 | .strip 300 | .gsub(" ", "") 301 | .split("%") 302 | .select{|el| 303 | el.split(":")[1] != "0" 304 | } 305 | .map{|el| el+"%"}.join(", ") 306 | .gsub("L:", "Left :") 307 | .gsub("R:", "Right :") 308 | .gsub("C:", "Case :") 309 | 310 | airpods_battery_item = { 311 | :title => "Airpods" , 312 | :subtitle => "#{battery_info}" , 313 | :uid => "Airpods" , 314 | :valid => 'no' , 315 | :autocomplete => 'Airpods ⟩ ' , 316 | :icon => icon , 317 | } 318 | @feedback.add_item(airpods_battery_item) 319 | end 320 | 321 | def percentage_sign(percent, use_sign = :emoji) 322 | if use_sign.eql? :emoji 323 | full = '🔴' 324 | empty = '⚪' 325 | elsif use_sign.eql? :plain 326 | full = '●' 327 | empty = '○' 328 | elsif use_sign.eql? :fruit 329 | signs = ["🍎", "🍎", "🍎", "🍊", "🍊", "🍊", "🍏" , "🍏", "🍏", "🍏", "🍏"] 330 | mark = percent / 10 331 | return signs[0...mark].join 332 | end 333 | mark = percent / 10 334 | sign = '' 335 | mark.times { |_| sign += full } 336 | (10 - mark).times { |_| sign += empty } 337 | sign 338 | end 339 | 340 | end 341 | def generate_feedback(alfred, query) 342 | eye = Glance.new(alfred, query) 343 | eye.collect 344 | 345 | puts alfred.feedback.to_alfred(Glance.with_query(query)) 346 | end 347 | 348 | 349 | if __FILE__ == $PROGRAM_NAME 350 | Alfred.with_friendly_error do |alfred| 351 | alfred.with_rescue_feedback = true 352 | generate_feedback(alfred, ARGV) 353 | end 354 | end 355 | -------------------------------------------------------------------------------- /top/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon.png -------------------------------------------------------------------------------- /top/icon/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/.DS_Store -------------------------------------------------------------------------------- /top/icon/battery/age.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/age.png -------------------------------------------------------------------------------- /top/icon/battery/airpods-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/airpods-2.png -------------------------------------------------------------------------------- /top/icon/battery/airpods-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/airpods-3.png -------------------------------------------------------------------------------- /top/icon/battery/airpods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/airpods.png -------------------------------------------------------------------------------- /top/icon/battery/charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/charging.png -------------------------------------------------------------------------------- /top/icon/battery/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/clock.png -------------------------------------------------------------------------------- /top/icon/battery/critical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/critical.png -------------------------------------------------------------------------------- /top/icon/battery/cycles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/cycles.png -------------------------------------------------------------------------------- /top/icon/battery/full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/full.png -------------------------------------------------------------------------------- /top/icon/battery/health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/health.png -------------------------------------------------------------------------------- /top/icon/battery/low.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/low.png -------------------------------------------------------------------------------- /top/icon/battery/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/medium.png -------------------------------------------------------------------------------- /top/icon/battery/power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/power.png -------------------------------------------------------------------------------- /top/icon/battery/serial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/serial.png -------------------------------------------------------------------------------- /top/icon/battery/temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/battery/temp.png -------------------------------------------------------------------------------- /top/icon/bluetooth/AppleBluetoothHIDKeyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/bluetooth/AppleBluetoothHIDKeyboard.png -------------------------------------------------------------------------------- /top/icon/bluetooth/BNBMouseDevice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/bluetooth/BNBMouseDevice.png -------------------------------------------------------------------------------- /top/icon/bluetooth/BNBTrackpadDevice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/bluetooth/BNBTrackpadDevice.png -------------------------------------------------------------------------------- /top/icon/fan/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/fan/blue.png -------------------------------------------------------------------------------- /top/icon/fan/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/fan/green.png -------------------------------------------------------------------------------- /top/icon/fan/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/fan/red.png -------------------------------------------------------------------------------- /top/icon/process/GPU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/process/GPU.png -------------------------------------------------------------------------------- /top/icon/process/auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/process/auto.png -------------------------------------------------------------------------------- /top/icon/process/cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/process/cpu.png -------------------------------------------------------------------------------- /top/icon/process/io.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/process/io.png -------------------------------------------------------------------------------- /top/icon/process/memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/process/memory.png -------------------------------------------------------------------------------- /top/icon/temperature/GPU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhprd/system-monitor-alfred-workflow/f2a9def95f864743cc5b9bd03a218ba62f5c52a4/top/icon/temperature/GPU.png -------------------------------------------------------------------------------- /top/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | me.zhaowu.top 7 | connections 8 | 9 | 2011A968-7743-480E-A078-3D3602FF8E11 10 | 11 | 12 | destinationuid 13 | C439BF3F-F4EF-43E6-BFD2-DF8837E2B120 14 | modifiers 15 | 0 16 | modifiersubtext 17 | 18 | 19 | 20 | 2B8AA7B1-2F79-475C-ADEF-6EE35005FCBA 21 | 22 | 23 | destinationuid 24 | CFA5D2DB-0DDA-4D3C-9755-3C4DD3A6BA29 25 | modifiers 26 | 0 27 | modifiersubtext 28 | 29 | 30 | 31 | 6DED0FCD-B485-4D7D-A4B7-673C0D34E2D0 32 | 33 | 34 | destinationuid 35 | CA714745-B63F-46C5-9D77-50C52956368C 36 | modifiers 37 | 0 38 | modifiersubtext 39 | 40 | 41 | 42 | 7DC8A847-D1E3-4D91-B2B5-844E95E7F38A 43 | 44 | 45 | destinationuid 46 | A162DE22-9392-4CD1-AA9C-AAC39F6D31F8 47 | modifiers 48 | 0 49 | modifiersubtext 50 | 51 | 52 | 53 | destinationuid 54 | DA167D3F-4147-4632-A672-72656D18E997 55 | modifiers 56 | 1048576 57 | modifiersubtext 58 | Force Kill 59 | 60 | 61 | A162DE22-9392-4CD1-AA9C-AAC39F6D31F8 62 | 63 | 64 | destinationuid 65 | 4F27382C-82E2-4594-91A4-A671F119A335 66 | modifiers 67 | 0 68 | modifiersubtext 69 | 70 | 71 | 72 | CA714745-B63F-46C5-9D77-50C52956368C 73 | 74 | 75 | destinationuid 76 | CE16D203-D372-4FC5-AA16-B8A41ECA3D16 77 | modifiers 78 | 524288 79 | modifiersubtext 80 | nice cpu priority 81 | 82 | 83 | destinationuid 84 | A493B0AC-FD4E-459A-9CFE-2137F39C6249 85 | modifiers 86 | 131072 87 | modifiersubtext 88 | Search for process info online 89 | 90 | 91 | destinationuid 92 | A162DE22-9392-4CD1-AA9C-AAC39F6D31F8 93 | modifiers 94 | 262144 95 | modifiersubtext 96 | kill process 97 | 98 | 99 | destinationuid 100 | 3F4FBD02-B2C3-467A-9976-05BF7556923E 101 | modifiers 102 | 0 103 | modifiersubtext 104 | 105 | 106 | 107 | destinationuid 108 | DA167D3F-4147-4632-A672-72656D18E997 109 | modifiers 110 | 1048576 111 | modifiersubtext 112 | force kill 113 | 114 | 115 | CE16D203-D372-4FC5-AA16-B8A41ECA3D16 116 | 117 | 118 | destinationuid 119 | 638845CE-0394-46AA-85F6-723639C71696 120 | modifiers 121 | 0 122 | modifiersubtext 123 | 124 | 125 | 126 | DA167D3F-4147-4632-A672-72656D18E997 127 | 128 | 129 | destinationuid 130 | 4F27382C-82E2-4594-91A4-A671F119A335 131 | modifiers 132 | 0 133 | modifiersubtext 134 | 135 | 136 | 137 | 138 | createdby 139 | Zhao Cai 140 | description 141 | List/Kill Top Processes by Memory, Cpu or IO Usage 142 | disabled 143 | 144 | name 145 | Top Processes 146 | objects 147 | 148 | 149 | config 150 | 151 | lastpathcomponent 152 | 153 | onlyshowifquerypopulated 154 | 155 | output 156 | 0 157 | removeextension 158 | 159 | sticky 160 | 161 | text 162 | {query} 163 | title 164 | nice cpu priority 165 | 166 | type 167 | alfred.workflow.output.notification 168 | uid 169 | 638845CE-0394-46AA-85F6-723639C71696 170 | version 171 | 0 172 | 173 | 174 | config 175 | 176 | escaping 177 | 38 178 | script 179 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb --workflow-mode=action --modifier=alt "{query}" 180 | type 181 | 0 182 | 183 | type 184 | alfred.workflow.action.script 185 | uid 186 | CE16D203-D372-4FC5-AA16-B8A41ECA3D16 187 | version 188 | 0 189 | 190 | 191 | config 192 | 193 | argumenttype 194 | 1 195 | escaping 196 | 36 197 | keyword 198 | kill 199 | runningsubtext 200 | list processes... 201 | script 202 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb {query} 203 | subtext 204 | Type to filter processes 205 | title 206 | Kill Process 207 | type 208 | 0 209 | withspace 210 | 211 | 212 | type 213 | alfred.workflow.input.scriptfilter 214 | uid 215 | 7DC8A847-D1E3-4D91-B2B5-844E95E7F38A 216 | version 217 | 0 218 | 219 | 220 | config 221 | 222 | escaping 223 | 38 224 | script 225 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb --workflow-mode=action --modifier=shift "{query}" 226 | type 227 | 0 228 | 229 | type 230 | alfred.workflow.action.script 231 | uid 232 | A493B0AC-FD4E-459A-9CFE-2137F39C6249 233 | version 234 | 0 235 | 236 | 237 | config 238 | 239 | escaping 240 | 38 241 | script 242 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb --workflow-mode=action --modifier=control "{query}" 243 | type 244 | 0 245 | 246 | type 247 | alfred.workflow.action.script 248 | uid 249 | A162DE22-9392-4CD1-AA9C-AAC39F6D31F8 250 | version 251 | 0 252 | 253 | 254 | config 255 | 256 | lastpathcomponent 257 | 258 | onlyshowifquerypopulated 259 | 260 | output 261 | 0 262 | removeextension 263 | 264 | sticky 265 | 266 | text 267 | {query} 268 | title 269 | Kill Process 270 | 271 | type 272 | alfred.workflow.output.notification 273 | uid 274 | 4F27382C-82E2-4594-91A4-A671F119A335 275 | version 276 | 0 277 | 278 | 279 | config 280 | 281 | action 282 | 0 283 | argument 284 | 0 285 | hotkey 286 | 0 287 | hotmod 288 | 0 289 | hotstring 290 | 291 | leftcursor 292 | 293 | modsmode 294 | 0 295 | 296 | type 297 | alfred.workflow.trigger.hotkey 298 | uid 299 | 6DED0FCD-B485-4D7D-A4B7-673C0D34E2D0 300 | version 301 | 0 302 | 303 | 304 | config 305 | 306 | escaping 307 | 102 308 | script 309 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb --workflow-mode=action "{query}" 310 | type 311 | 0 312 | 313 | type 314 | alfred.workflow.action.script 315 | uid 316 | 3F4FBD02-B2C3-467A-9976-05BF7556923E 317 | version 318 | 0 319 | 320 | 321 | config 322 | 323 | argumenttype 324 | 1 325 | escaping 326 | 0 327 | keyword 328 | top 329 | runningsubtext 330 | Determining top processes... 331 | script 332 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb {query} 333 | subtext 334 | sort by Memory, CPU, or IO usage 335 | title 336 | Search Top Processes for '{query}' 337 | type 338 | 0 339 | withspace 340 | 341 | 342 | type 343 | alfred.workflow.input.scriptfilter 344 | uid 345 | CA714745-B63F-46C5-9D77-50C52956368C 346 | version 347 | 0 348 | 349 | 350 | config 351 | 352 | escaping 353 | 38 354 | script 355 | LANG=en_US.UTF-8 /usr/bin/ruby ./alfred2_top_workflow.rb --workflow-mode=action --modifier=command "{query}" 356 | type 357 | 0 358 | 359 | type 360 | alfred.workflow.action.script 361 | uid 362 | DA167D3F-4147-4632-A672-72656D18E997 363 | version 364 | 0 365 | 366 | 367 | config 368 | 369 | argumenttype 370 | 0 371 | escaping 372 | 62 373 | keyword 374 | lsof 375 | runningsubtext 376 | waiting... 377 | script 378 | LANG=en_US.UTF-8 /usr/bin/ruby ./lsof.rb {query} 379 | subtext 380 | lsof pid query 381 | title 382 | List Files Opened by Process {query} 383 | type 384 | 0 385 | withspace 386 | 387 | 388 | type 389 | alfred.workflow.input.scriptfilter 390 | uid 391 | 2B8AA7B1-2F79-475C-ADEF-6EE35005FCBA 392 | version 393 | 0 394 | 395 | 396 | type 397 | alfred.workflow.action.revealfile 398 | uid 399 | CFA5D2DB-0DDA-4D3C-9755-3C4DD3A6BA29 400 | version 401 | 0 402 | 403 | 404 | config 405 | 406 | argumenttype 407 | 1 408 | escaping 409 | 0 410 | keyword 411 | glance 412 | runningsubtext 413 | working on it ヽ( ´¬`)ノ 414 | script 415 | LANG=en_US.UTF-8 /usr/bin/ruby ./glance.rb {query} 416 | subtext 417 | Type '{query}' to filter 418 | title 419 | Glances an Eye on your system 420 | type 421 | 0 422 | withspace 423 | 424 | 425 | type 426 | alfred.workflow.input.scriptfilter 427 | uid 428 | C439BF3F-F4EF-43E6-BFD2-DF8837E2B120 429 | version 430 | 0 431 | 432 | 433 | config 434 | 435 | action 436 | 0 437 | argument 438 | 0 439 | hotkey 440 | 0 441 | hotmod 442 | 0 443 | hotstring 444 | 445 | leftcursor 446 | 447 | modsmode 448 | 0 449 | 450 | type 451 | alfred.workflow.trigger.hotkey 452 | uid 453 | 2011A968-7743-480E-A078-3D3602FF8E11 454 | version 455 | 0 456 | 457 | 458 | config 459 | 460 | applescript 461 | on alfred_script(q) tell application "Alfred 2" to search "lsof " & q & " " end alfred_script 462 | 463 | cachescript 464 | 465 | 466 | type 467 | alfred.workflow.action.applescript 468 | uid 469 | A325DFB8-2F81-4919-8541-1365154D5F89 470 | version 471 | 0 472 | 473 | 474 | readme 475 | Lists top ten system processes by CPU or Memory usage. Provide actions to kill. 476 | uidata 477 | 478 | 2011A968-7743-480E-A078-3D3602FF8E11 479 | 480 | ypos 481 | 690 482 | 483 | 2B8AA7B1-2F79-475C-ADEF-6EE35005FCBA 484 | 485 | ypos 486 | 520 487 | 488 | 3F4FBD02-B2C3-467A-9976-05BF7556923E 489 | 490 | ypos 491 | 330 492 | 493 | 4F27382C-82E2-4594-91A4-A671F119A335 494 | 495 | ypos 496 | 270 497 | 498 | 638845CE-0394-46AA-85F6-723639C71696 499 | 500 | ypos 501 | 10 502 | 503 | 6DED0FCD-B485-4D7D-A4B7-673C0D34E2D0 504 | 505 | ypos 506 | 320 507 | 508 | 7DC8A847-D1E3-4D91-B2B5-844E95E7F38A 509 | 510 | ypos 511 | 120 512 | 513 | A162DE22-9392-4CD1-AA9C-AAC39F6D31F8 514 | 515 | ypos 516 | 230 517 | 518 | A325DFB8-2F81-4919-8541-1365154D5F89 519 | 520 | ypos 521 | 1010 522 | 523 | A493B0AC-FD4E-459A-9CFE-2137F39C6249 524 | 525 | ypos 526 | 130 527 | 528 | C439BF3F-F4EF-43E6-BFD2-DF8837E2B120 529 | 530 | ypos 531 | 670 532 | 533 | CA714745-B63F-46C5-9D77-50C52956368C 534 | 535 | ypos 536 | 340 537 | 538 | CE16D203-D372-4FC5-AA16-B8A41ECA3D16 539 | 540 | ypos 541 | 30 542 | 543 | CFA5D2DB-0DDA-4D3C-9755-3C4DD3A6BA29 544 | 545 | ypos 546 | 590 547 | 548 | DA167D3F-4147-4632-A672-72656D18E997 549 | 550 | ypos 551 | 460 552 | 553 | 554 | webaddress 555 | https://github.com/zhaocai/alfred2-top-workflow 556 | 557 | 558 | -------------------------------------------------------------------------------- /top/lsof.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # -*- coding: utf-8 -*- 3 | # ============== = =========================================================== 4 | # Description : Alfred 2 Top Processes Workflow 5 | # Author : Zhao Cai 6 | # HomePage : https://github.com/zhaocai/alfred2-top-workflow 7 | # Version : 0.1 8 | # Date Created : Sun 10 Mar 2013 09:59:48 PM EDT 9 | # Last Modified : Sat 30 Mar 2013 10:48:07 PM EDT 10 | # Tag : [ ruby, alfred, workflow ] 11 | # Copyright : © 2013 by Zhao Cai, 12 | # Released under current GPL license. 13 | # ============== = =========================================================== 14 | 15 | ($LOAD_PATH << File.expand_path("..", __FILE__)).uniq! 16 | 17 | require 'rubygems' unless defined? Gem # rubygems is only needed in 1.8 18 | require "bundle/bundler/setup" 19 | require "alfred" 20 | require 'open3' 21 | 22 | 23 | # OPTIMIZE: use pgrep for name based search 24 | def valid_pid?(pid) 25 | return false if pid.nil? 26 | !pid.match(/[^0-9]/) 27 | end 28 | 29 | def generate_feedback(alfred, pid, with_query) 30 | fb = alfred.feedback 31 | 32 | files = [] 33 | 34 | c = %Q{lsof -p #{pid}} 35 | stdin, stdout, stderr = Open3.popen3(c) 36 | lines = stdout.readlines.map(&:chomp) 37 | 38 | if lines.empty? 39 | # try sudo 40 | c = %Q{./sudo.sh #{c}} 41 | stdin, stdout, stderr = Open3.popen3(c) 42 | lines = stdout.readlines.map(&:chomp) 43 | end 44 | 45 | if lines.empty? 46 | puts alfred.rescue_feedback(:title => "Is #{pid} a valid PID? Or the process has been terminated.") 47 | return false 48 | end 49 | 50 | lines.shift 51 | 52 | lines.each do |entry| 53 | columns = entry.split 54 | f = columns[8..-1] 55 | if f 56 | file = f.join(" ") 57 | files << file if File.exist?(file) 58 | end 59 | end 60 | 61 | files.delete_if { |f| 62 | f.start_with?("/Applications/") or f.eql?('/') or f.eql?('/dev/null') 63 | } 64 | 65 | 66 | files.each do |f| 67 | fb.add_file_item(f) 68 | end 69 | 70 | puts fb.to_alfred(with_query) 71 | end 72 | 73 | if __FILE__ == $PROGRAM_NAME 74 | Alfred.with_friendly_error do |alfred| 75 | 76 | alfred.with_rescue_feedback = true 77 | 78 | pid = ARGV[0] 79 | ARGV.shift 80 | 81 | unless valid_pid?(pid) 82 | puts alfred.rescue_feedback(:title => "Invalid PID: #{pid}") 83 | exit(-1) 84 | end 85 | 86 | generate_feedback(alfred, pid, ARGV) 87 | end 88 | end 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /top/setting.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | :id: me.zhaowu.top 3 | :Homepage : &homepage 4 | http://zhaocai.github.io/alfred2-top-workflow/ 5 | :triviaware : &triviaware 6 | http://triviaware.com/macprocess/all 7 | :macinside : &macinside 8 | http://www.macinside.info/ 9 | :help: 10 | - :kind: url 11 | :title: Homepage 12 | :subtitle: *homepage 13 | :url: *homepage 14 | - :kind: url 15 | :title: MacInside - Apple Mac Process & Security Information 16 | :subtitle: *macinside 17 | :order: 300 18 | :url: *macinside 19 | - :kind: url 20 | :order: 301 21 | :title: Know your Mac OS X processes - Information about your Mac system processes and applications 22 | :subtitle: *triviaware 23 | :url: *triviaware 24 | - :kind: file 25 | :path: README.pdf 26 | 27 | -------------------------------------------------------------------------------- /top/sudo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | PASS=$(Authenticate.app/Contents/MacOS/Authenticate -get password) 3 | if [ "$PASS" = "(null)" ] ; then 4 | Authenticate.app/Contents/MacOS/Authenticate 5 | PASS=$(Authenticate.app/Contents/MacOS/Authenticate -get password) 6 | fi 7 | echo $PASS | sudo -S "$@" 8 | 9 | -------------------------------------------------------------------------------- /top/top: -------------------------------------------------------------------------------- 1 | /Users/peter/Dev/alfred2-top-workflow/top -------------------------------------------------------------------------------- /top/update.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2.0, 3 | "remote_json": "https://github.com/zhaocai/alfred2-top-workflow/raw/master/version.json" 4 | } 5 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2.0, 3 | "download_uri": "https://github.com/zhaocai/alfred2-top-workflow/raw/master/Top%20Processes.alfredworkflow", 4 | "description": "flexible handler framework" 5 | } 6 | --------------------------------------------------------------------------------