diff --git a/.gitmodules b/.gitmodules index db4c6d6e..6114f6bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "dotfiles/config/taffybar/taffybar"] path = dotfiles/config/taffybar/taffybar - url = ../taffybar.git + url = ../../travitch/taffybar.git [submodule "dotfiles/xmonad/xmonad"] path = dotfiles/config/xmonad/xmonad url = ../xmonad.git diff --git a/dotfiles/config/taffybar/imalison-taffybar.cabal b/dotfiles/config/taffybar/imalison-taffybar.cabal index 08ee9de4..c6e204b9 100644 --- a/dotfiles/config/taffybar/imalison-taffybar.cabal +++ b/dotfiles/config/taffybar/imalison-taffybar.cabal @@ -18,10 +18,12 @@ executable imalison-taffybar , containers , directory , filepath + , gtk-strut , gi-gtk , glib , gtk3>=0.14.8 , gtk-sni-tray + , hslogger , mtl , haskell-gi-base , process diff --git a/dotfiles/config/taffybar/stack.yaml b/dotfiles/config/taffybar/stack.yaml index 48c92054..fd49b6b2 100644 --- a/dotfiles/config/taffybar/stack.yaml +++ b/dotfiles/config/taffybar/stack.yaml @@ -8,16 +8,10 @@ packages: git: git@github.com:willdonnelly/dyre.git commit: 11412752b483135e0c151ab90be17b217f837c4b extra-dep: true -- location: - git: git@github.com:IvanMalison/gtk-traymanager.git - commit: 517b24722b2cdab2dadbafa882ffcb6b8a1d01ff - extra-dep: true - location: ../xmonad/xmonad-contrib extra-dep: true - location: ../../../../Projects/status-notifier-item extra-dep: true -- location: ../../../../Projects/haskell-dbus - extra-dep: true - location: ../../../../Projects/gtk-sni-tray extra-dep: true - location: @@ -27,19 +21,24 @@ packages: - gtk extra-dep: true extra-deps: -- spool-0.1 - X11-xft-0.3.1 -- gio-0.13.4.1 -- libxml-sax-0.7.5 -- rate-limit-1.1.1 -- time-units-1.0.0 -- xml-helpers-1.0.0 -- gi-dbusmenugtk3-0.4.1 +- dbus-1.0.0 - gi-dbusmenu-0.4.1 +- gi-dbusmenugtk3-0.4.1 - gi-gdk-3.0.15 - gi-gdkpixbuf-2.0.15 -- gi-gtk-3.0.21 +- gi-gdkx11-3.0.2 - gi-gio-2.0.16 +- gi-gtk-3.0.21 - gi-pango-1.0.16 -resolver: lts-10.5 +- gi-xlib-2.0.2 +- gio-0.13.4.1 +- gtk-strut-0.1.2.0 +- gtk-traymanager-1.0.1 +- libxml-sax-0.7.5 +- rate-limit-1.1.1 +- spool-0.1 +- time-units-1.0.0 +- xml-helpers-1.0.0 +resolver: lts-11.4 allow-newer: true diff --git a/dotfiles/config/taffybar/taffybar b/dotfiles/config/taffybar/taffybar index f7673d90..1c2dbadc 160000 --- a/dotfiles/config/taffybar/taffybar +++ b/dotfiles/config/taffybar/taffybar @@ -1 +1 @@ -Subproject commit f7673d90530183aa97d86000dc3160ca784fa492 +Subproject commit 1c2dbadc40ce23a54a465bc072b1fce208c9be7e diff --git a/dotfiles/config/taffybar/taffybar.hs b/dotfiles/config/taffybar/taffybar.hs index 1758d1c3..ff7f8d1c 100644 --- a/dotfiles/config/taffybar/taffybar.hs +++ b/dotfiles/config/taffybar/taffybar.hs @@ -11,9 +11,10 @@ import Data.List import Data.List.Split import qualified Data.Map as M import Data.Maybe +import Debug.Trace import Foreign.ForeignPtr import Foreign.Ptr -import qualified GI.Gtk.Objects.Widget as GI +import qualified GI.Gtk as GI import qualified "gtk3" Graphics.UI.Gtk as Gtk import qualified "gtk3" Graphics.UI.Gtk.Abstract.Widget as W import qualified "gtk3" Graphics.UI.Gtk.Layout.Table as T @@ -23,10 +24,13 @@ import System.Directory import System.Environment import System.FilePath.Posix import System.Glib.GObject +import System.IO import System.Information.CPU import System.Information.EWMHDesktopInfo import System.Information.Memory import System.Information.X11DesktopInfo +import System.Log.Handler.Simple +import System.Log.Logger import System.Process import System.Taffybar import System.Taffybar.Battery @@ -34,14 +38,13 @@ import System.Taffybar.IconImages import System.Taffybar.LayoutSwitcher import System.Taffybar.MPRIS2 import System.Taffybar.NetMonitor -import System.Taffybar.Pager import System.Taffybar.SimpleClock +import System.Taffybar.SimpleConfig import System.Taffybar.Systray import System.Taffybar.ToggleMonitor import System.Taffybar.Widgets.PollingGraph import System.Taffybar.WindowSwitcher import System.Taffybar.WorkspaceHUD -import System.Taffybar.WorkspaceSwitcher import Text.Printf import Text.Read hiding (lift) import Unsafe.Coerce @@ -123,28 +126,6 @@ underlineWidget cfg buildWidget name = do return $ Gtk.toWidget t -movableWidget builder = - do - -- Delay creation of the widget or else failure from trying to get screen - widVar <- MV.newEmptyMVar - let moveWidget = do - isEmpty <- MV.isEmptyMVar widVar - when isEmpty $ - do - putwid <- builder - MV.putMVar widVar putwid - wid <- MV.readMVar widVar - hbox <- Gtk.hBoxNew False 0 - parent <- Gtk.widgetGetParent wid - if isJust parent - then - Gtk.widgetReparent wid hbox - else - Gtk.containerAdd hbox wid - Gtk.widgetShowAll hbox - return $ Gtk.toWidget hbox - return moveWidget - myFormatEntry wsNames ((ws, wtitle, wclass), _) = printf "%s: %s - %s" wsName (head $ splitOn "\NUL" wclass) wtitle where @@ -157,18 +138,28 @@ getInterfaces = do addClass klass action = do widget <- action - widgetSetClass widget klass + lift $ widgetSetClass widget klass return widget (buildWidgetCons, _) = mkWidget buildSNITray = do - GI.Widget trayGIWidgetMP <- buildTrayWithHost + -- XXX: this won't work for multiple taffybars because it will attempt to + -- register a second host with a name that already exists on the dbus tray. + -- Need to take an approach similar to that of gtk-sni-tray to get that to + -- work. + GI.Widget trayGIWidgetMP <- buildTrayWithHost GI.OrientationHorizontal wrapNewGObject mkWidget (castPtr <$> disownManagedPtr trayGIWidgetMP) +logDebug = do + handler <- streamHandler stdout DEBUG + logger <- getLogger "System.Taffybar" + saveGlobalLogger $ setLevel DEBUG logger + main = do interfaceNames <- getInterfaces homeDirectory <- getHomeDirectory + logDebug let resourcesDirectory = homeDirectory ".lib" "resources" inResourcesDirectory file = resourcesDirectory file highContrastDirectory = @@ -232,25 +223,29 @@ main = do -- ] , showWorkspaceFn = hideEmpty , updateRateLimitMicroseconds = 100000 - , updateOnWMIconChange = True , debugMode = False , labelSetter = workspaceNamesLabelSetter } netMonitor = netMonitorMultiNew 1.5 interfaceNames - pagerConfig = - defaultPagerConfig - {useImages = True, windowSwitcherFormatter = myFormatEntry} -- makeUnderline = underlineWidget myHUDConfig - pgr <- pagerNew pagerConfig + -- pgr <- pagerNew pagerConfig -- tray2 <- movableWidget tray - let hud = buildWorkspaceHUD myHUDConfig pgr - los = layoutSwitcherNew pgr - wnd = windowSwitcherNew pgr - taffyConfig = - defaultTaffybarConfig + let hud = buildWorkspaceHUD myHUDConfig + los = layoutSwitcherNew defaultLayoutSwitcherConfig + wnd = windowSwitcherNew defaultWindowSwitcherConfig + simpleTaffyConfig = + defaultSimpleTaffyConfig { startWidgets = [hud, los, addClass "WindowSwitcher" wnd] , endWidgets = [ batteryBarNewWithFormat defaultBatteryConfig "$percentage$% ($time$) - $status$" 1.0 +||||||| merged common ancestors + , endWidgets = + [ batteryBarNew defaultBatteryConfig 1.0 +======= + , centerWidgets = [] + , endWidgets = map lift + [ batteryBarNew defaultBatteryConfig 1.0 +>>>>>>> b44e57a9f4ec822e99649b1ccc5516cbcbad4fb8 , makeContents clock "Cpu" -- , makeContents systrayNew "Cpu" , makeContents buildSNITray "Cpu" @@ -261,10 +256,10 @@ main = do ] , barPosition = Top , barPadding = 5 - , barHeight = (underlineHeight myHUDConfig + windowIconSize myHUDConfig + 10) + , barHeight = (underlineHeight myHUDConfig + windowIconSize myHUDConfig + 15) , widgetSpacing = 0 } - withToggleSupport taffyConfig + dyreTaffybar $ handleDBusToggles $ toTaffyConfig simpleTaffyConfig -- Local Variables: -- flycheck-ghc-args: ("-Wno-missing-signatures") diff --git a/dotfiles/config/taffybar/taffybar.rc b/dotfiles/config/taffybar/taffybar.rc deleted file mode 100644 index 3ab4edab..00000000 --- a/dotfiles/config/taffybar/taffybar.rc +++ /dev/null @@ -1,134 +0,0 @@ -style "taffybar-default" { - color["black"] = "#000000" - color["white"] = "#ffffff" - - color["green"] = "#4caf50" - color["yellow"] = "#ffeb3b" - color["orange"] = "#f4511e" - color["blue"] = "#2196f3" - color["red"] = "#F44336" - color["dgrey"] = "#212121" - color["ldgrey"] = "#333333" - color["mgrey"] = "#808080" - color["lldgrey"] = "#424242" - color["lgrey"] = "#bdbdbd" - color["teal"] = "#00796b" - color["bgrey"] = "#37474F" - color["bgreyl"] = "#546E7A" - color["activeWS"] = @yellow - color["visibleWS"] = @red - - color["base"] = @black - color["accent1"] = @dgrey - color["accent2"] = @ldgrey - - bg[NORMAL] = @black - fg[NORMAL] = @white - text[NORMAL] = @black - fg[PRELIGHT] = @yellow -} - -style "taffybar-active-window" = "taffybar-default" { - fg[NORMAL] = @white -} - -style "taffybar-notification-button" = "taffybar-default" { - text[NORMAL] = @red - fg[NORMAL] = @red -} - -style "taffybar-workspace-border-active" = "taffybar-default" { - bg[NORMAL] = @yellow -} -style "taffybar-workspace-border-visible" = "taffybar-default" { - bg[NORMAL] = @orange -} -style "taffybar-workspace-border-empty" = "taffybar-default" { - bg[NORMAL] = @blue -} -style "taffybar-workspace-border-hidden" = "taffybar-default" { - bg[NORMAL] = @blue -} - -style "taffybar-icon-urgent" = "taffybar-default" { - bg[NORMAL] = @yellow -} - -style "taffybar-icon-active" = "taffybar-default" { - bg[NORMAL] = @teal -} - -style "taffybar-icon-minimized" = "taffybar-default" { - bg[NORMAL] = @red -} - -style "taffybar-workspace-contents-active" = "taffybar-default" { - bg[NORMAL] = @dgrey -} - -style "taffybar-workspace-contents-visible" = "taffybar-default" { - bg[NORMAL] = @black -} - -style "taffybar-hover-button" = "taffybar-default" { - bg[ACTIVE] = @yellow - bg[NORMAL] = @black - bg[PRELIGHT] = @yellow - text[PRELIGHT] = @yellow -} - -style "blue" = "taffybar-default" { - bg[NORMAL]= @blue -} -style "orange" = "taffybar-default" { - bg[NORMAL]= @orange -} -style "red" = "taffybar-default" { - bg[NORMAL]= @red -} -style "yellow" = "taffybar-default" { - bg[NORMAL]= @yellow -} -style "green" = "taffybar-default" { - bg[NORMAL]= @green -} -style "teal" = "taffybar-default" { - bg[NORMAL]= @teal -} -style "bgrey" = "taffybar-default" { - bg[NORMAL]= @bgrey -} - -widget "Taffybar*" style "taffybar-default" -widget "*WindowTitle*" style "taffybar-active-window" -widget "*NotificationCloseButton" style "taffybar-notification-button" - -widget "*Workspace-underline*-active*" style "taffybar-workspace-border-active" -widget "*Workspace-contents*-active*" style "taffybar-workspace-contents-active" -widget "*Workspace-contents*-visible*" style "taffybar-workspace-contents-visible" - -widget "*Workspace-underline*-visible*" style "taffybar-workspace-border-visible" -widget "*Workspace-underline*-empty*" style "taffybar-workspace-border-empty" -widget "*Workspace-underline*-hidden*" style "taffybar-workspace-border-hidden" - -widget "*Workspace-Border*-active*" style "taffybar-workspace-border-active" -widget "*Workspace-Container-*-active*" style "taffybar-default" -widget "*Workspace-Border*-visible*" style "taffybar-workspace-border-visible" -widget "*Workspace-Container-*-visible*" style "taffybar-default" - -widget "*Workspace-icon*-urgent*" style "taffybar-icon-urgent" -widget "*Workspace-icon*-active*" style "taffybar-icon-active" -widget "*Workspace-icon*-minimized*" style "taffybar-icon-minimized" - -widget "*WorkspaceHUD-*" style "taffybar-hover-button" -widget "*WorkspaceHUD-*" style "taffybar-hover-button" - -widget "*clock-underline*" style "taffybar-workspace-border-active" -widget "*tray-underline*" style "taffybar-workspace-border-hidden" -widget "*blue-underline*" style "blue" -widget "*red-underline*" style "red" -widget "*yellow-underline*" style "yellow" -widget "*orange-underline*" style "orange" -widget "*green-underline*" style "green" -widget "*teal-underline*" style "teal" -widget "*bgrey-underline*" style "bgrey" diff --git a/dotfiles/emacs.d/README.org b/dotfiles/emacs.d/README.org index 88395ce9..5642beb0 100644 --- a/dotfiles/emacs.d/README.org +++ b/dotfiles/emacs.d/README.org @@ -2134,6 +2134,12 @@ I don't use auto-complete at all, so I have set up a hook to automatically disab (global-flycheck-mode)) :diminish flycheck-mode) #+END_SRC +* straight +#+BEGIN_SRC emacs-lisp +(use-package straight + :config + (setq straight-vc-git-auto-fast-forward t)) +#+END_SRC * Major Modes ** Programming <> diff --git a/dotfiles/lib/bin/rofi_systemd.sh b/dotfiles/lib/bin/rofi_systemd.sh index 5bacd231..5e1e0776 100755 --- a/dotfiles/lib/bin/rofi_systemd.sh +++ b/dotfiles/lib/bin/rofi_systemd.sh @@ -1,59 +1,107 @@ -#!/usr/bin/env zsh +#!/usr/bin/env sh export SYSTEMD_COLORS=0 +term=${ROFI_SYSTEMD_TERM-termite -e} +default_action=${ROFI_SYSTEMD_DEFAULT_ACTION-"list_actions"} function user_units { - SYSTEMD_COLORS=0 systemctl --user list-unit-files | tail -n +2 | head -n -2 | - awk '{print $0 " user"}' + SYSTEMD_COLORS=0 systemctl --user list-unit-files | tail -n +2 | head -n -2 | + awk '{print $0 " user"}' } function system_units { - systemctl list-unit-files | tail -n +2 | head -n -2 | - awk '{print $0 " system"}' + systemctl list-unit-files | tail -n +2 | head -n -2 | + awk '{print $0 " system"}' } enable="Alt+e" disable="Alt+d" stop="Alt+k" restart="Alt+r" +tail="Alt+t" +list_actions="Alt+l" + +all_actions="enable +disable +stop +restart +tail +list_actions" function select_service_and_act { - result=$(rofi -dmenu -i -p "systemd unit: " \ - -kb-custom-1 "${enable}" \ - -kb-custom-2 "${disable}" \ - -kb-custom-3 "${stop}" \ - -kb-custom-4 "${restart}") + result=$(rofi -dmenu -i -p "systemd unit: " \ + -kb-custom-1 "${enable}" \ + -kb-custom-2 "${disable}" \ + -kb-custom-3 "${stop}" \ + -kb-custom-4 "${restart}" \ + -kb-custom-5 "${tail}" \ + -kb-custom-6 "${list_actions}") - rofi_exit="$?" - selection="$(echo $result | sed -n 's/ \+/ /gp')" + rofi_exit="$?" - action="restart" - case "$rofi_exit" in - 1) - exit - ;; - 10) - action="enable" - ;; - 11) - action="disable" - ;; - 12) - action="stop" - ;; - esac + case "$rofi_exit" in + 1) + action="exit" + exit 1 + ;; + 10) + action="enable" + ;; + 11) + action="disable" + ;; + 12) + action="stop" + ;; + 13) + action="restart" + ;; + 14) + action="tail" + ;; + 15) + action="list_actions" + ;; + *) + action="$default_action" + ;; + esac - service_name="$(printf $selection | awk '{ print $1 }' | tr -d ' ')" - is_user="$(printf $selection | awk '{ print $3 }' )" + selection="$(echo $result | sed -n 's/ \+/ /gp')" + service_name="$(echo $selection | awk '{ print $1 }' | tr -d ' ')" + is_user="$(echo $selection | awk '{ print $3 }' )" - case "$is_user" in - user*) - systemctl "$action" --user "$service_name" - ;; - system*) - sudo systemctl "$action" "$service_name" - ;; - esac + case "$is_user" in + user*) + user_arg="--user" + command="systemctl $user_arg" + ;; + system*) + user_arg="" + command="sudo systemctl" + ;; + *) + command="systemctl" + esac + + to_run="$(get_command_with_args)" + echo "Running $to_run" + eval "$to_run" +} + +function get_command_with_args { + case "$action" in + "tail") + echo "$term 'journalctl $user_arg -u $service_name -f'" + ;; + "list_actions") + action=$(echo "$all_actions" | rofi -dmenu -i -p "Select action: ") + get_command_with_args + ;; + *) + echo "$command $action $service_name" + ;; + esac } { user_units; system_units; } | column -tc 1 | select_service_and_act diff --git a/dotfiles/lib/python/investment_optimization.py b/dotfiles/lib/python/investment_optimization.py new file mode 100755 index 00000000..8e76e393 --- /dev/null +++ b/dotfiles/lib/python/investment_optimization.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +import heapq +from collections import namedtuple + + +BuyOpportunity = namedtuple( + 'BuyOpportunity', + ['trans_yield', 'start', 'end'] +) + + +def maximize_profit(num_transactions, prices): + minima, maxima = find_extrema(prices) + opp_queue, reverse_opp_queue = make_opportunity_queues( + minima, maxima, prices, + ) + if not opp_queue: + return [] + + largest_segment = opp_queue[0][1] + # Segments will be kept in sorted order + segments = [largest_segment] + + # Remove any reverse yields that are greater than the largest actual yield + # since they can never be realized anyway. + while (reverse_opp_queue and reverse_opp_queue[0][1].trans_yield >= + largest_segment.trans_yield): + heapq.heappop(reverse_opp_queue) + + def try_rev_opp(): + # It is okay to definitely pop here even though we don't know that we + # can actually use the opp for the following reason: + # Since the rev opp queue was selected OVER that of the opp queue, we + # KNOW that the bounding segment that includes this rev opp must have + # already been selected if it is going to be included at all (since it + # must have greater yield). + _, rev_opp_can = heapq.heappop(reverse_opp_queue) + for (seg_index, split_seg) in enumerate(segments): + if split_seg.end >= rev_opp_can.end: + # Since segments is sorted, this must be the correct segment + break + else: + return + if split_seg.start <= rev_opp_can.start: + # We found the containing segment + left_yield = prices[rev_opp_can.start] - prices[split_seg.start] + right_yield = prices[split_seg.end] - prices[rev_opp_can.end] + left_segment = BuyOpportunity(left_yield, split_seg.start, rev_opp_can.start) + right_segment = BuyOpportunity(right_yield, rev_opp_can.end, split_seg.end) + segments.pop(seg_index) + segments.insert(seg_index, left_segment) + segments.insert(seg_index + 1, right_segment) + + def try_opp(): + _, opp = heapq.heappop(opp_queue) + if not segments: + segments.append(opp) + insertion_index = 0 + for (index, seg) in enumerate(segments): + if seg.start >= opp.start: + insertion_index = index + break + else: + insertion_index = len(segments) + seg = None + previous_seg = segments[insertion_index - 1] if insertion_index > 0 else None + + if ((seg is None or seg.start >= opp.end) and + (previous_seg is None or previous_seg.end <= opp.start)): + # There is no overlap, so we can insert + segments.insert(insertion_index, opp) + else: + pass + + while (opp_queue or reverse_opp_queue) and len(segments) < num_transactions: + if not reverse_opp_queue: + try_opp() + elif not opp_queue: + try_rev_opp() + else: + opp_can = opp_queue[0][1] + rev_opp_can = reverse_opp_queue[0][1] + + if rev_opp_can.trans_yield > opp_can.trans_yield: + try_rev_opp() + else: + try_opp() + + return segments + + +def make_opportunity_queues(minima, maxima, prices): + opp_queue = [] + reverse_opp_queue = [] + for min_index, minimum in enumerate(minima): + for max_index, maximum in enumerate(maxima): + transaction_yield = prices[maximum] - prices[minimum] + if transaction_yield < 0: + # We can ignore this pair because the transaction has negative + # yield. + continue + # minimum comes before maximum in time + if minimum < maximum: + # Transaction yield is made negative because heapq is a min-heap + heapq.heappush( + opp_queue, ((-transaction_yield, maximum - minimum), BuyOpportunity( + transaction_yield, minimum, maximum, + )), + ) + else: + heapq.heappush( + reverse_opp_queue, (-transaction_yield, BuyOpportunity( + transaction_yield, maximum, minimum, + )) + ) + return opp_queue, reverse_opp_queue + + +def find_extrema(prices): + maxima = [] + minima = [] + length_of_prices = len(prices) + if length_of_prices < 2: + return minima, maxima + + upwards = None + last = prices[0] + + for (index, price) in enumerate(prices): + if price < last: + if upwards is True: + maxima.append(index - 1) + elif upwards is None: + # We set the starting price as a maximum, but theres no point + # since we would really never buy. + maxima.append(0) + pass + upwards = False + elif price > last: + if upwards is False: + minima.append(index - 1) + elif upwards is None: + # The starting value is a minimum + minima.append(0) + upwards = True + last = price + + if upwards is True: + maxima.append(length_of_prices - 1) + elif upwards is False: + minima.append(length_of_prices - 1) + + return minima, maxima + + +if __name__ == '__main__': + print (maximize_profit(10, [0, 1, 3, 2, 3, 0, 10, 12, 1, 2, 3, 2, 0, 2, 4, 3, 6, 4, 14, 1, 0, 2, 4, 5, 4, 5, 6])) + + print [ + BuyOpportunity(trans_yield=1, start=0, end=1), + BuyOpportunity(trans_yield=12, start=2, end=4), + BuyOpportunity(trans_yield=2, start=5, end=7), + BuyOpportunity(trans_yield=6, start=9, end=11), + BuyOpportunity(trans_yield=6, start=12, end=13), + BuyOpportunity(trans_yield=10, start=14, end=15), + BuyOpportunity(trans_yield=5, start=17, end=20), + BuyOpportunity(trans_yield=2, start=21, end=23), + ]