https://github.com/4DA/eshell-toggle
Набыдлил простую фичу: по шоткату (например s-`) показывается консолька eshell под активным окном с каталогом текущего буфера.
По этому же шоткату убирается.
Костыли чтобы заюзать org-capture для того чтобы добавить запись в файлик ledger.
Плюс комлишен Accounts из задаваемого списка.
https://github.com/4DA/emacs-stuff/blob/master/ledger-completed-capture.el
Работает примерно так
Увидел следующую замену systemd:
#define _XOPEN_SOURCE 700
#include <signal.h>
#include <unistd.h>
int main()
{
sigset_t set;
int status;
if (getpid() != 1) return 1;
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, 0);
if (fork()) for (;;) wait(&status);
sigprocmask(SIG_UNBLOCK, &set, 0);
setsid();
setpgid(0, 0);
return execve("/etc/rc", (char *[]){ "rc", 0 }, (char *[]){ 0 });
}
Какие подводные камни?
Расписание горнолыжных соревнований TZ: MSK+4
| Day | Date | Begin | End | Discipline |
| День 3 | Воскресенье, 9 февраля | 11:00 | 13:10 | Скоростной спуск, мужчины |
| День 4 | Понедельник, 10 февраля | 11:00/15:00 | 12:30/16:10 | Суперкомбинация, женщины |
| День 6 | Среда, 12 февраля | 11:00 | 13:10 | Скоростной спуск, женщины |
| День 8 | Пятница, 14 февраля | 11:00/15:30 | 12:30/16:40 | Суперкомбинация, мужчины |
| День 9 | Суббота, 15 февраля | 11:00 | 13:10 | Супергигант, женщины |
| День 10 | Воскресенье, 16 февраля | 11:00 | 13:10 | Супергигант, мужчины |
| День 11 | Вторник, 18 февраля | 11:00/14:30 | 13:00/16:10 | Гигантский слалом, женщины |
| День 12 | Среда, 19 февраля | 11:00/14:30 | 13:00/16:10 | Гигантский слалом, мужчины |
| День 15 | Пятница, 21 февраля | 16:45/20:15 | 18:00/21:25 | Слалом, женщины |
| День 16 | Суббота, 22 февраля | 16:45/21:50 | 18:15/20:15 | Слалом, мужчины |
Костыль для емакса чтобы в конец буфера вставлялся первый встретившийся выше номер поста или комента (вида #foo/bar).
(defun do-reply-to-post-comment ()
(if (re-search-backward
"^#[0-9a-zA-Z]+\(/[0-9a-zA-Z]+\)?" nil t 1)
(progn
(end-of-buffer)
(insert-buffer-substring-no-properties (current-buffer)
(match-beginning 0) (match-end 0))
(insert " "))
(message "No comments found")))
(defun reply-to-post-comment()
(interactive)
(save-excursion
(do-reply-to-post-comment))
(end-of-buffer))
(global-set-key (kbd "C-c r") 'reply-to-post-comment)
Драйвер редиса возвращает Redis (Either Reply a)
. При операции HGET
возвращает, соответственно, Redis (Either Reply (Maybe ByteString))
, типа значения по ключу может и не быть. Программист для упрощения пишет сначала специальную функцию redis'
, которая заворачивает ответ редиса в EitherT-based монаду, чтоб соединять подобные вычисления и возвращать первую неудачу:
newtype Redis' a = Redis' (EitherT Redis.Reply Redis.Redis a) deriving (MonadIO)
instance Monad Redis' where
return = Redis' . EitherT . return . Right
(Redis' m) >>= f = Redis' $ m >>= \rv -> unwrapRedis' $ f rv
redis' = Redis' . EitherT
Таким образом, теперь, если вы получаете ответ Redis (Either Reply a)
, вы его преобразуете в
Redis' (EitherT Reply Redis a)
и можете соединять подобные вычисления в do-блоке типа:
do
res <- redis' $ Redis.hget foo bar
res2 <- redis' $ Redis.hget baz zab
и вычисление остановится на первом возврате ошибки.
Далее. Программисту необходимо по кучке значений сделать HGET
и вернуть это как-то внутри кортежа, поскольку мы внутри новой монады Redis'
-- завернуть результат в неё. В случае, если значения хоть по одному ключу не существует, хочется вернуть Nothing
для всех. Потому создаётся новая монада:
newtype HashFields a = HashFields (MaybeT Redis' a)
deriving (Functor, Monad)
instance Applicative HashFields where
pure = return
(<*>) = ap
описывающая вычисления типа Redis'
, которые могут вернуть неудачу. Пишется новая функция
hashField = HashFields . MaybeT . redis'
способная завернуть результат неудачи в новую монаду, которая умеет останавливаться на первой неудаче. Также пишется специальная функция для HGET
:
getField :: ByteString -- ^ Key
-> ByteString -- ^ Hash field name
-> HashFields String
getField key field = fmap toString $ hashField $ Redis.hget key field
Также напишем функцию, которая "запустит" наше вычисление:
getRedisFields :: forall a. HashFields a -> Redis' (Maybe a)
getRedisFields (HashFields f) = runMaybeT f
И теперь лёгким движением руки мы можем сделать что-то вроде:
getRedisFields ((,,,,,) <$>
getField k "foo" <*>
getField k "bar" <*>
getField k "baz" <*>
getField k "zab" <*>
getField k "rab" <*>
getField k "oof")
Вопрос: вам не кажется это "слишком"? Я пока еще не настолько просто манипулирую типами в голове, чтоб ощутить всю ситуацию, хорошо хоть в целом могу медленно прости по шагам по коду, но есть ощущение, что что-то здесь не так.
Суровый выхлоп работы ракетовского макростеппера:
(define (g)
(forever (let ([abort abort])
(unless #t (abort)) (abort))))))
Для тех, кому интересно: первый abort имееет контекст из раскрытия макроса while', а второй - из раскрытия макроса
forever', этакие костыли для обхода гигены без использвания stx-params.
сорцы: http://paste.lisp.org/display/138905
соус: barzilay.org/misc/stxparam.pdf
$ torify cabal update
Downloading the latest package list from hackage.haskell.org
Segmentation fault