Repository: garybernhardt/destroy-all-software-extras
Branch: master
Commit: 419d76f6562a
Files: 17
Total size: 39.8 KB
Directory structure:
gitextract_ee0bj18n/
├── das-0010-fast-tests-with-and-without-rails/
│ └── test
├── das-0026-controller-refactoring-demo-part-2/
│ └── account_controller.rb
├── das-0030-some-vim-tips/
│ ├── grb256.vim
│ └── ir_black.vim
├── das-0070-time-to-first-request/
│ └── time_to_first_request.sh
├── das-0094-computing-by-constructing/
│ ├── everything.py
│ └── lambda.py
├── das-0095-power-of-lambda-calculus/
│ ├── everything.py
│ └── lambda.py
└── das-0102-data-compressor-from-scratch/
├── LICENSE
├── README
├── RUNME.sh
├── bin.rb
├── garyzip.rb
├── imgcat
├── rendertree.rb
└── tree.dot
================================================
FILE CONTENTS
================================================
================================================
FILE: das-0010-fast-tests-with-and-without-rails/test
================================================
#!/bin/bash
#
# From Destroy All Software screencast #10, at:
# http://destroyallsoftware.com/screencasts/catalog/fast-tests-with-and-without-rails
#
# Released under the MIT license: http://opensource.org/licenses/MIT
#
# Put this in the script/ directory of your Rails app, then run it with a spec
# filename. If the spec uses spec_helper, it'll be run inside Bundler.
# Otherwise, it'll be run directly with whatever `rspec` executable is on the
# path.
set -e
need_rails=1
if [ $# -gt 0 ]; then # we have args
filename=$1
# Remove trailing line numbers from filename, e.g. spec/my_spec.rb:33
grep_filename=`echo $1 | sed 's/:.*$//g'`
# if we can't match "spec_helper" in our file we have a stand-alone spec
grep -r '\bspec_helper\b' $grep_filename > /dev/null || need_rails=''
else # we have no args
filename='spec'
fi
command='rspec'
if [ $need_rails ]; then
command="ruby -S bundle exec $command"
fi
RAILS_ENV=test $command $filename
================================================
FILE: das-0026-controller-refactoring-demo-part-2/account_controller.rb
================================================
#-- copyright
# ChiliProject is a project management system.
#
# Copyright (C) 2010-2011 the ChiliProject Team
#
# 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 2
# of the License, or (at your option) any later version.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
class AccountController < ApplicationController
include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required
# Login request and validation
def login
if request.get?
logout_user
else
authenticate_user
end
end
# Log out current user and redirect to welcome page
def logout
logout_user
redirect_to home_url
end
# Enable user to choose a new password
def lost_password
redirect_to(home_url) && return unless Setting.lost_password?
if params[:token]
handle_existing_token
else
generate_token
end
end
def handle_existing_token
@token = Token.find_by_action_and_value("recovery", params[:token])
redirect_to(home_url) && return unless have_valid_token?
@user = @token.user
if request.post?
reset_password
else
render :template => "account/password_recovery"
end
end
def have_valid_token?
@token and !@token.expired?
end
def reset_password
@user.password = params[:new_password]
@user.password_confirmation = params[:new_password_confirmation]
if @user.save
@token.destroy
flash[:notice] = l(:notice_account_password_updated)
redirect_to :action => 'login'
else
render :template => "account/password_recovery"
end
end
def generate_token
return unless request.post?
user = User.find_by_mail(params[:mail])
if ensure_user_exists(user) && ensure_no_external_auth(user)
create_new_token(user)
end
end
def ensure_user_exists(user)
if user
true
else
flash.now[:error] = l(:notice_account_unknown_email)
false
end
end
def ensure_no_external_auth(user)
if user.auth_source_id
flash.now[:error] = l(:notice_can_t_change_password)
false
else
true
end
end
def create_new_token(user)
token = Token.new(:user => user, :action => "recovery")
if token.save
Mailer.deliver_lost_password(token)
flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to :action => 'login', :back_url => home_url
return
end
end
# User self-registration
def register
redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration]
if request.get?
session[:auth_source_registration] = nil
@user = User.new(:language => Setting.default_language)
else
@user = User.new(params[:user])
@user.admin = false
@user.register
if session[:auth_source_registration]
@user.activate
@user.login = session[:auth_source_registration][:login]
@user.auth_source_id = session[:auth_source_registration][:auth_source_id]
if @user.save
session[:auth_source_registration] = nil
self.logged_user = @user
flash[:notice] = l(:notice_account_activated)
redirect_to :controller => 'my', :action => 'account'
end
else
@user.login = params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
case Setting.self_registration
when '1'
register_by_email_activation(@user)
when '3'
register_automatically(@user)
else
register_manually_by_administrator(@user)
end
end
end
end
# Token based account activation
def activate
redirect_to(home_url) && return unless Setting.self_registration? && params[:token]
token = Token.find_by_action_and_value('register', params[:token])
redirect_to(home_url) && return unless token and !token.expired?
user = token.user
redirect_to(home_url) && return unless user.registered?
user.activate
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
end
redirect_to :action => 'login'
end
private
def logout_user
if User.current.logged?
cookies.delete Redmine::Configuration['autologin_cookie_name']
Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
self.logged_user = nil
end
end
def authenticate_user
if Setting.openid? && using_open_id?
open_id_authenticate(params[:openid_url])
else
password_authentication
end
end
def password_authentication
user = User.try_to_login(params[:username], params[:password])
if user.nil?
invalid_credentials
elsif user.new_record?
onthefly_creation_failed(user, {:login => user.login, :auth_source_id => user.auth_source_id })
else
# Valid user
successful_authentication(user)
end
end
def open_id_authenticate(openid_url)
authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => signin_url) do |result, identity_url, registration|
if result.successful?
user = User.find_or_initialize_by_identity_url(identity_url)
if user.new_record?
# Self-registration off
redirect_to(home_url) && return unless Setting.self_registration?
# Create on the fly
user.login = registration['nickname'] unless registration['nickname'].nil?
user.mail = registration['email'] unless registration['email'].nil?
user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
user.random_password
user.register
case Setting.self_registration
when '1'
register_by_email_activation(user) do
onthefly_creation_failed(user)
end
when '3'
register_automatically(user) do
onthefly_creation_failed(user)
end
else
register_manually_by_administrator(user) do
onthefly_creation_failed(user)
end
end
else
# Existing record
if user.active?
successful_authentication(user)
else
account_pending
end
end
end
end
end
def successful_authentication(user)
# Valid user
self.logged_user = user
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user })
redirect_back_or_default :controller => 'my', :action => 'page'
end
def set_autologin_cookie(user)
token = Token.create(:user => user, :action => 'autologin')
cookie_options = {
:value => token.value,
:expires => 1.year.from_now,
:path => Redmine::Configuration['autologin_cookie_path'],
:secure => Redmine::Configuration['autologin_cookie_secure'],
:httponly => true
}
cookies[Redmine::Configuration['autologin_cookie_name']] = cookie_options
end
# Onthefly creation failed, display the registration form to fill/fix attributes
def onthefly_creation_failed(user, auth_source_options = { })
@user = user
session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
render :action => 'register'
end
def invalid_credentials
logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
flash.now[:error] = l(:notice_account_invalid_creditentials)
end
# Register a user for email activation.
#
# Pass a block for behavior when a user fails to save
def register_by_email_activation(user, &block)
token = Token.new(:user => user, :action => "register")
if user.save and token.save
Mailer.deliver_register(token)
flash[:notice] = l(:notice_account_register_done)
redirect_to :action => 'login'
else
yield if block_given?
end
end
# Automatically register a user
#
# Pass a block for behavior when a user fails to save
def register_automatically(user, &block)
# Automatic activation
user.activate
user.last_login_on = Time.now
if user.save
self.logged_user = user
flash[:notice] = l(:notice_account_activated)
redirect_to :controller => 'my', :action => 'account'
else
yield if block_given?
end
end
# Manual activation by the administrator
#
# Pass a block for behavior when a user fails to save
def register_manually_by_administrator(user, &block)
if user.save
# Sends an email to the administrators
Mailer.deliver_account_activation_request(user)
account_pending
else
yield if block_given?
end
end
def account_pending
flash[:notice] = l(:notice_account_pending)
redirect_to :action => 'login'
end
end
================================================
FILE: das-0030-some-vim-tips/grb256.vim
================================================
" Based on
runtime colors/ir_black.vim
let g:colors_name = "grb256"
hi pythonSpaceError ctermbg=red guibg=red
hi Comment ctermfg=darkgray
hi StatusLine ctermbg=darkgrey ctermfg=white
hi StatusLineNC ctermbg=black ctermfg=lightgrey
hi VertSplit ctermbg=black ctermfg=lightgrey
hi LineNr ctermfg=darkgray
hi CursorLine guifg=NONE guibg=#121212 gui=NONE ctermfg=NONE ctermbg=234
hi Function guifg=#FFD2A7 guibg=NONE gui=NONE ctermfg=yellow ctermbg=NONE cterm=NONE
hi Visual guifg=NONE guibg=#262D51 gui=NONE ctermfg=NONE ctermbg=236 cterm=NONE
hi Error guifg=NONE guibg=NONE gui=undercurl ctermfg=16 ctermbg=red cterm=NONE guisp=#FF6C60 " undercurl color
hi ErrorMsg guifg=white guibg=#FF6C60 gui=BOLD ctermfg=16 ctermbg=red cterm=NONE
hi WarningMsg guifg=white guibg=#FF6C60 gui=BOLD ctermfg=16 ctermbg=red cterm=NONE
hi SpellBad guifg=white guibg=#FF6C60 gui=BOLD ctermfg=16 ctermbg=160 cterm=NONE
" ir_black doesn't highlight operators for some reason
hi Operator guifg=#6699CC guibg=NONE gui=NONE ctermfg=lightblue ctermbg=NONE cterm=NONE
highlight DiffAdd term=reverse cterm=bold ctermbg=lightgreen ctermfg=16
highlight DiffChange term=reverse cterm=bold ctermbg=lightblue ctermfg=16
highlight DiffText term=reverse cterm=bold ctermbg=lightgray ctermfg=16
highlight DiffDelete term=reverse cterm=bold ctermbg=lightred ctermfg=16
highlight PmenuSel ctermfg=16 ctermbg=156
================================================
FILE: das-0030-some-vim-tips/ir_black.vim
================================================
" ir_black color scheme
" More at: http://blog.infinitered.com/entries/show/8
" ********************************************************************************
" Standard colors used in all ir_black themes:
" Note, x:x:x are RGB values
"
" normal: #f6f3e8
"
" string: #A8FF60 168:255:96
" string inner (punc, code, etc): #00A0A0 0:160:160
" number: #FF73FD 255:115:253
" comments: #7C7C7C 124:124:124
" keywords: #96CBFE 150:203:254
" operators: white
" class: #FFFFB6 255:255:182
" method declaration name: #FFD2A7 255:210:167
" regular expression: #E9C062 233:192:98
" regexp alternate: #FF8000 255:128:0
" regexp alternate 2: #B18A3D 177:138:61
" variable: #C6C5FE 198:197:254
"
" Misc colors:
" red color (used for whatever): #FF6C60 255:108:96
" light red: #FFB6B0 255:182:176
"
" brown: #E18964 good for special
"
" lightpurpleish: #FFCCFF
"
" Interface colors:
" background color: black
" cursor (where underscore is used): #FFA560 255:165:96
" cursor (where block is used): white
" visual selection: #1D1E2C
" current line: #151515 21:21:21
" search selection: #07281C 7:40:28
" line number: #3D3D3D 61:61:61
" ********************************************************************************
" The following are the preferred 16 colors for your terminal
" Colors Bright Colors
" Black #4E4E4E #7C7C7C
" Red #FF6C60 #FFB6B0
" Green #A8FF60 #CEFFAB
" Yellow #FFFFB6 #FFFFCB
" Blue #96CBFE #FFFFCB
" Magenta #FF73FD #FF9CFE
" Cyan #C6C5FE #DFDFFE
" White #EEEEEE #FFFFFF
" ********************************************************************************
set background=dark
hi clear
if exists("syntax_on")
syntax reset
endif
let colors_name = "ir_black"
"hi Example guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
" General colors
hi Normal guifg=#f6f3e8 guibg=black gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi NonText guifg=#070707 guibg=black gui=NONE ctermfg=black ctermbg=NONE cterm=NONE
hi Cursor guifg=black guibg=white gui=NONE ctermfg=black ctermbg=white cterm=reverse
hi LineNr guifg=#3D3D3D guibg=black gui=NONE ctermfg=darkgray ctermbg=NONE cterm=NONE
hi VertSplit guifg=#202020 guibg=#202020 gui=NONE ctermfg=darkgray ctermbg=darkgray cterm=NONE
hi StatusLine guifg=#CCCCCC guibg=#202020 gui=italic ctermfg=white ctermbg=darkgray cterm=NONE
hi StatusLineNC guifg=black guibg=#202020 gui=NONE ctermfg=blue ctermbg=darkgray cterm=NONE
hi Folded guifg=#a0a8b0 guibg=#384048 gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi Title guifg=#f6f3e8 guibg=NONE gui=bold ctermfg=NONE ctermbg=NONE cterm=NONE
hi Visual guifg=NONE guibg=#262D51 gui=NONE ctermfg=NONE ctermbg=darkgray cterm=NONE
hi SpecialKey guifg=#808080 guibg=#343434 gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi WildMenu guifg=green guibg=yellow gui=NONE ctermfg=black ctermbg=yellow cterm=NONE
hi PmenuSbar guifg=black guibg=white gui=NONE ctermfg=black ctermbg=white cterm=NONE
"hi Ignore guifg=gray guibg=black gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi Error guifg=NONE guibg=NONE gui=undercurl ctermfg=white ctermbg=red cterm=NONE guisp=#FF6C60 " undercurl color
hi ErrorMsg guifg=white guibg=#FF6C60 gui=BOLD ctermfg=white ctermbg=red cterm=NONE
hi WarningMsg guifg=white guibg=#FF6C60 gui=BOLD ctermfg=white ctermbg=red cterm=NONE
" Message displayed in lower left, such as --INSERT--
hi ModeMsg guifg=black guibg=#C6C5FE gui=BOLD ctermfg=black ctermbg=cyan cterm=BOLD
if version >= 700 " Vim 7.x specific colors
hi CursorLine guifg=NONE guibg=#121212 gui=NONE ctermfg=NONE ctermbg=NONE cterm=BOLD
hi CursorColumn guifg=NONE guibg=#121212 gui=NONE ctermfg=NONE ctermbg=NONE cterm=BOLD
hi MatchParen guifg=#f6f3e8 guibg=#857b6f gui=BOLD ctermfg=white ctermbg=darkgray cterm=NONE
hi Pmenu guifg=#f6f3e8 guibg=#444444 gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi PmenuSel guifg=#000000 guibg=#cae682 gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi Search guifg=NONE guibg=NONE gui=underline ctermfg=NONE ctermbg=NONE cterm=underline
endif
" Syntax highlighting
hi Comment guifg=#7C7C7C guibg=NONE gui=NONE ctermfg=darkgray ctermbg=NONE cterm=NONE
hi String guifg=#A8FF60 guibg=NONE gui=NONE ctermfg=green ctermbg=NONE cterm=NONE
hi Number guifg=#FF73FD guibg=NONE gui=NONE ctermfg=magenta ctermbg=NONE cterm=NONE
hi Keyword guifg=#96CBFE guibg=NONE gui=NONE ctermfg=blue ctermbg=NONE cterm=NONE
hi PreProc guifg=#96CBFE guibg=NONE gui=NONE ctermfg=blue ctermbg=NONE cterm=NONE
hi Conditional guifg=#6699CC guibg=NONE gui=NONE ctermfg=blue ctermbg=NONE cterm=NONE " if else end
hi Todo guifg=#8f8f8f guibg=NONE gui=NONE ctermfg=red ctermbg=NONE cterm=NONE
hi Constant guifg=#99CC99 guibg=NONE gui=NONE ctermfg=cyan ctermbg=NONE cterm=NONE
hi Identifier guifg=#C6C5FE guibg=NONE gui=NONE ctermfg=cyan ctermbg=NONE cterm=NONE
hi Function guifg=#FFD2A7 guibg=NONE gui=NONE ctermfg=brown ctermbg=NONE cterm=NONE
hi Type guifg=#FFFFB6 guibg=NONE gui=NONE ctermfg=yellow ctermbg=NONE cterm=NONE
hi Statement guifg=#6699CC guibg=NONE gui=NONE ctermfg=lightblue ctermbg=NONE cterm=NONE
hi Special guifg=#E18964 guibg=NONE gui=NONE ctermfg=white ctermbg=NONE cterm=NONE
hi Delimiter guifg=#00A0A0 guibg=NONE gui=NONE ctermfg=cyan ctermbg=NONE cterm=NONE
hi Operator guifg=white guibg=NONE gui=NONE ctermfg=white ctermbg=NONE cterm=NONE
hi link Character Constant
hi link Boolean Constant
hi link Float Number
hi link Repeat Statement
hi link Label Statement
hi link Exception Statement
hi link Include PreProc
hi link Define PreProc
hi link Macro PreProc
hi link PreCondit PreProc
hi link StorageClass Type
hi link Structure Type
hi link Typedef Type
hi link Tag Special
hi link SpecialChar Special
hi link SpecialComment Special
hi link Debug Special
" Special for Ruby
hi rubyRegexp guifg=#B18A3D guibg=NONE gui=NONE ctermfg=brown ctermbg=NONE cterm=NONE
hi rubyRegexpDelimiter guifg=#FF8000 guibg=NONE gui=NONE ctermfg=brown ctermbg=NONE cterm=NONE
hi rubyEscape guifg=white guibg=NONE gui=NONE ctermfg=cyan ctermbg=NONE cterm=NONE
hi rubyInterpolationDelimiter guifg=#00A0A0 guibg=NONE gui=NONE ctermfg=blue ctermbg=NONE cterm=NONE
hi rubyControl guifg=#6699CC guibg=NONE gui=NONE ctermfg=blue ctermbg=NONE cterm=NONE "and break, etc
"hi rubyGlobalVariable guifg=#FFCCFF guibg=NONE gui=NONE ctermfg=lightblue ctermbg=NONE cterm=NONE "yield
hi rubyStringDelimiter guifg=#336633 guibg=NONE gui=NONE ctermfg=lightgreen ctermbg=NONE cterm=NONE
"rubyInclude
"rubySharpBang
"rubyAccess
"rubyPredefinedVariable
"rubyBoolean
"rubyClassVariable
"rubyBeginEnd
"rubyRepeatModifier
"hi link rubyArrayDelimiter Special " [ , , ]
"rubyCurlyBlock { , , }
hi link rubyClass Keyword
hi link rubyModule Keyword
hi link rubyKeyword Keyword
hi link rubyOperator Operator
hi link rubyIdentifier Identifier
hi link rubyInstanceVariable Identifier
hi link rubyGlobalVariable Identifier
hi link rubyClassVariable Identifier
hi link rubyConstant Type
" Special for Java
" hi link javaClassDecl Type
hi link javaScopeDecl Identifier
hi link javaCommentTitle javaDocSeeTag
hi link javaDocTags javaDocSeeTag
hi link javaDocParam javaDocSeeTag
hi link javaDocSeeTagParam javaDocSeeTag
hi javaDocSeeTag guifg=#CCCCCC guibg=NONE gui=NONE ctermfg=darkgray ctermbg=NONE cterm=NONE
hi javaDocSeeTag guifg=#CCCCCC guibg=NONE gui=NONE ctermfg=darkgray ctermbg=NONE cterm=NONE
"hi javaClassDecl guifg=#CCFFCC guibg=NONE gui=NONE ctermfg=white ctermbg=NONE cterm=NONE
" Special for XML
hi link xmlTag Keyword
hi link xmlTagName Conditional
hi link xmlEndTag Identifier
" Special for HTML
hi link htmlTag Keyword
hi link htmlTagName Conditional
hi link htmlEndTag Identifier
" Special for Javascript
hi link javaScriptNumber Number
" Special for Python
"hi link pythonEscape Keyword
" Special for CSharp
hi link csXmlTag Keyword
" Special for PHP
================================================
FILE: das-0070-time-to-first-request/time_to_first_request.sh
================================================
#!/bin/bash
main() {
print_runtime > /dev/null
print_runtime
}
print_runtime() {
pid=$(start_server)
runtime=$(time_command wait_for_server)
baseline=$(time_command wait_for_server)
echo $runtime - $baseline | bc
kill -9 $pid
}
start_server() {
cd example
rackup >/dev/null 2>&1 &
echo $!
}
time_command() {
local cmd=$*
TIMEFORMAT="%3R"
(time $cmd) 2>&1
}
wait_for_server() {
while true; do
lsof -i :9292 > /dev/null
if [[ $? == 0 ]]; then
break
fi
done
}
main
================================================
FILE: das-0094-computing-by-constructing/everything.py
================================================
#!/usr/bin/env python3
NULL = (
lambda x: x
)
TRUE = (
lambda t: lambda f: t(NULL)
)
FALSE = (
lambda t: lambda f: f(NULL)
)
IF = (
lambda cond: lambda t: lambda f: cond(t)(f)
)
ZERO = (
lambda f: lambda x: x
)
ADD1 = (
lambda n: lambda f: lambda x: f( n(f)(x) )
)
ADD = (
lambda n: lambda m: n(ADD1)(m)
)
# Is this number equal to zero?
IS_ZERO = (
lambda n: n(lambda x: FALSE)(TRUE)
)
# Subtract 1: opposite of S, so SUB1(ONE) == ZERO.
# Like Y, this is more complex and subtle than most
# of our functions have been. It's OK to skip over it
# during this introduction.
SUB1 = (
(lambda n:
lambda f:
lambda x: n (lambda g: lambda h: h(g(f)))
(lambda u: x)
(lambda u: u))
)
# Multiplication: "add m to zero n times".
MULT = (
lambda n: lambda m: n(lambda x:
ADD(x)(m))(ZERO)
)
ONE = (
ADD1(ZERO)
)
SIX = (
ADD1(ADD1(ADD1(ADD1(ADD1(ADD1(ZERO))))))
)
================================================
FILE: das-0094-computing-by-constructing/lambda.py
================================================
#!/usr/bin/env python3
ONE = 1
IS_ZERO = lambda x: x == 0
SUB1 = lambda x: x - 1
MULT = lambda x: lambda y: x * y
IF = lambda cond: lambda t_func: lambda f_func: t_func(None) if cond else f_func(None)
print(
(
lambda myself: (
lambda n: (
IF(
IS_ZERO(n)
)(
lambda _: ONE
)(
lambda _: MULT(n)( myself(myself)(SUB1(n)) )
)
)
)
)(
lambda myself: (
lambda n: (
IF(
IS_ZERO(n)
)(
lambda _: ONE
)(
lambda _: MULT(n)( myself(myself)(SUB1(n)) )
)
)
)
)
(6)
)
================================================
FILE: das-0095-power-of-lambda-calculus/everything.py
================================================
#!/usr/bin/env python3
NULL = (
lambda x: x
)
TRUE = (
lambda t: lambda f: t(NULL)
)
FALSE = (
lambda t: lambda f: f(NULL)
)
IF = (
lambda cond: lambda t: lambda f: cond(t)(f)
)
ZERO = (
lambda f: lambda x: x
)
ADD1 = (
lambda n: lambda f: lambda x: f( n(f)(x) )
)
ADD = (
lambda n: lambda m: n(ADD1)(m)
)
# Is this number equal to zero?
IS_ZERO = (
lambda n: n(lambda x: FALSE)(TRUE)
)
# Subtract 1: opposite of S, so SUB1(ONE) == ZERO.
# Like Y, this is more complex and subtle than most
# of our functions have been. It's OK to skip over it
# during this introduction.
SUB1 = (
(lambda n:
lambda f:
lambda x: n (lambda g: lambda h: h(g(f)))
(lambda u: x)
(lambda u: u))
)
# Multiplication: "add m to zero n times".
MULT = (
lambda n: lambda m: n(lambda x:
ADD(x)(m))(ZERO)
)
ONE = (
ADD1(ZERO)
)
SIX = (
ADD1(ADD1(ADD1(ADD1(ADD1(ADD1(ZERO))))))
)
================================================
FILE: das-0095-power-of-lambda-calculus/lambda.py
================================================
#!/usr/bin/env python3
print(
( lambda myself: ( lambda n: ( ( lambda cond: lambda t: lambda f: cond(t)(f))( ( lambda n: n(lambda x: ( lambda t: lambda f: f(( lambda x: x))))(( lambda t: lambda f: t(( lambda x: x)))))(n))( lambda _:( ( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda f: lambda x: x))) )( lambda _: ( lambda n: lambda m: n(lambda x: ( lambda n: lambda m: n(( lambda n: lambda f: lambda x: f( n(f)(x) )))(m))(x)(m))(( lambda f: lambda x: x)))(n)( myself(myself)(( (lambda n: lambda f: lambda x: n (lambda g: lambda h: h(g(f))) (lambda u: x) (lambda u: u)))(n)) )))))( lambda myself: ( lambda n: ( ( lambda cond: lambda t: lambda f: cond(t)(f))( ( lambda n: n(lambda x: ( lambda t: lambda f: f(( lambda x: x))))(( lambda t: lambda f: t(( lambda x: x)))))(n))( lambda _:( ( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda f: lambda x: x))) )( lambda _: ( lambda n: lambda m: n(lambda x: ( lambda n: lambda m: n(( lambda n: lambda f: lambda x: f( n(f)(x) )))(m))(x)(m))(( lambda f: lambda x: x)))(n)( myself(myself)(( (lambda n: lambda f: lambda x: n (lambda g: lambda h: h(g(f))) (lambda u: x) (lambda u: u)))(n)) )))))
(( ( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda n: lambda f: lambda x: f( n(f)(x) ))(( lambda f: lambda x: x)))))))))
(lambda x: x + 1)(0)
)
================================================
FILE: das-0102-data-compressor-from-scratch/LICENSE
================================================
Copyright 2017 Gary Bernhardt
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: das-0102-data-compressor-from-scratch/README
================================================
These are the files used in Destroy All Software production 0102, "Data
Compressor From Scratch", available at:
https://www.destroyallsoftware.com/screencasts/catalog/data-compressor-from-scratch
The files are:
- RUNME.sh, which wasn't used in the screencast, but exists to give you an
easy way to run this code and see it work. You can execute it via
`./RUNME.sh` (without the backquotes).
- garyzip.rb, which is the file written in the screencast.
- bin.rb, which defines BinPacker and BinUnpacker, responsible for packing
sequences of int8s, int16s (unused in the screencast), int32s, and arbitrary
bits into bytes.
- rendertree.rb, which provides the `render_tree` function used to show the
Huffman coding trees visually.
- tree.dot, a manually-created tree diagram shown at the beginning of the
screencast. You can render it via `dot -Tpng tree.dot | ./imgcat` (requires
iTerm 2 or a terminal implementing iTerm 2's PNG rendering escape codes).
- imgcat, which is distributed by the authors of iTerm 2 but included here for
convenience. It allows us to print PNGs to the terminal. It will only work
with iTerm 2 or other terminals that implement iTerm 2's PNG rendering
escape codes.
DEPENDENCIES
- Ruby 2.4.1 (or probably older or newer versions, but try 2.4.1 if anything
goes wrong).
- For the tree rendering, iTerm 2 version 3.0.15.
SUPPORT
This code is entirely unsupported and is for educational purposes only.
LICENSE
All files here is released under the MIT license, with the exception of
`imgcat`, whose copyright is held by the authors of iTerm 2. See the file
`LICENSE`.
================================================
FILE: das-0102-data-compressor-from-scratch/RUNME.sh
================================================
#!/usr/bin/env bash
set -e -o pipefail
echo -n "abbcccc" | ./garyzip.rb compress | hexdump
================================================
FILE: das-0102-data-compressor-from-scratch/bin.rb
================================================
# This file was used in Destroy All Software production 0102, "Data Compressor
# From Scratch". It wasn't shown in the screencast, so it's not designed to be
# as readable as the main code. All of this code is exactly as used in the
# screencast except for the addition of comments.
#
# To see how this file was used to build a data compressor, visit:
#
# https://www.destroyallsoftware.com/screencasts/catalog/data-compressor-from-scratch
class BinPacker
def initialize
@bits = []
end
def int32(int)
@bits << [int_to_bits(int, 32), int]
self
end
def int16(int)
@bits << [int_to_bits(int, 16), int]
self
end
def int8(int)
@bits << [int_to_bits(int, 8), int]
self
end
def int(int, bit_count)
@bits << [int_to_bits(int, bit_count), int]
self
end
def bits(bits)
@bits << [bits, bits]
self
end
def pack
[flattened_bits.map(&:to_s).join].pack("b*")
end
def flattened_bits
@bits.map { |bits, original| bits }.flatten(1)
end
# This function was banged out to be used once during recording, without
# regard for whether anyone would ever read it. Oh well!
def debug
# Some ANSI escape codes that we'll use
red = "\e[31;49m"
reset = "\e[0m"
# Pack up the original packed values into DebugValues containing DebugBits.
# The DebugValues carry the original data plus the serialized bits; the
# DebugBits carry the original bits plus the colorized bits.
debug_values = @bits.each_with_index.map do |(bits, original), index|
mark_this_group = index % 2 == 0
debug_bits = bits.map do |bit|
bit_string = mark_this_group ? red + bit.to_s + reset : bit.to_s
DebugBit.new(bit_string, bit)
end
DebugValue.new(debug_bits, original)
end
# Print the original bit groups with their added alternating colors.
$stderr.puts "Original values (#{debug_values.length}):"
bit_strings = debug_values.map(&:debug_bits).map do |group|
# Reverse so the bits are printed in decreasing significance order, as
# expected by humans.
group.map(&:colorized_bit).reverse.join
end
original_values = debug_values.map(&:original).map(&:to_s)
max_original_length = original_values.map(&:length).max
bit_strings.zip(original_values).each do |bit_string, original|
$stderr.puts " " + original.rjust(max_original_length) + " | " + bit_string
end
$stderr.puts
# Print the actual bytes in three forms (bits, base-10 number, and ASCII
# character), maintaining the alternate coloring so we can see how the
# original bit groups map to the output bytes.
$stderr.puts "Bytes (#{pack.length}):"
debug_values.map(&:debug_bits).flatten(1).each_slice(8) do |group|
padding = "0" * (8 - group.length)
colorized_bits = padding + group.map(&:colorized_bit).reverse.join
just_the_bits = group.map(&:bit)
# Convert this group of bits into a character
char = [just_the_bits.map(&:to_s).join].pack("b*")
$stderr.puts " " + colorized_bits + " | " + char.ord.to_s.ljust(3) + " | " + char.inspect
end
$stderr.puts
# Print the final packed string, which will be the same as the ASCII
# characters rendered for the packed bits.
$stderr.puts "Packed string (#{pack.length}): #{pack.inspect}"
$stderr.puts
end
DebugValue = Struct.new(:debug_bits, :original)
DebugBit = Struct.new(:colorized_bit, :bit)
private
def int_to_bits(int, bit_count)
bits = []
bit_count.times do
bits << (int & 0x1)
int >>= 1
end
bits
end
end
class BinUnpacker
def initialize(packed)
@bits = packed.unpack("b*").fetch(0).chars.map(&:to_i)
end
def int32
int(32)
end
def int16
int(16)
end
def int8
int(8)
end
def bits(count)
bits = @bits[0...count]
@bits = @bits[count..-1]
bits
end
def peek(n)
@bits[0...n]
end
def int(bit_count)
bits, @bits = @bits[0...bit_count], @bits[bit_count..-1]
int = 0
bits.reverse.each do |bit|
int <<= 1
int |= bit
end
int
end
end
================================================
FILE: das-0102-data-compressor-from-scratch/garyzip.rb
================================================
#!/usr/bin/env ruby
# This file was used in Destroy All Software production 0102, "Data Compressor
# From Scratch". It wasn't shown in the screencast, so it's not designed to be
# as readable as the main code. All of this code is exactly as used in the
# screencast except for:
#
# - This comment.
# - Calls to `render_tree` and `packer.debug` in the `compress` function, so
# you can easily run this file and see the debug output from the screencast.
#
# To see this work, try the command below. Note that the tree printed by
# `render_tree` will only work in iTerm 2, or other terminals that support its
# PNG rendering escape codes. If you're not using iTerm 2, you can comment out
# the call to `render_tree`.
#
# echo -n "abbcccc" | ./garyzip.rb compress | hexdump
#
# To see how this file was written, visit:
#
# https://www.destroyallsoftware.com/screencasts/catalog/data-compressor-from-scratch
require "./rendertree"
require "./bin"
def compress(original)
tree = build_tree(original)
table = build_table(tree)
packer = BinPacker.new
packer.int32(original.length)
pack_table(table, packer)
original.bytes.each do |byte|
bits = look_up_byte(table, byte)
packer.bits(bits)
end
render_tree(tree)
packer.debug
packer.pack
end
def decompress(compressed)
unpacker = BinUnpacker.new(compressed)
data_length = unpacker.int32
table = unpack_table(unpacker)
data_length.times.map do
look_up_bits(table, unpacker)
end.map(&:chr).join
end
def build_tree(original)
bytes = original.bytes
unique_bytes = bytes.uniq
nodes = unique_bytes.map do |byte|
Leaf.new(byte, bytes.count(byte))
end
until nodes.length == 1
node1 = nodes.delete(nodes.min_by(&:count))
node2 = nodes.delete(nodes.min_by(&:count))
nodes << Node.new(node1, node2, node1.count + node2.count)
end
nodes.fetch(0)
end
def build_table(node, path=[])
if node.is_a? Node
build_table(node.left, path + [0]) +
build_table(node.right, path + [1])
else
[TableRow.new(node.byte, path)]
end
end
def look_up_byte(table, byte)
table.each do |row|
if row.byte == byte
return row.bits
end
end
awoijf
end
# a = 00
# b = 01
# c = 1
def look_up_bits(table, unpacker)
table.each do |row|
if row.bits == unpacker.peek(row.bits.length)
unpacker.bits(row.bits.length)
return row.byte
end
end
awoijf
end
def pack_table(table, packer)
packer.int8(table.length - 1)
table.each do |row|
packer.int8(row.byte)
packer.int8(row.bits.length)
packer.bits(row.bits)
end
end
def unpack_table(unpacker)
table_length = unpacker.int8 + 1
table_length.times.map do
byte = unpacker.int8
bit_count = unpacker.int8
bits = unpacker.bits(bit_count)
TableRow.new(byte, bits)
end
end
Node = Struct.new(:left, :right, :count)
Leaf = Struct.new(:byte, :count)
TableRow = Struct.new(:byte, :bits)
if ARGV.fetch(0) == "compress"
$stdout.write(compress($stdin.read))
else
$stdout.write(decompress($stdin.read))
end
================================================
FILE: das-0102-data-compressor-from-scratch/imgcat
================================================
#!/bin/bash
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
# only accepts ESC backslash for ST.
function print_osc() {
if [[ $TERM == screen* ]] ; then
printf "\033Ptmux;\033\033]"
else
printf "\033]"
fi
}
# More of the tmux workaround described above.
function print_st() {
if [[ $TERM == screen* ]] ; then
printf "\a\033\\"
else
printf "\a"
fi
}
# print_image filename inline base64contents
# filename: Filename to convey to client
# inline: 0 or 1
# base64contents: Base64-encoded contents
function print_image() {
print_osc
printf '1337;File='
if [[ -n "$1" ]]; then
printf 'name='`echo -n "$1" | base64`";"
fi
if $(base64 --version 2>&1 | grep GNU > /dev/null)
then
BASE64ARG=-d
else
BASE64ARG=-D
fi
echo -n "$3" | base64 $BASE64ARG | wc -c | awk '{printf "size=%d",$1}'
printf ";inline=$2"
printf ":"
echo -n "$3"
print_st
printf '\n'
}
function error() {
echo "ERROR: $*" 1>&2
}
function show_help() {
echo "Usage: imgcat filename ..." 1>& 2
echo " or: cat filename | imgcat" 1>& 2
}
## Main
if [ -t 0 ]; then
has_stdin=f
else
has_stdin=t
fi
# Show help if no arguments and no stdin.
if [ $has_stdin = f -a $# -eq 0 ]; then
show_help
exit
fi
# Look for command line flags.
while [ $# -gt 0 ]; do
case "$1" in
-h|--h|--help)
show_help
exit
;;
-*)
error "Unknown option flag: $1"
show_help
exit 1
;;
*)
if [ -r "$1" ] ; then
print_image "$1" 1 "$(base64 < "$1")"
else
error "imgcat: $1: No such file or directory"
exit 2
fi
;;
esac
shift
done
# Read and print stdin
if [ $has_stdin = t ]; then
print_image "" 1 "$(cat | base64)"
fi
exit 0
================================================
FILE: das-0102-data-compressor-from-scratch/rendertree.rb
================================================
# This file was used in Destroy All Software production 0102, "Data Compressor
# From Scratch". It wasn't shown in the screencast, so it's not designed to be
# as readable as the main code. All of this code is exactly as used in the
# screencast except for:
#
# - New comments (including this one)
# - The call to `imgcat` was changed to refer to the `imgcat` script in this
# directory Previously, it relied on the `imgcat` in my ~/bin directory,
# which is in $PATH.
#
# To see how this file was used to build a data compressor, visit:
#
# https://www.destroyallsoftware.com/screencasts/catalog/data-compressor-from-scratch
require "open3"
# Render a Huffman tree by converting it into Graphviz dot code, then piping
# the dot into the `dot` command line tool, and finally into the `imgcat`
# script. This will only work in recent versions of iTerm 2, or any other
# terminal that supports iTerm 2's PNG rendering escape codes.
def render_tree(nodes)
nodes = [nodes] unless nodes.is_a? Array
dot = [
"digraph {",
"ordering=out",
"dpi=120",
nodes.map do |node|
tree_to_dot(node)
end,
"}"
].flatten.join("\n")
rendered = Open3.popen3("dot -Tpng | ./imgcat") do |stdin, stdout, stderr, wait_thr|
stdin.write(dot)
stdin.close
stdout.read
end
$stderr.puts(rendered)
end
def tree_to_dot(node)
name = "node_#{node.object_id}"
if node.is_a? Node
[
%{#{name}[label="(n=#{node.count})"]},
%{#{name} -> node_#{node.left.object_id}[label="0"]},
%{#{name} -> node_#{node.right.object_id}[label="1"]},
tree_to_dot(node.left),
tree_to_dot(node.right),
].join("\n")
else
[
%{node_#{node.object_id}[label="#{node.byte.chr.gsub(/"/,'\"')}\n(n=#{node.count})"]},
].join("\n")
end
end
================================================
FILE: das-0102-data-compressor-from-scratch/tree.dot
================================================
digraph {
dpi=120
ordering=out;
# abbcccc
# 1 a
# 2 b
# 4 c
a[label="a\n(n=1)"]
b[label="b\n(n=2)"]
c[label="c\n(n=4)"]
n1 [label="(n=3)"]
n1 -> a [label=0]
n1 -> b [label=1]
n2 [label="(n=7)"]
n2 -> n1 [label=0]
n2 -> c [label=1]
}
gitextract_ee0bj18n/
├── das-0010-fast-tests-with-and-without-rails/
│ └── test
├── das-0026-controller-refactoring-demo-part-2/
│ └── account_controller.rb
├── das-0030-some-vim-tips/
│ ├── grb256.vim
│ └── ir_black.vim
├── das-0070-time-to-first-request/
│ └── time_to_first_request.sh
├── das-0094-computing-by-constructing/
│ ├── everything.py
│ └── lambda.py
├── das-0095-power-of-lambda-calculus/
│ ├── everything.py
│ └── lambda.py
└── das-0102-data-compressor-from-scratch/
├── LICENSE
├── README
├── RUNME.sh
├── bin.rb
├── garyzip.rb
├── imgcat
├── rendertree.rb
└── tree.dot
SYMBOL INDEX (54 symbols across 4 files)
FILE: das-0026-controller-refactoring-demo-part-2/account_controller.rb
class AccountController (line 14) | class AccountController < ApplicationController
method login (line 21) | def login
method logout (line 30) | def logout
method lost_password (line 36) | def lost_password
method handle_existing_token (line 45) | def handle_existing_token
method have_valid_token? (line 56) | def have_valid_token?
method reset_password (line 60) | def reset_password
method generate_token (line 72) | def generate_token
method ensure_user_exists (line 82) | def ensure_user_exists(user)
method ensure_no_external_auth (line 91) | def ensure_no_external_auth(user)
method create_new_token (line 100) | def create_new_token(user)
method register (line 111) | def register
method activate (line 147) | def activate
method logout_user (line 163) | def logout_user
method authenticate_user (line 171) | def authenticate_user
method password_authentication (line 179) | def password_authentication
method open_id_authenticate (line 193) | def open_id_authenticate(openid_url)
method successful_authentication (line 234) | def successful_authentication(user)
method set_autologin_cookie (line 245) | def set_autologin_cookie(user)
method onthefly_creation_failed (line 258) | def onthefly_creation_failed(user, auth_source_options = { })
method invalid_credentials (line 264) | def invalid_credentials
method register_by_email_activation (line 272) | def register_by_email_activation(user, &block)
method register_automatically (line 286) | def register_automatically(user, &block)
method register_manually_by_administrator (line 302) | def register_manually_by_administrator(user, &block)
method account_pending (line 312) | def account_pending
FILE: das-0102-data-compressor-from-scratch/bin.rb
class BinPacker (line 10) | class BinPacker
method initialize (line 11) | def initialize
method int32 (line 15) | def int32(int)
method int16 (line 20) | def int16(int)
method int8 (line 25) | def int8(int)
method int (line 30) | def int(int, bit_count)
method bits (line 35) | def bits(bits)
method pack (line 40) | def pack
method flattened_bits (line 44) | def flattened_bits
method debug (line 50) | def debug
method int_to_bits (line 108) | def int_to_bits(int, bit_count)
class BinUnpacker (line 118) | class BinUnpacker
method initialize (line 119) | def initialize(packed)
method int32 (line 123) | def int32
method int16 (line 127) | def int16
method int8 (line 131) | def int8
method bits (line 135) | def bits(count)
method peek (line 141) | def peek(n)
method int (line 145) | def int(bit_count)
FILE: das-0102-data-compressor-from-scratch/garyzip.rb
function compress (line 26) | def compress(original)
function decompress (line 45) | def decompress(compressed)
function build_tree (line 56) | def build_tree(original)
function build_table (line 73) | def build_table(node, path=[])
function look_up_byte (line 82) | def look_up_byte(table, byte)
function look_up_bits (line 96) | def look_up_bits(table, unpacker)
function pack_table (line 107) | def pack_table(table, packer)
function unpack_table (line 116) | def unpack_table(unpacker)
FILE: das-0102-data-compressor-from-scratch/rendertree.rb
function render_tree (line 21) | def render_tree(nodes)
function tree_to_dot (line 40) | def tree_to_dot(node)
Condensed preview — 17 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (44K chars).
[
{
"path": "das-0010-fast-tests-with-and-without-rails/test",
"chars": 976,
"preview": "#!/bin/bash\n#\n# From Destroy All Software screencast #10, at:\n# http://destroyallsoftware.com/screencasts/catalog/fast-t"
},
{
"path": "das-0026-controller-refactoring-demo-part-2/account_controller.rb",
"chars": 9234,
"preview": "#-- copyright\n# ChiliProject is a project management system.\n#\n# Copyright (C) 2010-2011 the ChiliProject Team\n#\n# This "
},
{
"path": "das-0030-some-vim-tips/grb256.vim",
"chars": 1664,
"preview": "\" Based on\nruntime colors/ir_black.vim\n\nlet g:colors_name = \"grb256\"\n\nhi pythonSpaceError ctermbg=red guibg=red\n\nhi Comm"
},
{
"path": "das-0030-some-vim-tips/ir_black.vim",
"chars": 10140,
"preview": "\" ir_black color scheme\n\" More at: http://blog.infinitered.com/entries/show/8\n\n\n\" **************************************"
},
{
"path": "das-0070-time-to-first-request/time_to_first_request.sh",
"chars": 565,
"preview": "#!/bin/bash\n\nmain() {\n print_runtime > /dev/null\n print_runtime\n}\n\nprint_runtime() {\n pid=$(start_server)\n r"
},
{
"path": "das-0094-computing-by-constructing/everything.py",
"chars": 976,
"preview": "#!/usr/bin/env python3\n\nNULL = (\n lambda x: x\n)\n\nTRUE = (\n lambda t: lambda f: t(NULL)\n)\nFALSE = (\n lambda t: l"
},
{
"path": "das-0094-computing-by-constructing/lambda.py",
"chars": 797,
"preview": "#!/usr/bin/env python3\n\nONE = 1\nIS_ZERO = lambda x: x == 0\nSUB1 = lambda x: x - 1\nMULT = lambda x: lambda y: x * y\nIF = "
},
{
"path": "das-0095-power-of-lambda-calculus/everything.py",
"chars": 976,
"preview": "#!/usr/bin/env python3\n\nNULL = (\n lambda x: x\n)\n\nTRUE = (\n lambda t: lambda f: t(NULL)\n)\nFALSE = (\n lambda t: l"
},
{
"path": "das-0095-power-of-lambda-calculus/lambda.py",
"chars": 1493,
"preview": "#!/usr/bin/env python3\n\nprint(\n ( lambda myself: ( lambda n: ( ( lambda cond: lambda t: lambda f: cond(t)(f))( ( lamb"
},
{
"path": "das-0102-data-compressor-from-scratch/LICENSE",
"chars": 1054,
"preview": "Copyright 2017 Gary Bernhardt\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this soft"
},
{
"path": "das-0102-data-compressor-from-scratch/README",
"chars": 1627,
"preview": "These are the files used in Destroy All Software production 0102, \"Data\nCompressor From Scratch\", available at:\n\n htt"
},
{
"path": "das-0102-data-compressor-from-scratch/RUNME.sh",
"chars": 94,
"preview": "#!/usr/bin/env bash\n\nset -e -o pipefail\n\necho -n \"abbcccc\" | ./garyzip.rb compress | hexdump\n\n"
},
{
"path": "das-0102-data-compressor-from-scratch/bin.rb",
"chars": 4124,
"preview": "# This file was used in Destroy All Software production 0102, \"Data Compressor\n# From Scratch\". It wasn't shown in the s"
},
{
"path": "das-0102-data-compressor-from-scratch/garyzip.rb",
"chars": 3039,
"preview": "#!/usr/bin/env ruby\n\n# This file was used in Destroy All Software production 0102, \"Data Compressor\n# From Scratch\". It "
},
{
"path": "das-0102-data-compressor-from-scratch/imgcat",
"chars": 1976,
"preview": "#!/bin/bash\n\n# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;\n# <sequence> ST, and for all ESCs i"
},
{
"path": "das-0102-data-compressor-from-scratch/rendertree.rb",
"chars": 1790,
"preview": "# This file was used in Destroy All Software production 0102, \"Data Compressor\n# From Scratch\". It wasn't shown in the s"
},
{
"path": "das-0102-data-compressor-from-scratch/tree.dot",
"chars": 267,
"preview": "digraph {\n dpi=120\n ordering=out;\n\n # abbcccc\n # 1 a\n # 2 b\n # 4 c\n\n a[label=\"a\\n(n=1)\"]\n b[label=\"b\\n(n=2)\"]\n "
}
]
About this extraction
This page contains the full source code of the garybernhardt/destroy-all-software-extras GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 17 files (39.8 KB), approximately 12.2k tokens, and a symbol index with 54 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.