scite-session 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: efd809ac386914ed6ce5c31d292b843f9bbb0d9e
4
+ data.tar.gz: 5b19a590c94d8863047538eb4a825b7499072160
5
+ SHA512:
6
+ metadata.gz: 4dc744eb71c3bb741348587574a068b7e704bfbd401b1ff568f27e434ba49d9550eef10207abe65fbd023c173f9c5324bd20c0f55a6b36231193e3f495098081
7
+ data.tar.gz: c3d6c856128c6f88798272b93f583fa68f6c9f7ada83621fdba081d460f46fbccf0fe254e681b94df52ed5d2a062a4ce3e273475bc500fa6df636faa1ea59327
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in scite-session.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Sergey Baev, https://github.com/tinbka
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ # SciTE::Session
2
+
3
+ This gem is used to ease a process of starting to work on a new project.
4
+ It handles SciTE sessions using a yaml file with a list of windows needed to pop up on demand. With a command it restores and arranges on a display a project-specific set of SciTE windows setting them custom meta-titles.
5
+ It works only within KDE using `kwin`, `xwininfo` and `wmctrl`.
6
+
7
+ SciTE is a non-popular text editor which I use for several reasons:
8
+ 1. My eyes favor non-monospace fonts.
9
+ 2. Several years ago I made cute lexers with beautiful color scheme for Ruby, CofeeScript, HAML, and Slim.
10
+ 3. It allows to arrange its instances so that I have configs in the first corner, models in the second, controllers in the third and so on. One day it has become mnemonical.
11
+
12
+ I use one Dolphin instance to manage files which allows text editor windows to contain only code not wasting display space.
13
+
14
+ For more info on title template read comment at top of `./bin/kwintag.fish`
15
+
16
+ ## Installation
17
+
18
+ Inside new project dir, so that it would be installed into an according gemset, run
19
+
20
+ $ gem install scite-session
21
+
22
+ ## Usage
23
+
24
+ Suggest there is two windows for project "my-app": one with models and another with controllers.
25
+ Save sessions to `~/scite/my-app/models` and `~/scite/my-app/controllers` accordingly.
26
+ In a console:
27
+
28
+ ```ruby
29
+ require 'scite/session'
30
+ windows = SciTE::Window.find_all
31
+ windows[0].title = 'Models: :title:'
32
+ windows[1].title = 'Controllers: :title:'
33
+ windows[0].session = 'my-app/models'
34
+ windows[1].session = 'my-app/controllers'
35
+ SciTE::Session.save windows, layout: 'my-app'
36
+ ```
37
+
38
+ Now when you run
39
+
40
+ ```ruby
41
+ SciTE::Session.restore layout: 'my-app'
42
+ ```
43
+ or
44
+ ```
45
+ $ scite-session my-app
46
+ ```
47
+
48
+ Those windows will be back on positions.
49
+ You can manually adjust a layout at ~/scite/layouts/my-app.yml
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "scite/session"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env fish
2
+
3
+ # This is a modified version of what can be found at https://unix.stackexchange.com/questions/22561/override-the-window-title-for-an-arbitrary-window-in-kde-and-set-a-custom-window
4
+ # This version implements "meta-title", that is it keeps a custom template for a window, and when a program changes a title for the window, it extracts the title, inserts it into the template and sets a result as an actual title.
5
+ #
6
+ # Usage:
7
+ # $ kwintag
8
+ # then quickly make a window active and in the opened window type a title you want
9
+ # There is a keyword ":title:", it will be substituted with the title a program itself want to set. E.g.
10
+ # suggest you set "Specs: :title:" on an editor window,
11
+ # then an editor tries to reset it to "message_spec.rb * SciTE",
12
+ # then a window title actually becomes "Specs: message_spec.rb *"
13
+ # It handles asterisk as well as regular KDE dashes and long dashes.
14
+
15
+ # this block is so you can use it from the command line with -t and -w
16
+ if test "$argv" != "" -a (math (count $argv)%2 == 0)
17
+ for i in (seq 1 (count $argv))
18
+ if test $argv[$i] = '-t'
19
+ set title_i_want $argv[(math 1 + $i)]
20
+ else if test $argv[$i] = '-w'
21
+ set window_id $argv[(math 1 + $i)]
22
+ end
23
+ end
24
+ if not test $window_id
25
+ echo "YOU DIDN'T ENTER A `window_id` WITH `-w`,
26
+ SO MAKE SURE THE WINDOW YOU WANT HAS FOCUS
27
+ TWO SECONDS FROM NOW!"
28
+ sleep 2
29
+ end
30
+ end
31
+
32
+ # get the id of the currently focused window
33
+ if not test $window_id
34
+ set window_id (xprop -root _NET_ACTIVE_WINDOW | grep -P -o "0x\w+")
35
+ end
36
+
37
+ echo window_id = $window_id
38
+
39
+ # get the title to force on that window
40
+
41
+ if not test $title_i_want
42
+ set title_i_want (kdialog --title "entitled" --inputbox "Type the title you want and hit enter.
43
+ To stop renaming, just enter nothing and hit esc.")
44
+ end
45
+
46
+ # this bit is needed for a kludge that allows window renaming
47
+ set has_renamed_before "FALSE"
48
+ set interrupt_message "WAIT WAIT I WANT A TURN BLOO BLOO BLEE BLUH BLOO" # hopefully i never want to actually use that as a title xD
49
+ xprop -f _NET_WM_NAME 8u -set _NET_WM_NAME $interrupt_message -id $window_id
50
+
51
+ set auto_title ""
52
+ set custom_title ""
53
+ # take the output of xprop
54
+ # pipe it into a while loop
55
+ # everytime it outputs a new line
56
+ # stuff it into a variable named "current_title"
57
+ xprop -spy _NET_WM_NAME -id $window_id | while read current_title
58
+
59
+ # cut off extraneous not-the-title bits of that string
60
+ set current_title (echo $current_title | grep -P -o '(?<=_NET_WM_NAME\(UTF8_STRING\) = ").*(?="\z)')
61
+
62
+ # if the current title is the interrupt message
63
+ # AND
64
+ # this script has renamed the window at least once before
65
+ # then we wanna let the new name take over
66
+ if test $current_title = $interrupt_message -a $has_renamed_before = "TRUE"
67
+ exit
68
+ # if title_i_want is an empty string, exit
69
+ else if test $title_i_want = ""
70
+ xprop -f _NET_WM_NAME 8u -set _NET_WM_NAME "WIDNOW WILL START RENAMING ITSELF AS NORMAL" -id $window_id
71
+ exit
72
+ # otherwise just change the title to what i want
73
+ else if test $current_title != $custom_title
74
+ set auto_title (echo $current_title | sed -re 's| \* ([—\-] )?| * - |')
75
+ echo auto title: $auto_title
76
+ set auto_title_short (echo $auto_title | grep -P -o '.*?(?= [—\-] )')
77
+ echo auto title short: $auto_title_short
78
+ echo title i want: $title_i_want
79
+ set custom_title (echo $title_i_want | sed -e "s|:title:|$auto_title_short|")
80
+ echo custom title: $custom_title
81
+ echo $current_title != $custom_title
82
+ xprop -f _NET_WM_NAME 8u -set _NET_WM_NAME "$custom_title" -id $window_id
83
+ set has_renamed_before "TRUE"
84
+ end
85
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'scite/session'
3
+ SciTE::Session.restore layout: ARGV[0]
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,44 @@
1
+ # Basic implementation of an animation. Could be used anywhere.
2
+ # Optimized to not do anything when it is too late to display a frame.
3
+ module Animation
4
+ class << self
5
+
6
+ def swing_easing(part)
7
+ 0.5 - Math.cos(part * Math::PI)/2
8
+ end
9
+
10
+ def perform(initial_values, target_values, frames: 40, duration: 400.0, &interpolation)
11
+ keys = initial_values.merge(target_values).keys
12
+ values_diff = keys.map_hash {|k| [k, target_values[k].to_f - initial_values[k].to_f]}
13
+
14
+ initial_time = Time.now.to_f
15
+ duration_ms = duration.to_f / 1000
16
+ frame_count = frames
17
+ wait_count = frames - 1
18
+
19
+ 1.upto(frame_count) {|frame_i|
20
+ if frame_i != frame_count
21
+ now = Time.now.to_f
22
+ this_must_be_run_at = initial_time + duration_ms/wait_count * (frame_i - 1)
23
+ next_must_be_run_at = initial_time + duration_ms/wait_count * frame_i
24
+ next if now > this_must_be_run_at + 0.001
25
+ end
26
+
27
+ frame_values = keys.map_hash {|k|
28
+ time_part = frame_i.to_f / frame_count
29
+ [k, initial_values[k] + values_diff[k] * swing_easing(time_part)]
30
+ }
31
+ #$log << frame_values
32
+ yield frame_values
33
+
34
+ if frame_i != frame_count
35
+ now = Time.now.to_f
36
+ if now < next_must_be_run_at
37
+ sleep next_must_be_run_at - now
38
+ end
39
+ end
40
+ }
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,58 @@
1
+ require "scite/session/version"
2
+ require "rmtools"
3
+ require "scite/animation"
4
+ require "scite/window"
5
+
6
+ module SciTE
7
+
8
+ class << self
9
+
10
+ def run(params={})
11
+ sh_pid = Process.spawn "scite #{params.map {|k, v| "-#{k}:\"#{v}\""}*' '} 1>/dev/null 2>/dev/null", pgroup: 0
12
+ pid = `pgrep -P #{sh_pid}`.chomp
13
+ #$log << pid
14
+ pid
15
+ end
16
+
17
+ def set_title(wid, title)
18
+ Process.spawn "#{File.dirname(__FILE__)}/../../bin/kwintag.fish -t '#{title}' -w #{wid} 1>/dev/null 2>/dev/null", pgroup: 0
19
+ end
20
+
21
+ end
22
+
23
+ # Save and restore a SciTE sessions layout.
24
+ module Session
25
+ mattr_accessor :home, :layouts_home
26
+ self.home = "#{ENV['HOME']}/scite"
27
+ self.layouts_home = "#{home}/layouts"
28
+
29
+ class << self
30
+
31
+ def save(windows, layout:)
32
+ File.write "#{layouts_home}/#{layout}.yml", windows.map {|win|
33
+ {session: win.session, title: win.title, move_to: win.position}
34
+ }.to_yaml
35
+ end
36
+
37
+ def restore(windows: nil, layout: nil)
38
+ if layout
39
+ windows ||= YAML.load read "#{layouts_home}/#{layout}.yml"
40
+ end
41
+
42
+ windows.map! {|params|
43
+ if params.is Window
44
+ params
45
+ else
46
+ Window.new params
47
+ end
48
+ }
49
+ windows.each {|w|
50
+ w.create
51
+ sleep 0.1
52
+ }
53
+ windows.each &:wait
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ module SciTE
2
+ module Session
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,109 @@
1
+ module KDE
2
+
3
+ # Basic operations over windows in KDE.
4
+ class Window
5
+ class_attribute :header_height, :border_width
6
+ self.header_height = 23
7
+ self.border_width = 2
8
+
9
+ attr_reader :title, :position, :pid
10
+ attr_writer :title
11
+
12
+ def self.find(title: nil)
13
+ if title
14
+ if info = `wmctrl -l -p`[/^(0x\w+) +-?\d+ (\d+) .+ #{title}$/]
15
+ new title: title, pid: $2.to_i, wid: $1
16
+ end
17
+ end
18
+ end
19
+
20
+ def initialize(title: nil, pid: nil, wid: nil)
21
+ @title, @pid, @wid = title, pid, wid
22
+ @threads = []
23
+ end
24
+
25
+ def wait
26
+ @threads.joins
27
+ @threads = []
28
+ self
29
+ end
30
+
31
+ def wid
32
+ @wid ||= `wmctrl -l -p | grep " #@pid "`[/0x\w+/]
33
+ end
34
+
35
+ def position
36
+ @position ||= begin
37
+ shape = `xwininfo -id #{wid} -shape`.lines
38
+ dimms = shape.grep(/-geometry/)[0].match(/(?<w>\d+)x(?<h>\d+)/)
39
+ corner = shape.grep(/Corner/)[0].match(/\+(?<x>-?\d+)\+(?<y>-?\d+)/)
40
+ {w: dimms[:w].to_i, h: dimms[:h].to_i,
41
+ x: corner[:x].to_i - border_width, y: corner[:y].to_i - header_height}
42
+ end
43
+ end
44
+
45
+ def position=(coords)
46
+ coords = coords.map_hash {|k, v| [k, v.to_i]}
47
+ if @position != coords
48
+ @position = coords
49
+ `wmctrl -i -r #{wid} -e 0,#{coords[:x]},#{coords[:y]},#{coords[:w]},#{coords[:h]}`
50
+ end
51
+ end
52
+
53
+ def move(frames: 20, duration: 400.0, **coords)
54
+ coords.reverse_merge! position
55
+ #$log << [position, coords, {frames: frames, duration: duration}]
56
+ Animation.perform(position, coords, frames: frames, duration: duration) {|coords|
57
+ self.position = coords
58
+ }
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ module SciTE
66
+
67
+ # SciTE-specific operations over windows in KDE.
68
+ class Window < KDE::Window
69
+ attr_reader :session, :move_to
70
+ attr_writer :session
71
+
72
+ def self.find_all
73
+ `wmctrl -l -p`.split("\n").map {|line|
74
+ if line[/^(0x\w+) +-?\d+ (\d+) +\S+ +(.+ [-*] SciTE)$/]
75
+ new(title: $3, pid: $2.to_i, wid: $1)
76
+ end
77
+ }.compact
78
+ end
79
+
80
+ def initialize(title: nil, pid: nil, wid: nil, session: nil, move_to: nil)
81
+ @session, @move_to = session, move_to
82
+ super title: title, pid: pid, wid: wid
83
+ end
84
+
85
+ def create(&oncreate)
86
+ @pid ||= SciTE.run loadsession: "#{SciTE::Session.home}/#@session"
87
+ @threads << Thread.new {
88
+ sleep 0.2
89
+ self.position = {w: 50, h: 20, x: 2550, y: -40}
90
+ sleep 3 # даём вкладкам прогрузиться
91
+ move if @move_to
92
+ set_title if @title
93
+ yield self if block_given?
94
+ }
95
+ self
96
+ end
97
+
98
+ def move(frames: 20, duration: 400.0, **coords)
99
+ coords.reverse_merge! @move_to if @move_to
100
+ super
101
+ end
102
+
103
+ def set_title
104
+ SciTE.set_title wid, @title
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'scite/session/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "scite-session"
8
+ spec.version = SciTE::Session::VERSION
9
+ spec.authors = ["Sergey Baev"]
10
+
11
+ spec.summary = "Restores and arranges multiple SciTE sessions within KDE"
12
+ spec.homepage = "https://github.com/tinbka/" + spec.name
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.require_paths = ["lib"]
16
+ spec.bindir = "bin"
17
+ spec.executables = ["scite-session"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.10"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+
22
+ spec.add_dependency "rmtools", "~> 2.5.0"
23
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scite-session
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sergey Baev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rmtools
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.5.0
55
+ description:
56
+ email:
57
+ executables:
58
+ - scite-session
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/kwintag.fish
70
+ - bin/scite-session
71
+ - bin/setup
72
+ - lib/scite/animation.rb
73
+ - lib/scite/session.rb
74
+ - lib/scite/session/version.rb
75
+ - lib/scite/window.rb
76
+ - scite-session.gemspec
77
+ homepage: https://github.com/tinbka/scite-session
78
+ licenses: []
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.4.8
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Restores and arranges multiple SciTE sessions within KDE
100
+ test_files: []