;;; wifi-bluetooth-conf.el --- Configuration to manage wifi and bluetooth -*- lexical-binding: t; -*- ;; Copyright (C) 2021 李俊緯 ;; Author: 李俊緯 ;; Keywords: comm, hardware, games, unix ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; Configuration to manage wifi and bluetooth. ;;; Code: ;;;###autoload (defvar durand-wifi-on-p nil "If WIFI is on or not. This is defined in \"/Users/durand/.emacs.d/view-conf.el\"") ;;;###autoload (defvar durand-bluetooth-on-p nil "If BLUETOOTH is on or not. This is defined in \"/Users/durand/.emacs.d/view-conf.el\"") ;;;###autoload (defun durand-wifi-filter (proc output) "Filter function to set the wifi variable. This should only be used for the process \"durand-wifi\". This is defined in \"/Users/durand/.emacs.d/view-conf.el\"" (cond ((string= (process-name proc) "durand-wifi")) ((user-error "Filter function associated with a wrong process."))) (setq durand-wifi-on-p (string-match "On$" output))) ;;;###autoload (defun durand-bluetooth-filter (proc output) "Filter function to set the bluetooth variable. This should only be used for the process \"durand-bluetooth\". This is defined in \"/Users/durand/.emacs.d/view-conf.el\"" (cond ((string= (process-name proc) "durand-bluetooth")) ((user-error "Filter function associated with a wrong process."))) (setq durand-bluetooth-on-p (string-match "1" output))) ;;;###autoload (defun durand-wifi-toggle () "Check if WIFI is enabled, then ask to toggle WIFI." (interactive) (make-process :name "durand-wifi" :buffer nil :command '("networksetup" "-getairportpower" "en0") :filter #'durand-wifi-filter :sentinel #'ignore) (accept-process-output (get-process "durand-wifi")) (let* ((prompt (format "WIFI is %s. Do you want to turn WIFI %s" (cond (durand-wifi-on-p "on") ("off")) (cond (durand-wifi-on-p "off?") ("on?")))) (decision (y-or-n-p prompt))) (cond (decision (let ((new-state (cond (durand-wifi-on-p "off") ("on")))) (make-process :name "durand-toggle-wifi" :buffer nil :command (list "networksetup" "-setairportpower" "en0" new-state) :sentinel #'ignore :filter #'ignore) (message "WIFI turned %s" new-state)))))) ;;;###autoload (defun durand-bluetooth-toggle () "Check if BLUETOOTH is enabled, then ask to toggle BLUETOOTH." (interactive) (make-process :name "durand-bluetooth" :buffer nil :command '("blueutil" "-p") :filter #'durand-bluetooth-filter :sentinel 'ignore) (accept-process-output (get-process "durand-bluetooth")) (let* ((prompt (format "BLUETOOTH is %s. Do you want to turn BLUETOOTH %s" (cond (durand-bluetooth-on-p "on") ("off")) (cond (durand-bluetooth-on-p "off?") ("on?")))) (decision (y-or-n-p prompt))) (cond (decision (let ((new-state (cond (durand-bluetooth-on-p "0") ("1")))) (make-process :name "durand-toggle-bluetooth" :buffer nil :command (list "blueutil" "-p" new-state) :sentinel 'ignore :filter 'ignore) (message "BLUETOOTH turned %s" (cond (durand-bluetooth-on-p "off") ("on")))))))) ;;;###autoload (defconst durand-wifi-executable "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport" "The executable to manage some WIFI settings.") ;;;###autoload (defconst durand-wifi-bluetooth-buffer "*durand-wifi-bluetooth*" "The buffer to accept outputs from commands managing WIFI or BLUETOOTH.") ;;;###autoload (defun durand-wifi-list-ports (&optional arg) "List available wifi networks. If ARG is non-nil, then list the currently connected port." (interactive "P") (cond ((and (get-buffer durand-wifi-bluetooth-buffer) (buffer-live-p (get-buffer durand-wifi-bluetooth-buffer))) (kill-buffer durand-wifi-bluetooth-buffer))) (cond ((null arg) (make-process :name "durand-wifi-list-ports" :buffer durand-wifi-bluetooth-buffer :command (list durand-wifi-executable "-I") :sentinel #'durand-wifi-list-sentinel)) ((make-process :name "durand-wifi-list-ports" :buffer durand-wifi-bluetooth-buffer :command (list durand-wifi-executable "-s") :sentinel #'durand-wifi-list-sentinel) ))) ;;;###autoload (defun durand-wifi-join-port (port &optional pwd) "Join PORT. If PWD is non-nil, use that as the password." (interactive (let ((po (read-string "Port to join: ")) (pwd (read-string "Password: "))) (cond ((and pwd (not (string= pwd ""))) (list po pwd)) ((list po))))) (make-process :name "durand-wifi-join-port" :buffer durand-wifi-bluetooth-buffer :command (append (list "networksetup" "setairportnetwork" "en0" port) (cond ((and pwd (not (string= pwd ""))) (list pwd)))) :filter #'durand-wifi-join-filter)) ;;;###autoload (defun durand-wifi-list-sentinel (process status) "Extract and message the information about available WIFI's SSID's. PROCESS should have the name \"durand-wifi-list-ports\". This only does something when STATUS is the string \"finished\\n\"." (cond ((string-equal (process-name process) "durand-wifi-list-ports")) ((error "The list sentinel is applied to a wrong process: %S" process))) (let (first-var) (cond ((string-equal status "finished\n") (with-current-buffer durand-wifi-bluetooth-buffer (goto-char (point-min)) (cond ((re-search-forward "AirPort: Off" nil t) (message "Wifi is not enabled.")) ((re-search-forward "\\s-+SSID" (line-end-position) t) (setq first-var t) (forward-line 1) (let ((start 0) list-of-ssids) (while (re-search-forward "\\S-" (line-end-position) t) (forward-char -1) (setq start (point)) (re-search-forward "\\s-" (line-end-position) t) (forward-char -1) (setq list-of-ssids (cons (buffer-substring-no-properties start (point)) list-of-ssids)) (forward-line 1)) (erase-buffer) (goto-char (point-min)) (insert (string-join list-of-ssids (string 10))) (goto-char (point-min)))) ((re-search-forward "\\s-+SSID: " nil t) (message (buffer-substring-no-properties (point) (line-end-position)))))) (cond (first-var (display-buffer durand-wifi-bluetooth-buffer '((display-buffer-in-side-window) (side . bottom) (window-height . #'durand-fit-window-to-buffer-with-max))) (with-current-buffer durand-wifi-bluetooth-buffer (fit-window-to-buffer (get-buffer-window (current-buffer)) (floor (* durand-window-max-height (frame-height (window-frame (get-buffer-window (current-buffer)))))))))))))) ;;;###autoload (defun durand-wifi-join-filter (proc output) "Message the OUTPUT of the PROCESS." (cond ((string= (process-name proc) "durand-wifi-join-port")) ((error "The join filter is applied to a wrong process: %S" proc))) (message output)) (define-key global-map (vector 3 ?w ?w) #'durand-wifi-toggle) (define-key global-map (vector 3 ?w ?b) #'durand-bluetooth-toggle) (define-key global-map (vector 3 ?w ?l) #'durand-wifi-list-ports) (define-key global-map (vector 3 ?w ?j) #'durand-wifi-join-port) ;; Control the display of the buffer ;; (setq display-buffer-alist ;; (delete (assoc durand-wifi-bluetooth-buffer display-buffer-alist #'string-match) ;; display-buffer-alist)) ;; (cond ;; ((assoc durand-wifi-bluetooth-buffer display-buffer-alist #'string-match) ;; (setcdr (assoc durand-wifi-bluetooth-buffer ;; display-buffer-alist #'string-match) ;; '((display-buffer-at-bottom) ;; (window-height . #'durand-fit-window-to-buffer-with-max)))) ;; (t ;; (add-to-list 'display-buffer-alist ;; `(,(rx-to-string `(seq bos ,durand-wifi-bluetooth-buffer eos)) ;; (display-buffer-at-bottom) ;; (window-height . #'durand-fit-window-to-buffer-with-max))))) (provide 'wifi-bluetooth-conf) ;;; wifi-bluetooth-conf.el ends here